JavaSE@拓展补遗@笔记13@反射新讲

一、反射的概念

JAVA反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意方法和属性;

这种动态获取信息以及动态调用对象方法的功能称为java语言的反射机制。

二、获取字节码对象的三种方式

  1. 使用类名调用.class属性(.class不是只有类能调用)
  2. 使用一个类的对象调用.getClass()方法
  3. 使用Class类的静态方法forName("类全名")
/获取字节码对象的三种方式
​
//1.使用类名调用.class属性(.class不是只有类能调用)
Class c1 = String.class;
​
//2.使用一个类的对象调用.getClass()方法
Class c2 = "abd".getClass();
​
//3.使用Class类的静态方法forName("类全名")
Class c3 = Class.forName("java.lang.String");
​
System.out.println(c1 == c2);//true
System.out.println(c2 == c3);//true

三、反射操作构造方法

1、反射获取构造方法

Class类的方法:

  • getConstructor(Class... c) 可以获取某一个构造方法(公共的)

  • getConstructors() 可以获取所有的构造方法(公共的)

反射执行构造方法​

import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
​
public class Test02 {
    public static void main(String[] args) throws Exception{
        //获取类的字节码对象
        Class c = Class.forName("com.itheima_02.Student");
​
        //- getConstructors()  可以获取所有的构造方法(公共的)
        //获取学生类的所有公共构造方法
        //Constructor[] cons = c.getConstructors();
        //遍历数组
        //for (Constructor con : cons) {
        //    System.out.println(con);
        //}
​
        //- getConstructor(Class... c) 可以获取某一个构造方法(公共的)
        //获取空参构造
        Constructor con1 = c.getConstructor();
        //获取有参构造
        Constructor con2 = c.getConstructor(String.class,int.class);
​
​
        //newInstance(Object... obj) : 执行当前构造方法创建对象。
        //使用空参构造创建对象
        Object o1 = con1.newInstance();
        System.out.println(o1);
        //o1就是一个空参创建的学生对象,显示的是父类Object,可以向下转型
​
        //使用有参构造创建对象
        Object o2 = con2.newInstance("石原里美",28);
        System.out.println(o2);
​
        //上面的反射和下面的创建对象功能一模一样,为什么要反射呢?一会说。
        //Student stu = new Student("石原里美",28);
    }
}

Constructor类的方法:

  • newInstance(Object... obj) : 执行当前构造方法创建对象。

    Object... obj 表示的是创建对象时的实际参数。

四、反射操作成员方法

1、反射获取成员方法

Class类的方法:

getMethod(String name, Class... c) :获取一个成员方法(公共的)

String name 表示方法名称

Class... c 表示的是方法的参数的类型

getMethods() : 获取类中的所有方法(公共的)

反射执行成员方法

import java.lang.reflect.Method;
​
public class Test04 {
    public static void main(String[] args) throws Exception{
        //反射获取成员方法并执行
        //获取类的字节码对象
        Class c = Class.forName("com.itheima_02.Student");
        //- getMethods() : 获取类中的所有方法(公共的)
        //Method[] ms = c.getMethods();
        //遍历数组
        //for (Method m : ms) {
        //   System.out.println(m);
        //}
        //- getMethod(String name, Class... c) :获取一个成员方法(公共的)
        //获取睡觉方法
        Method m1 = c.getMethod("sleep");
        //获取吃饭方法
        Method m2 = c.getMethod("eat", String.class);
​
        //Object  invoke(Object obj , Object... o)  :让方法执行
        //第一个参数是对象,第二个参数是方法的实际参数,返回值是方法的实际返回值
​
        //创建对象
        Student s = new Student("石原里美",28);
​
        // 返回值 =  s.sleep(参数);
        //执行睡觉方法
        m1.invoke(s);
​
        //执行吃饭方法
        m2.invoke(s, "汉堡");
​
        //需求:通过反射调用toString()
        //获取方法
        Method m3 = c.getMethod("toString");
        //执行方法
        Object o3 = m3.invoke(s);
        System.out.println("o3是toString方法的返回值" + o3);
​
        //上面的三行代码相当于
        //String s3 = s.toString();
        //System.out.println(s3);
        //为什么要反射?一会说。
    }
}

Method类的方法:

Object invoke(Object obj , Object... o) :让方法执行

第一个参数表示执行的对象

第二个参数表示方法的实际参数

返回值表示方法的实际返回值

五、暴力反射

反射正常情况下遵从java权限修饰的规则。

如果使用暴力反射就可以打破权限修饰符的规则。

写法: 在所有的获取方法之间加declared词就可以了,然后调用setAccessable(true)就表示可以访问了。

暴力反射一般不要用。

import java.lang.reflect.Constructor;
public class Test03 {
    public static void main(String[] args) throws Exception{
        //获取类的字节码对象
        Class c = Class.forName("com.itheima_02.Student");
        //获取有参构造
        Constructor con2 = c.getDeclaredConstructor(String.class,int.class);
        //设置可以访问
        con2.setAccessible(true);
​
        //使用有参构造创建对象
        Object o2 = con2.newInstance("石原里美",28);
        System.out.println(o2);
    }
}

六、反射操作成员变量【了解】

import java.lang.reflect.Field;
public class Test05 {
    public static void main(String[] args) throws Exception{
        //获取字节码对象
        Class c = Class.forName("com.itheima_02.Student");
​
        //获取成员变量
        //变量是私有的所以不能这么获取
        //Field f1 = c.getField("age");
        //System.out.println(f1);
        //如果获取需要暴力反射
        Field f2 = c.getDeclaredField("age");
        System.out.println(f2);
        //类中的成员变量因为遵从面向对象的语法,都会使用private修饰
        //不让在外界直接使用
    }
}

七、反射的作用案例演示

反射是框架的灵魂。

反射代码虽然复杂,但是可以配合配置文件,代码不需要修改,把灵活修改的部分放在配置文件中。

 

1、案例演示

配置文件

className=com.itheima_03.Cat
methodName=sleep

代码

import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.lang.reflect.Constructor;
import java.lang.reflect.Method;
import java.util.Properties;
​
public class Test02使用反射 {
    public static void main(String[] args) throws Exception {
        //Properties配置文件
        Properties prop = new Properties();
        //读取文件的键值对
        prop.load(new FileReader("day14\\abc.properties"));
​
        //根据键获取值
        String cn = prop.getProperty("className");
        String mn = prop.getProperty("methodName");
​
        //System.out.println(cn);  //com.itheima_03.Dog
        //System.out.println(mn);  //eat
        
        //反射获取字节码对象
        Class c = Class.forName(cn);
        //字节码获取构造方法
        Constructor con = c.getConstructor();
        //创建对象
        Object o = con.newInstance();  //o其实是一个子类对象
​
        //获取方法
        Method m = c.getMethod(mn);
        //执行方法
        m.invoke(o);
    }
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值