java中的反射

主要介绍以下几方面内容

  • 理解 Class 类
  • 理解 Java 的类加载机制
  • 学会使用 ClassLoader 进行类加载
  • 理解反射的机制
  • 掌握 Constructor、Method、Field 类的用法
  • 理解并掌握动态代理

1.理解Class类

  –对象照镜子后可以得到的信息:某个类的数据成员名、方法和构造器、某个类到底实现了哪些接口。对于每个类而言,JRE 都为其保留一个不变的 Class 类型的对象。一个 Class 对象包含了特定某个类的有关信息。
  –Class 对象只能由系统建立对象
  –一个类在 JVM 中只会有一个Class实例
  –每个类的实例都会记得自己是由哪个 Class 实例所生成
      1: Class是什么?
      Class是一个类:
java中的反射
public class ReflectionTest {
    @Test
    public void testClass() {
       Class clazz = null;
    }
}


//Class的定义
public final
    class Class<T> implements java.io.Serializable,
                              java.lang.reflect.GenericDeclaration,
                              java.lang.reflect.Type,
                              java.lang.reflect.AnnotatedElement {

.....
.....
.....
}
//小写class表示是一个类类型,大写Class表示这个类的名称
java中的反射

      2:Class这个类封装了什么信息?

  Class是一个类,封装了当前对象所对应的类的信息
   一个类中有属性,方法,构造器等,比如说有一个Person类,一个Order类,一个Book类,这些都是不同的类,现在需要一个类,用来描述类,这就是Class,它应该有类名,属性,方法,构造器等。Class是用来描述类的类

  Class类是一个对象照镜子的结果,对象可以看到自己有哪些属性,方法,构造器,实现了哪些接口等等

      3.对于每个类而言,JRE 都为其保留一个不变的 Class 类型的对象。一个 Class 对象包含了特定某个类的有关信息。
    4.Class 对象只能由系统建立对象,一个类(而不是一个对象)在 JVM 中只会有一个Class实例

java中的反射
package com.atguigu.java.fanshe;

public class Person {
    String name;
    private int age;
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public int getAge() {
        return age;
    }
    public void setAge(int age) {
        this.age = age;
    }
    
    //包含一个带参的构造器和一个不带参的构造器
    public Person(String name, int age) {
        super();
        this.name = name;
        this.age = age;
    }
    public Person() {
        super();
    }

}
定义一个Person类

      通过Class类获取类对象

java中的反射
public class ReflectionTest {
    @Test
    public void testClass() {
       Class clazz = null;
       
       //1.得到Class对象
       clazz = Person.class;
       
       System.out.println();  //插入断点
    }
}
java中的反射

  在断点处就可以看到Class对像包含的信息
java中的反射

  同样,这些属性值是可以获取的

java中的反射
public class ReflectionTest {
    @Test
    public void testClass() {
       Class clazz = null;
       
       //1.得到Class对象
       clazz = Person.class;
       //2.返回字段的数组
       Field[] fields = clazz.getDeclaredFields();
       
       System.out.println();  //插入断点
    }
}
java中的反射

   查看fields的内容

java中的反射

  对象为什么需要照镜子呢?

    1. 有可能这个对象是别人传过来的

    2. 有可能没有对象,只有一个全类名 

  通过反射,可以得到这个类里面的信息

获取Class对象的三种方式

  1.通过类名获取      类名.class    

  2.通过对象获取      对象名.getClass()

  3.通过全类名获取    Class.forName(全类名)

java中的反射
public class ReflectionTest {
    @Test
    public void testClass() throws ClassNotFoundException {
       Class clazz = null;
       
       //1.通过类名
       clazz = Person.class;
       

//2.通过对象名 //这种方式是用在传进来一个对象,却不知道对象类型的时候使用 Person person = new Person(); clazz = person.getClass(); //上面这个例子的意义不大,因为已经知道person类型是Person类,再这样写就没有必要了 //如果传进来是一个Object类,这种做法就是应该的 Object obj = new Person(); clazz = obj.getClass();
//3.通过全类名(会抛出异常) //一般框架开发中这种用的比较多,因为配置文件中一般配的都是全类名,通过这种方式可以得到Class实例 String className=" com.atguigu.java.fanshe.Person"; clazz = Class.forName(className);

//字符串的例子 clazz = String.class; clazz = "javaTest".getClass(); clazz = Class.forName("java.lang.String"); System.out.println(); } }
java中的反射

 

Class类的常用方法

方法名

功能说明

static Class forName(String name)

返回指定类名 name 的 Class 对象

Object newInstance()

调用缺省构造函数,返回该Class对象的一个实例

Object newInstance(Object []args)

调用当前格式构造函数,返回该Class对象的一个实例

getName()

返回此Class对象所表示的实体(类、接口、数组类、基本类型或void)名称

Class getSuperClass()

返回当前Class对象的父类的Class对象

Class [] getInterfaces()

获取当前Class对象的接口

ClassLoader getClassLoader()

返回该类的类加载器

Class getSuperclass()

返回表示此Class所表示的实体的超类的Class

 

  Class类的newInstance()方法

java中的反射
    public void testNewInstance() throws ClassNotFoundException, InstantiationException, IllegalAccessException{
        //1.获取Class对象
        String className="com.atguigu.java.fanshe.Person";
        Class clazz = Class.forName(className);  
        
        //利用Class对象的newInstance方法创建一个类的实例
        Object obj =  clazz.newInstance();
        System.out.println(obj);
    }
    //结果是:com.atguigu.java.fanshe.Person@2866bb78
    
java中的反射

  可以看出确实是创建了一个Person实例
  但是Person类有两个构造方法,到底是调用的哪一个构造方法呢

  实际调用的是类的无参数的构造器。所以在我们在定义一个类的时候,定义一个有参数的构造器,作用是对属性进行初始化,还要写一个无参数的构造器,作用就是反射时候用。

  一般地、一个类若声明一个带参的构造器,同时要声明一个无参数的构造器

ClassLoader

   类装载器是用来把类(class)装载进 JVM 的。JVM 规范定义了两种类型的类装载器:启动类装载器(bootstrap)和用户自定义装载器(user-defined class loader)。 JVM在运行时会产生3个类加载器组成的初始化加载器层次结构 ,如下图所示:

java中的反射

 

java中的反射
public class ReflectionTest {
    @Test
    public void testClassLoader() throws ClassNotFoundException, FileNotFoundException{
        //1. 获取一个系统的类加载器(可以获取,当前这个类PeflectTest就是它加载的)
        ClassLoader classLoader = ClassLoader.getSystemClassLoader();
        System.out.println(classLoader);
        

//2. 获取系统类加载器的父类加载器(扩展类加载器,可以获取). classLoader = classLoader.getParent(); System.out.println(classLoader);
//3. 获取扩展类加载器的父类加载器(引导类加载器,不可获取). classLoader = classLoader.getParent(); System.out.println(classLoader);
//4. 测试当前类由哪个类加载器进行加载(系统类加载器): classLoader = Class.forName("com.atguigu.java.fanshe.ReflectionTest") .getClassLoader(); System.out.println(classLoader);
//5. 测试 JDK 提供的 Object 类由哪个类加载器负责加载(引导类) classLoader = Class.forName("java.lang.Object") .getClassLoader(); System.out.println(classLoader); } } //结果: //sun.misc.Launcher$AppClassLoader@5ffdfb42 //sun.misc.Launcher$ExtClassLoader@1b7adb4a //null //sun.misc.Launcher$AppClassLoader@5ffdfb42 //null
java中的反射

 

  使用类加载器获取当前类目录下的文件

java中的反射

  首先,系统类加载器可以加载当前项目src目录下面的所有类,如果文件也放在src下面,也可以用类加载器来加载

  调用 getResourceAsStream 获取类路径下的文件对应的输入流.

java中的反射

 

java中的反射
、public class ReflectionTest {
    @Test
    public void testClassLoader() throws FileNotFoundException{
        //src目录下,直接加载
        InputStream in1 = null;
        in1 = this.getClass().getClassLoader().getResourceAsStream("test1.txt");
        
        //放在内部文件夹,要写全路径
        InputStream in2 = null;
        in2 = this.getClass().getClassLoader().getResourceAsStream("com/atguigu/java/fanshe/test2.txt");
    }
}
java中的反射


 

java中的反射

上一篇:WNDR3700V4 安装SVN Server


下一篇:Netty 框架学习 —— 预置的 ChannelHandler 和编解码器