Java反射整理总结

1.类的加载

java源码--编译-->java字节码--类的加载-->JVM
当字节码文件加载到内存之后,JVM会为它创建一个Class对象(字节码文件的对象)   

2.类的加载时机

类的字节码文件什么时候会被加载???
a.创建类的实例。
b.访问类的静态变量
c.调用类的静态方法
d.使用反射方式来强制加载某个类
e.使用到了该类的子类,也会导致该类被加载
f.直接使用java.exe命令运行某个测试类(含有main方法的类)
总而言之:
    类的字节码文件什么时候会被加载,当我们用到该类或者该类的子类时!

3.类加载器的作用和分类

类加载器(ClassLoader),将字节码文件加载到JVM的内存中
类加载器的分类:
    根类加载器(引导类加载器): 用于加载系统类库(比如:%JAVA_HOME%\bin下的这些类)
    扩展类加载器: 用于加载扩展类库(比如:库<JAVA_HOME>\lib\ext目录下的类)
    应用类加载器: 用于加载我们自定义类的加载器. 

4.双亲委派机制

双亲委派机制的作用

1、防止重复加载同一个.class。通过委托去向上面问一问,加载过了,就不用再加载一遍。保证数据安全。
2、保证核心.class不能被篡改。通过委托方式,不会去篡改核心.clas,即使篡改也不会去加载,即使加载也不会是同一个.class对象了。不同的加载器加载同一个.class也不是同一个Class对象。这样保证了Class执行安全。
双亲委派模型工作工程:
  1.当Application ClassLoader 收到一个类加载请求时,他首先不会自己去尝试加载这个类,而是将这个请求委派给父类加载器Extension ClassLoader去完成。  
  2.当Extension ClassLoader收到一个类加载请求时,他首先也不会自己去尝试加载这个类,而是将请求委派给父类加载器Bootstrap ClassLoader去完成。  
  3.如果Bootstrap ClassLoader加载失败(在<JAVA_HOME>\lib中未找到所需类),就会让Extension ClassLoader尝试加载。  
  4.如果Extension ClassLoader也加载失败,就会使用Application ClassLoader加载。  
  5.如果Application ClassLoader也加载失败,就会使用CustomClassLoader(用户自定义类加载器)去尝试加载。  
6.如果均加载失败,就会抛出ClassNotFoundException异常。
//1
Class clas = Dog.class;
System.out.println(clas);
//2
Dog dog = new Dog();
System.out.println(dog.getClass());
//3
Class aClass = Class.forName("day26_classLoader.Dog");
System.out.println(aClass);

反射中万物皆对象:
    一个成员方法  --> Method类型对象
    一个成员变量  --> Field类型对象
    一个构造方法  --> Constructor类型对象

2个常见的单词:
    newInstance: 创建对象
    invoke: 执行方法/调用方法
反射的语法:
    创建对象:
        正常语法: 类名 对象名 = new 构造方法(参数);
        反射语法: 类名 对象名 = 构造方法对象.newInstance();
    调用方法:
        正常语法: 对象名.方法(参数);
        反射语法: 方法对象.invoke(对象名,参数);
setAccessible(true)想要调用私有构造或方法必须设置此参数
获取反射类的构造
构造方法:
public Constructor<T> getConstructor(Class<?>... parameterTypes) 获取public修饰, 指定参数类型所对应的构造方法 public Constructor<T> getDeclaredConstructor(Class<?>... parameterTypes) 获取指定参数类型所对应的构造方法(包含私有的) public Constructor<?>[] getConstructors() 获取所有的public 修饰的构造方法 public Constructor<?>[] getDeclaredConstructors() 获取所有的构造方法(包含私有的)
根据构造不同的参数区分获取
Class<Dog> dogClass = Dog.class; Constructor<Dog> constructor = dogClass.getConstructor(); Constructor<Dog> constructorName = dogClass.getConstructor(String.class); Constructor<Dog> constructor1 = dogClass.getDeclaredConstructor(String.class,int.class);
//如果构造方法是非public,那么我们需要调用getDeclaredConstructor获取 Constructor con = cc.getDeclaredConstructor(String.class);
//如果是私有构造,那么必须先设置暴力访问权限 con.setAccessible(true); Object con = con4.newInstance("旺财");
获取反射类的成员
返回一个成员变量
public Field getField(String name) 获取指定的 public修饰的变量public Field getDeclaredField(String name) 获取指定的任意变量 返回多个成员变量 public Field[] getFields() 获取所有public 修饰的变量 public Field[] getDeclaredFields() 获取所有的 变量 (包含私有) public void set(Object obj, Object value)在指定对象obj中,将此 Field 对象表示的成员变量设置为指定的新值
public Object get(Object obj)返回指定对象obj中,此 Field 对象表示的成员变量的值
//成员变量
Class<Dog> dogClass = Dog.class;
Field field = dogClass.getField("towname");
System.out.println(field.get(dogClass.newInstance()));
Field name = dogClass.getDeclaredField("name");
//必须暴力获取私有
name.setAccessible(true);
System.out.println(name.get(dogClass.newInstance()));
//获取所有成员变量
Field[] fields = dogClass.getFields();
System.out.println(Arrays.toString(fields));

 

获取成员方法:
返回获取一个方法:
public Method getMethod(String name, Class<?>... parameterTypes)获取public 修饰的方法
public Method getDeclaredMethod(String name, Class<?>... parameterTypes)获取任意的方法,包含私有的
参数1: name 要查找的方法名称; 参数2: parameterTypes 该方法的参数类型
返回获取多个方法:
public Method[] getMethods() 获取本类与父类中所有public 修饰的方法
public Method[] getDeclaredMethods() 获取本类中所有的方法(包含私有的)
Class<Dog> dogClass = Dog.class;
Method method = dogClass.getMethod("drink");
Method eat = dogClass.getMethod("eat", String.class);
Method eat1 = dogClass.getMethod("eat");
Dog dog = dogClass.newInstance();
//调用invoke
method.invoke(dog);
eat.invoke(dog,"😀");
eat1.invoke(dog);
//获取私有
Method declaredMethod = dogClass.getDeclaredMethod("testD", String.class);
declaredMethod.setAccessible(true);
declaredMethod.invoke(dog,"xiao");
成员变量:
    返回一个成员变量
    public Field getField(String name) 获取指定的 public修饰的变量
    Field ageField = c.getField("age");
    public Field getDeclaredField(String name) 获取指定的任意变量
    Field addressField = c.getDeclaredField("address");

    返回多个成员变量
    public Field[] getFields() 获取所有public 修饰的变量
  Field[] fields = c.getFields();
   //遍历
   public Field[] getDeclaredFields() 获取所有的 变量 (包含私有)
   Field[] fields =  c.getDeclaredFields();
   for (Field field : fields) {
        System.out.println(field);
   }
                        
  public void set(Object obj, Object value)
   在指定对象obj中,将此 Field 对象表示的成员变量设置为指定的新值
   nameField.set(obj, 23)
                        
   public Object get(Object obj)
   返回指定对象obj中,此 Field 对象表示的成员变量的值
   nameField.get(obj)
   nameField,nameField都是通过getField()获得的对象

 



                        

posted @ 2019-03-28 14:12  一半人生  阅读(179)  评论(0编辑  收藏  举报