反射

反射

​ 反射是Java被称作"准动态语言的关键",反射机制允许程序在执行期取得任何类的内部信息,并且可以直接操作任意对象的内部属性和方法。

在类加载完毕后,方法区中就产生了一个Class类型的队形(一个类只有一个Class对象),这个对象包含了该类的完整的结构信息。我们可以通过这个Class对象看到这个类的结构。

这个对象就像一面镜子,透过这个镜子看到类的结构,所以, 我们形象的称之为:反射

反射主要也就是在学习Class对象

反射的优缺点

优点:可以动态编译,很灵活

缺点:对性能有影响,使用反射是一种解释操作。我肯可以高速jvm,我们希望做什么并且它满足我们的要求。这类操作总是慢于执行相同的操作

Class类

在Object类中定义了以下的方法

public final Class getClass()

该方法可以返回调用对象的Class类。

我们得到Class对象后可以得到某个类完整的结构,包括属性、方法、构造器等。

获取Class类的实例的方法

1.若已知具体的类,通过类的class属性获取,该方法最为安全可靠,程序性能最高。

2.已知某个类的实例,调用该实例的getClass()方法获取Class对象

  1. 已知一个类的全类名,且该类在类路径下,可通过Class类的静态方法forName()获取, 可能抛出ClassNotFoundException

    public class MyTest {
        public static void main(String[] args) throws ClassNotFoundException {
            MyClassTest myClassTest = new MyClassTest();
    
            System.out.println("正常方法创建对象---------");
    
            //获取Class对象的方法
            Class class1 = MyClassTest.class;//已知具体的类,通过类的class属性获取,该方法最为安全可靠,程序性能最高。
    
            Class class2 = myClassTest.getClass();// 已知某个类的实例,调用该实例的getClass()方法获取Class对象
    
            Class class3 = Class.forName("F:\\java\\demo\\反射\\src\\org\\westos\\demo\\MyTest.java");// 已知一个类的全类名,且该类在类路径下,可通过Class类的静态方法forName()获取,
        }
    }
    class MyClassTest{
    
    }
    
获取运行时类的完整结构
public class MyTest2 {

    public static void main(String[] args) throws NoSuchFieldException, NoSuchMethodException {
        //正常创建两个MyClassTest2对象
        MyClassTest2 big = new MyClassTest2("大张", 15);
        MyClassTest2 small = new MyClassTest2("小张", 5);

        //获得Class对象
        Class class1 = MyClassTest2.class;

        //利用Class对象获得MyClassTest2类的所有信息



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

        Field[] fields = class1.getFields();//获得所有public属性
        Field name = class1.getDeclaredField("name");//获得指定属性
        Field[] fields2 =class1.getDeclaredFields();//获得所有的属性


        System.out.println("============================");
        Constructor[] constructors = class1.getConstructors();//获得所有public构造器
        Constructor[] constructors2 = class1.getDeclaredConstructors();//获得所有构造器
        class1.getDeclaredConstructor(String.class,int.class);//获得指定构造器.因为构造器存在重载,获得指定构造器需要添加参数.参数为构造器的参数类型的class类型


        System.out.println("============================");
        Method[] methods = class1.getMethods();//返回当前类和被继承的类的public方法
        Method[] declaredMethods = class1.getDeclaredMethods(); //获得当前类的所有方法
        Method setName = class1.getDeclaredMethod("setName", String.class);//获得指定的方法.同上述构造方法一样.因为存在函数重载.所以需要添加方法名和方法的参数类型的class类型
    }
}

class MyClassTest2 {
    String name;
    int age;

    public MyClassTest2() {
    }

    MyClassTest2(String name, int age) {
        this.name = name;
        this.age = 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;
    }
}
利用Class对象操纵该类
public class MyTest3 {

    public static void main(String[] args) throws NoSuchFieldException, NoSuchMethodException, IllegalAccessException, InstantiationException, InvocationTargetException {
        //正常创建两个MyClassTest3对象
        MyClassTest3 big = new MyClassTest3("大张", 15);
        MyClassTest3 small = new MyClassTest3("小张", 5);


        Class class1 = MyClassTest3.class;

        Constructor constructor = class1.getDeclaredConstructor(String.class,int.class);
        Field name = class1.getDeclaredField("name");

        Method setName = class1.getMethod("setName", String.class);
        //演示通过Class对象来对类进行操作

        //1.演示创建对象
        //1.1通过类的newInstance()方法创建对象
        MyClassTest3 myClassTest3 = (MyClassTest3) class1.newInstance();
        myClassTest3.setAge(15);
        System.out.println(myClassTest3.getAge());
        //1.2通过类的构造器创建对象
        MyClassTest3 myClassTest31  = (MyClassTest3)constructor.newInstance("张晓", 38);
        System.out.println(myClassTest31.getName());

        //2.通过Class类来修改属性
        System.out.println(big.getName());
        name.set(big,"张三");
        System.out.println(big.getName());//此处通过类成功的修改了对象big的属性.注意.因为一个类可以创建多个对象.所以在修改属性时需要添加参数.明确你想要修改的是哪一个对象的属性
        
        
        //3.通过Class类来调用方法
        setName.invoke(big,"张四");
        System.out.println(big.getName());//此处通过invoke再次绕过了对象调用了该类的方法.修改了big的name属性.
 
    }
}

class MyClassTest3 {
    String name="LALAL";
    int age=0;

    public MyClassTest3() {
    }

    MyClassTest3(String name, int age) {
        this.name = name;
        this.age = 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;
    }

注意:在使用反射操作时。显示调用setAccessible为true,则可以访问private方法!所以会对程序的安全性造成极大的破坏。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值