Java学习:反射

类加载器
(1)什么是类的加载
当程序要使用某个类时,如果该类还未被加载到内存中,则系统会通过加载,连接,
初始化三步来实现对这个类进行初始化。

一个类在加载过程中的三部曲:
1.加载
就是指将class文件读入内存,并为之创建一个Class对象.
任何类被使用时系统都会建立一个Class对象。

2.连接
验证 是否有正确的内部结构,并和其他类协调一致
准备 负责为类的静态成员分配内存,并设置默认初始化值
解析 将类的二进制数据中的符号引用替换为直接引用

3.初始化 就是我们以前讲过的初始化步骤

(2)类的加载时机
2.1 创建类的实例
2.2 访问类的静态变量,或者为静态变量赋值
2.3 调用类的静态方法
2.4 使用反射方式来强制创建某个类或接口对应的java.lang.Class对象
2.5 初始化某个类的子类
2.6 直接使用java.exe命令来运行某个主类

(3)加载器分类
3.1 类加载起的作用?
负责将.class文件加载到内在中,并为之生成对应的Class对象。

3.2 类加载器的分类
Bootstrap ClassLoader 根类加载器
也被称为引导类加载器,负责Java核心类的加载
比如System,String等。在JDK中JRE的lib目录下rt.jar文件中

Extension ClassLoader 扩展类加载器
负责JRE的扩展目录中jar包的加载。
在JDK中JRE的lib目录下ext目录

Sysetm ClassLoader 系统类加载器
负责在JVM启动时加载来自java命令的class文件

反射
Student.java--Student.class(字节码文件)--看成一个对象,这个对象就叫字节码文件对象--对应的类Class
什么是反射?(画图描述)
答:通过字节码文件对象去使用成员。

(1)获取字节码文件对象的三种方式:
A:Object类的getClass()方法
B:数据类型的静态class属性
C:Class类的静态方法forName()
注意:
在平常写案例的时候,我们直接使用第二种最方便。
但是实际开发中,我们一般用的都是第三种。是因为第三种接收的是一个字符串类型的参数,
我们可以把这个参数作为配置文件的内容进行配置,这样就实现了一个变化的内容。

 1 public static void main(String[] args) throws ClassNotFoundException {
 2         //获取Person类对应的Class字节码文件对象
 3         //A:Object类的getClass()方法
 4         Person p1 = new Person();
 5         Person p2 = new Person();
 6
 7         Class c1 = p1.getClass();
 8         Class c2 = p2.getClass();
 9         System.out.println(p1==p2);//false
10         System.out.println(c1==c2);//true
11         //每一个类会对应一个字节码文件对象,而这个字节码文件对象就是这个类的原型,每一个类有且仅有一个字节码文件对象
12
13         System.out.println("-------------");
14         //B:数据类型的静态class属性
15         Class c3 = Person.class;
16         System.out.println(c2==c3);
17
18         System.out.println("---------------");
19         //C:Class类的静态方法forName()
20         //public static Class<?> forName(String className),在这里所说的类名是全类名(带包名的类名)
21         //Class c4 = Class.forName("Person");//java.lang.ClassNotFoundException: Person
22         Class c4 = Class.forName("com.edu_01.Person");
23         System.out.println(c3==c4);
24     }

获取字节码文件的三种方式

(2)反射的使用步骤
Class:
成员变量 Field
构造方法 Constructor
成员方法 Method

反射:
class字节码文件对象 -- 去得到对应的成员对象 -- 通过该成员的对象调用方法使用

通过反射获取构造方法并使用

(3)案例:
1.通过反射获取构造方法
public Constructor[] getConstructors() 获取公共的构造方法
public Constructor[] getDeclaredConstructors() 获取所有的构造方法(包括私有)
public Constructor getConstructor(Class... parameterTypes) 根据构造参数获取公共的指定构造
public Constructor getDeclaredConstructor(Class<?>... parameterTypes) 根据构造参数获取指定构造(包括私有,但是私有在使用的时候需要取消访问限制)

2.通过反射获取构造方法并创建对象
public T newInstance(Object... initargs)

public static void main(String[] args) throws Exception {
        //public Constructor[] getConstructors() 获取公共的构造方法
        //获取Peroson类对应的字节码文件对象
        Class c = Class.forName("com.edu_01.Person");

        //获取Perosn类中对应的构造方法
        Constructor[] cons = c.getConstructors();
        //遍历所有获取到的构造方法
        for (Constructor con : cons) {
            System.out.println(con);//public com.edu_01.Person()
        }

        System.out.println("----------------");
        //public Constructor[] getDeclaredConstructors() 获取所有的构造方法(包括私有)
        Constructor[] cons2 = c.getDeclaredConstructors();
        for (Constructor con : cons2) {
            System.out.println(con);
        }

        System.out.println("---------------");
        //public Constructor getConstructor(Class... parameterTypes) 根据构造参数获取公共的指定构造
        //获取Person类中的公共的无参数的构造方法
        Constructor con  = c.getConstructor();
        System.out.println(con);
        //怎么通过我们刚才获取的无参构造创建对象
        //public T newInstance(Object... initargs)
        Object obj = con.newInstance();
        System.out.println(obj);

        System.out.println("-------------");
        //获取Person类中的非公共的构造方法
        //public Constructor<T> getDeclaredConstructor(Class<?>... parameterTypes)
        Constructor con2 = c.getDeclaredConstructor(String.class,int.class,String.class);
        //获取构造器的时候,传入的什么参数,在调用获取到的这个构造方法对象的时候也就需要传入什么类型的参数
        //取消这个构造器对象所对应的访问权限检测
        con2.setAccessible(true);
        Object obj2 = con2.newInstance("陈奕迅",45,"香港");
        System.out.println(obj2);

        System.out.println("-----------");

        //获取被Protected修饰的构造方法
        Constructor con3 = c.getDeclaredConstructor(String.class,int.class);
        //取消访问权限的检测
        con3.setAccessible(true);
        Object obj3 = con3.newInstance("张学友",50);
        System.out.println(obj3);

    }

案例1和2

3.通过反射获取成员变量并使用
public Field[] getFields()获取公有的成员变量
public Field[] getDeclaredFields()获取全部的成员变量,包括私有
public Field getDeclaredField(String name) 传入变量名称返回指定的成员变量对象,包括私有
public Field getField(String name)传入变量名称返回指定的成员变量对象,仅可获取共有的
public void set(Object obj,Object value)给一个对象的一个字段设置一个值

 1 public static void main(String[] args) throws Exception {
 2         //获取Perosn类对应的字节码文件对象
 3         Class c = Class.forName("com.edu_01.Person");
 4
 5         //利用反射获取一个[Perosn对象
 6         Constructor con = c.getConstructor();
 7         Object obj = con.newInstance();
 8
 9         //获取所有公共的字段对象
10         //public Field[] getFields()获取公有的成员变量
11         Field[] fields = c.getFields();
12         for (Field field : fields) {
13             System.out.println(field);
14         }
15
16         System.out.println("--------------");
17         //获取所有的字段对象,包括私有
18         //public Field[] getDeclaredFields()获取全部的成员变量,包括私有
19         Field[] fields2 = c.getDeclaredFields();
20         for (Field field : fields2) {
21             System.out.println(field);
22         }
23
24         System.out.println("--------------");
25         //public Field getDeclaredField(String name) 传入变量名称返回指定的成员变量对象,包括私有
26         //获取String name;字段
27         Field f = c.getDeclaredField("name");
28
29         //使用f这个对象给一个Perosn对象设置姓名
30         //public void set(Object obj, Object value)
31         /**
32          * 参数1:需要设置的对象
33          * 参数2:需要给这个对象设置什么值
34          */
35         //取消访问修饰符的限制
36         f.setAccessible(true);
37         f.set(obj, "谢娜");
38
39
40         System.out.println("--------------");
41         //public Field getField(String name)传入变量名称返回指定的成员变量对象,仅可获取公有的
42         //获取public int age;
43         Field f2 = c.getField("age");
44         f2.set(obj, 30);
45
46         System.out.println("---------------");
47         Field f3 = c.getDeclaredField("address");
48         //取消权限检测
49         f3.setAccessible(true);
50         f3.set(obj, "湖南");
51
52         System.out.println(obj);
53
54
55     }

案例三

4.通过反射获取成员方法并使用
public Method[] getMethods()获取所有公共成员方法
public Method[] getDeclaredMethods()获取所有成员方法,包括私有
public Method getMethod(String name, Class<?>... parameterTypes)参数一:方法名 参数二:方法参数类型.class 获取指定的公共方法
public Method getDeclaredMethod(String name,Class<?>... parameterTypes)参数一:方法名 参数二:方法参数类型.class 获取指定的方法,包括私有
Object invoke(Object obj, Object... args) 让某一个对象使用这个方法,并且传入参数

 1 public static void main(String[] args) throws Exception {
 2         //1.获取Person类中所有的公有的成员方法
 3         //创建Pwrson类对应的字节码文件对象
 4         Class c = Class.forName("com.edu_01.Person");
 5
 6         //利用反射的方式创建一个Person对象
 7         Constructor con  = c.getConstructor();
 8         Object obj = con.newInstance();
 9
10         //public Method[] getMethods()获取所有公共成员方法,包括父类的公共的成员方法
11         Method[] methods = c.getMethods();
12         for (Method method : methods) {
13             System.out.println(method);
14         }
15
16         System.out.println("---------------");
17         //获取Person类中的所有的成员方法
18         //public Method[] getDeclaredMethods()获取所有成员方法,包括私有,只能获取本类的所有的成员方法,不能获取父类的
19         Method[] methods2 = c.getDeclaredMethods();
20         for (Method method : methods2) {
21             System.out.println(method);
22         }
23
24         System.out.println("---------------");
25         // public Method getMethod(String name, Class<?>... parameterTypes)
26         //参数一:方法名 参数二:方法参数类型.class 获取指定的公共方法
27         //获取method()这个公有的成员方法
28         Method m  = c.getMethod("method");
29         System.out.println(m);
30
31         System.out.println("---------------");
32         //public Method getDeclaredMethod(String name,Class<?>... parameterTypes)
33         //参数一:方法名 参数二:方法参数类型.class 获取指定的方法,包括私有
34         //需求获取method这个个方法
35         Method m2 = c.getDeclaredMethod("method");
36         System.out.println(m2);
37
38         //使用m2这个成员方法的对象
39         //public Object invoke(Object obj,Object... args)
40         /**
41          * 参数1:执行m2这个方法的对象
42          * 参数2:执行m2这个方法的时候,需要传入的参数
43          */
44         m2.invoke(obj);
45
46         System.out.println("-----------------");
47         //获取Person类中function方法
48         Method m3 = c.getDeclaredMethod("function", int.class);
49         //取消权限检测
50         m3.setAccessible(true);
51         m3.invoke(obj, 10);
52
53         System.out.println("-------------------");
54         Method m4 = c.getDeclaredMethod("show", String.class,String.class);
55         m4.setAccessible(true);
56         m4.invoke(obj, "张杰","谢娜");
57
58     }

案例四

时间: 2024-11-05 19:41:08

Java学习:反射的相关文章

java学习----反射

目录 1.什么是反射 2.反射的运用 3.总结   一.什么是反射 反射:反射是指计算机程序在运行时(Run time)可以访问.检测和修改它本身状态或行为的一种能力   ----by  维基百科 java中的反射也是如此,利用反射的原理我们可以在程序运行时候的能够动态的创建对象,并且调用对象的方法和属性 它的作用是:1.在运行时判断任意一个对象类型 2.在运行时候能够构造任意一个对象 3.在运行时候判断一个类的属性和方法 反射在实际开发中的运用主要是在编写第三方jar包中比较多.我们可以运用反

Java学习-反射机制入门

1.反射机制 我们在正常的使用过程之中只关心类产生对象,而后通过对象调用类之中的方法,可是,除了这种传统的方式外,也可以利用反射操作. 1.1.认识反射 既然有反,那么一定存在有正,正是指通过类产生对象,而后通过对象执行操作.而反呢?通过对象找到它所在类的信息.所有的对象都支持反这一操作,因为Object类有一个方法:public final Class<?> getClass(). 1 package cn.kvikon.demo; 2 import java.util.Date; 3 4

java学习——反射机制

/* * JAVA反射机制是在运行状态中,对于任意一个类 (class文件),都能够知道这个类的所有属性和方法: * 对于任意一个对象,都能够调用它的任意一个方法和属性: * 这种动态获取的信息以及动态调用对象的方法的功能称为java语言的反射机制. * * 动态获取类中信息,就是java反射 . * 可以理解为对类的解剖. * * 要想要对字节码文件进行解剖,必须要有字节码文件对象. * 如何获取字节码文件对象呢? * */ 1. 通过Class clazz =Class.forName()找

JAVA学习--反射之动态代理模式

1 import java.lang.reflect.InvocationHandler; 2 import java.lang.reflect.Method; 3 import java.lang.reflect.Proxy; 4 5 //动态代理的使用,体会反射是动态语言的关键 6 interface Subject { 7 void action(); 8 } 9 10 // 被代理类 11 class RealSubject implements Subject { 12 public

JAVA学习--反射属性操作

1 //获取对应的运行时类的属性 2 @Test 3 public void test1(){ 4 Class clazz = Person.class; 5 //1.getFields():只能获取到运行时类中及其父类中声明为public的属性 6 Field[] fields = clazz.getFields(); 7 8 for(int i = 0;i < fields.length;i++){ 9 System.out.println(fields[i]); 10 } 11 Syste

JAVA学习--反射构造器操作

1 @Test 2 public void test1() throws Exception{ 3 String className = "com.atguigu.java.Person"; 4 Class clazz = Class.forName(className); 5 //创建对应的运行时类的对象.使用newInstance(),实际上就是调用了运行时类的空参的构造器. 6 //要想能够创建成功:①要求对应的运行时类要有空参的构造器.②构造器的权限修饰符的权限要足够. 7 O

JAVA学习--反射其他操作

1 //1.获取运行时类的父类 2 @Test 3 public void test1(){ 4 Class clazz = Person.class; 5 Class superClass = clazz.getSuperclass(); 6 System.out.println(superClass); 7 } 1 //2.获取带泛型的父类 2 @Test 3 public void test2(){ 4 Class clazz = Person.class; 5 Type type1 =

JAVA学习--反射方法操作

1 //1.获取运行时类的方法 2 3 @Test 4 public void test1(){ 5 Class clazz = Person.class; 6 //1.getMethods():获取运行时类及其父类中所有的声明为public的方法 7 Method[] m1 = clazz.getMethods(); 8 for(Method m : m1){ 9 System.out.println(m); 10 } 11 System.out.println(); 12 13 //2.ge

JAVA学习--反射之静态代理模式

1 //静态代理模式 2 //接口 3 interface ClothFactory{ 4 void productCloth(); 5 } 6 //被代理类 7 class NikeClothFactory implements ClothFactory{ 8 9 @Override 10 public void productCloth() { 11 System.out.println("Nike工厂生产一批衣服"); 12 } 13 } 14 //代理类 15 class Pr

java中反射学习整理

转载请注明:http://blog.csdn.net/j903829182/article/details/38405735 反射主要是指程序可以访问,检测和修改它本身的状态或行为的一种能力. java中反射是一种强大的工具,它能够创建灵活的代码,这些代码可以在运行时装载,无须在组件之间进行链接.反射允许在编写与执行时,使程序能够接入到jvm中的类的内部信息,而不是源代码中选定的类协作的代码.这使反射成为构建灵活应用代码的主要工具.需要注意的是,如果使用不当,反射的成本会很高. package