Java反射知识整理

一、Class类

Class 类的实例表示正在运行的 Java 应用程序中的类和接口。

也就是说类或接口是java.lang.Class类的实例对象。

二、获取Class类的实例对象

public class ReflectDemo1 {

    public static void main(String[] args){
        //获取Class类的实例对象的方式一
        Class c1 = MyClass.class;

        //获取Class类的实例对象的方式二
        MyClass mc = new MyClass();
        Class c2 = mc.getClass();

        //获取Class类的实例对象的方式三
        try {
            Class c3 = Class.forName("com.xiao.reflect.MyClass");
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
    }
}
class MyClass{

}

c1、c2、c3称之为MyClass类的类类型,一个类只可能是Class类的一个实例对象,所以它们相等。

System.out.println(c1 == c2);

打印结果为true。

三、通过类的类类型创建该类的对象

public class ReflectDemo1 {

    public static void main(String[] args){
        //获取Class类的实例对象的方式一
        Class c1 = MyClass.class;

        //获取Class类的实例对象的方式二
        MyClass mc = new MyClass();
        Class c2 = mc.getClass();

        //获取Class类的实例对象的方式三
        Class c3 = null;
        try {
            c3 = Class.forName("com.xiao.reflect.MyClass");
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }

        //通过类类型(c1 or c2 or c3) 创建该类的对象
        try {
            MyClass myClass = (MyClass)c1.newInstance();//需要无参构造方法


            myClass.show();
        } catch (InstantiationException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        }
    }
}
class MyClass{
    public void show(){
        System.out.println("MyClass");
    }
}

四、动态加载类

编译时刻加载类,是静态加载类;运行时刻加载类,是动态加载类。

Class.forName(“类的全路径”)不仅表示类该类的类类型,还表示了动态加载该类。

五、类的加载

当Java虚拟机要运行某个类时,如果该类还未被加载到内存当中,虚拟机则会通过加载,连接,初始化这三个步骤实现对这个类的

初始化。

加载:指将class文件读入内存。并创建一个Class对象。任何类被使用时,虚拟机都会建立一个Class对象。

连接:验证是否具有正确的内部结构,并和其它类协调一致,准备负责为类的静态成员分配内存,并设置默认初始化值。

初始化:创建对象。

六、类的初始化时机

1.创建类的实例

2.使用类的静态成员或对其赋值(或调用静态方法)

3.使用反射方式来强制创建某个类或接口对应的Class对象

4.初始化某个子类(它的父类全部都要先于子类初始化)

5.直接使用java.exe命令来运行某个主类

七、类加载器

负责将.class文件加载到内存当中,并生成对应的Class对象。

三种类的加载器:

1.Bootstrap ClassLoader 根类加载器 也称为引导类加载器,负责Java核心类的加载。

2.Extension ClassLoader 扩展类加载器。

3.System    ClassLoader 系统类加载器。

八、反射

Java反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意一个方法和属性;这种动态获取的信息以及动态调用对象的方法的功能称为Java语言的反射机制。

九、反射获取构造方法

public class ReflectDemo2 {

    //反射获取构造方法
    @Test
    public void test_1() throws  Exception{
        //获取Person类的类类型
        Class c = Person.class;
        //获取构造方法
//        p.getConstructors(); 获得权限为public的所有构造器
        //获得指定的空参构造器
        Constructor con1 = c.getConstructor();
        //获得指定的有参构造器
        Constructor con2 = c.getConstructor(String.class);
        //运行空参构造
        Person p1  = (Person) con1.newInstance();
        //运行有参构造
        Person p2  = (Person) con2.newInstance("笑笑");
    }

}
class Person{

    private String name;

    //空参构造
    public  Person(){
        System.out.println("我是Person类的空参构造");
    }
    //有参构造
    public Person(String name) {
        this.name = name;
        System.out.println("我是Person类的有参构造");
    }
}

十、反射获取成员变量

public class ReflectDemo3 {

    //反射获取成员变量
    @Test
    public void test() throws Exception{

        //获取Cart类的类类型
        Class c = Class.forName("com.xiao.reflect.Cart");
        //获取所有public的成员变量
        c.getFields();
        //获取所有成员变量 包括private
        c.getDeclaredFields();
        //获取指定的私有成员变量
        c.getDeclaredField("name");
        //获得指定的public的成员变量
        Field field = c.getField("color");
        //通过Cart的类类型 创建该类对象
        Cart cart = (Cart) c.newInstance();
        //修改指定的成员变量的值
        field.set(cart,"yellow");
    }
}
class Cart{

    //私有成员变量
    private String name;

    //共有成员变量
    public String color;
}

十一、反射获取成员方法

public class ReflectDemo4 {
    
    //反射获取成员方法
    @Test
    public void test() throws  Exception{
        //获取Dog类的类型
        Class c = Dog.class;
        //获取所有public的成员方法,包括继承的
        c.getMethods();
        //获得指定的空参成员方法
        Method say = c.getMethod("say");
        //获得指定的有参成员方法
        Method eat = c.getMethod("eat", String.class);
        //使用Gog类的类类型创建其对象
        Dog dog = (Dog)c.newInstance();
        //运行空参成员方法
        say.invoke(dog);
        //运行有参成员方法
        eat.invoke(dog,"骨头");
    }
}
class Dog{
    //空参成员方法
    public  void say(){
        System.out.println("汪汪汪");
    }
    //有参成员方法
    public void eat(String food){
        System.out.println("吃"+food);
    }
}

十二、泛型擦除

在Java中,编译后的字节码文件中是没有泛型的。

例:加了String类型的泛型的集合,添加整型的数据。

//伪泛型
@Test
public void test_2() throws Exception{
    //创建了添加了String类型的泛型的集合
    ArrayList<String> array = new ArrayList<>();
    //获取集合ArrayList类的类类型
    Class c = array.getClass();
    //获取方法add
    Method method = c.getMethod("add",Object.class);
    //添加整形数据
    method.invoke(array, 12);
    method.invoke(array, 1222);
    method.invoke(array, 1000);
    System.out.println(array);
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值