Java 反射机制详解(一)

Java 反射机制详解(一)

主要介绍以下几方面内容

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

 1.Class类

通过Class类可以得到的信息某个类的数据成员名、方法和构造器、某个类到底实现了哪些接口等,对于每个类而言,JRE 都为其保留一个不变的 Class 类型的对象,一个 Class 对象包含了特定某个类的有关信息,Class 对象只能由系统建立对象 ,一个类在 JVM 中只会有一个Class实例,每个类的实例都会记得自己是由哪个 Class 实例所生成。

1.1 Class是什么? 

答: Class是一个类

1.2 Class类封装了什么信息?

答:封装了当前对象所对应的类的信息,包含类中的属性,方法,构造器等

例如: 有一个Person类,一个Order类,一个Book类,这些都是不同的类,现在需要一个类,用来描述这些类,这就是Class类,它应该有类名,属性,方法,构造器等。Class是用来描述类的类 Class类是一个对象照镜子的结果,对象可以看到自己有哪些属性,方法,构造器,实现了哪些接口等等

定义Person类: 

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();
    }

 通过Class类获取类对象:

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

 在断点处就可以看到Class对像包含的信息:

 

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

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

fields的内容如下:

 

 1.3 为什么需要Class类对象?

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

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

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

1.4 如何获取Class对象? 

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

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

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

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(); 
    }
}

 1.5 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()方法 : 

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

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

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

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

原文链接:https://www.cnblogs.com/tech-bird/p/3525336.html

猜你喜欢

转载自blog.csdn.net/nioqnw/article/details/84585262
今日推荐