java反射章节笔记,带源码!!!

反射

1、反射的引入

根据配置文件re.properties指定信息,创建Cat对象并调用方法hi

re.properties配置文件内容如下:

classfullpath=reflection_.test.Cat

method=hi

反射引入:

public void f1(){
    //传统方式是直接new一个对象,然后调用该方法(但是有时只有一个配置文件,不看文件是不知道调用什么方法,并且配置文件一更改就需要修改源代码了)
    //所以这时我们就需要用反射来解决这样的问题
    
    //1、使用properties类,可以读写配置文件
    Properties properties = new Properties();
    properties.load(new FileInputStream("src\\re.properties"));
    String classfullpath = properties.get("classfullpath").toString();//reflection_.test.Cat
    String methodName = properties.get("method").toString();//hi
    //2、创建对象,传统的方法行不通->反射机制 
    //new classfullpath()
    
    //3、使用反射机制解决问题
    //(1)加载类,返回Class类型对象cls
    Class cls = Class.forName(classfullpath);
    //(2)通过cls得到你加载的类reflection_.test.Cat的对象实例
    Object o = cls.newInstance();
    //(3)通过 cls 得到你加载的类 com.hspedu.Cat 的 methodName"hi" 的方法对象,即在反射中,可以把方法视为对象(万物皆可对象)
    Method method1 = cls.getMethod(methodName);
    //(4) 通过 method1 调用方法: 即通过方法对象来实现调用方法
    method1.invoke(o); //传统方法 对象.方法() , 反射机制 方法.invoke(对象)
}

2、反射机制

(1)Java Reflection

1.反射机制允许程序在执行期借助于Reflection API取得任何类的内部信息(比如成员变量,构造器,成员方法等等),并能操作对象的属性及方法。反射在设计模式和框架都会用到!!!

2.记载完类之后,在堆中就产生了一个Class类型的对象(一个类只有一个Class对象),这个对象包含了类的完整结构信息。通过这个对象得到类的结构。这个Class对象就像是一面镜子,透过这个镜子看到类的结构,所以形象的称之为:反射。

p对象–>类型Person类。

Class对象 cls–>类型Class类

(2)Java反射机制原理示意图!!!

在这里插入图片描述

(3)Java反射机制可以完成

  1. 在运行时判断任意一个对象所属的类
  2. 在运行时构造任意一个类的对象
  3. 在运行时得到任意一个类所具有的成员变量和方法
  4. 在运行时调用任意一个对象的成员变量和方法
  5. 生成动态代理

(4)反射相关的主要类

在这里插入图片描述

案例演示:

public class Reflection01 {
    public static void main(String[] args) throws IOException, ClassNotFoundException, NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException, NoSuchFieldException {
        //使用Properties类,可以读写配置文件
        Properties properties = new Properties();
        properties.load(new FileInputStream("src\\re.properties"));
        String classfullpath = properties.get("classfullpath").toString();
        String methodName = properties.get("method").toString();
        //传统方法就是要创建对象了,但是读取到的路径是一个字符串不知能直接new,所以现有的只是是完不成这样的功能的
        //下面就会用到反射机制来解决这个问题

        //反射----->优点:可以在不修改源码的前提下,调用方法(只需要修改配置文件即可)
        //1、加载类
        Class cls = Class.forName(classfullpath);
        //2、通过cls得到你加载的类的对象实例
        Object object = cls.getDeclaredConstructor().newInstance();
        System.out.println(object.getClass());//class reflection_.test.Cat
        //3、通过cls得到你记载的类的methodName (“hi”)的方法对象
        //即在反射中,可以把方法视为对象(万物皆为对象)
        Method method = cls.getMethod(methodName);
        //4、通过method来调用方法,即通过方法对象来实现调用方法
        method.invoke(object);//在传统方法:对象.方法     在反射机制:方法对象.invoke(对象)

        //java.lang.reflect.Field: 代表类的成员变量, Field 对象表示某个类的成员变量
        //得到 name 字段
        //getField不能得到私有的属性
        Field nameFiled = cls.getField("age");
        System.out.println(nameFiled.get(object));//传统写法 对象.成员变量 , 反射 : 成员变量对象.get(对象)

        //java.lang.reflect.Constructor: 代表类的构造方法, Constructor 对象表示构造器
        Constructor constructor = cls.getConstructor();
        System.out.println(constructor);

        Constructor constructor1 = cls.getConstructor(String.class);//这里传入的String.class就是String类的Class对象
        System.out.println(constructor1);
    }
}

(5)反射的优点和缺点

优点:可以动态的创建和使用对象(也是框架的底层核心),使用灵活,没有反射机制,框架技术就失去了底层支撑。

缺点:使用反射基本是解释执行,对执行速度有影响

下面我将会对用反射和不用反射对相同功能进行时间消耗测试:

传统方法:

public static void m1(){    //传统方法
    Cat cat = new Cat();
    long start=System.currentTimeMillis();
    for (int i = 0; i < 9000000; i++) {
        cat.hi();
    }
    long end=System.currentTimeMillis();
    System.out.println("m1()耗时="+(end-start));
}

反射方法:

public static void m2() throws ClassNotFoundException, InstantiationException, IllegalAccessException, NoSuchMethodException, InvocationTargetException {    //反射方法
    Class cls = Class.forName("reflection_.test.Cat");
    Object o = cls.newInstance();
    Method method = cls.getMethod("hi");
    long start=System.currentTimeMillis();
    for (int i = 0; i <  9000000; i++) {
        method.invoke(o);
    }
    long end=System.currentTimeMillis();
    System.out.println("m2()耗时="+(end-start));
}

反射优化(关闭访问检测):

public static void m3() throws ClassNotFoundException, InstantiationException, IllegalAccessException, NoSuchMethodException, InvocationTargetException {
    Class cls = Class.forName("reflection_.test.Cat");
    Object o = cls.newInstance();
    Method method = cls.getMethod("hi");
    method.setAccessible(true);//true为取消访问检测
    long start=System.currentTimeMillis();
    for (int i = 0; i <  9000000; i++) {
        method.invoke(o);
    }
    long end=System.currentTimeMillis();
    System.out.println("m3()耗时="+(end-start));
}

在这里插入图片描述

(6)反射调用优化-关闭访问检查

  1. Method和Field、Constructor对象都有setAccessible()方法
  2. setAccessible()方法的作用时启动和禁用访问安全检查的开关
  3. 参数值为true表示反射的对象在使用时取消访问检查,提高反射的效率。参数值为false则表示反射的对象执行访问检查。

3、Class类

(1)基本介绍

在这里插入图片描述

  1. Class也是类,因此也继承Object类
  2. Class类对象不是new出来的,而是系统创建的
  3. 对于某个类的Class类对象,在内存中只有一份,因为类只加载一次
  4. 每个类的实例都会记得自己是由哪个Class实例所生成的
  5. 通过Class对象可以完整地得到一个类的完整结构,通过一系列API
  6. Class对象是存放在堆的
  7. 类的字节码二进制数据,是放在方法区的,有的地方成为类的元数据(包括方法代码,变量名,方法名,访问权限等等)
public class Class01 {
    public static void main(String[] args) throws ClassNotFoundException {
        //Class类对象不是new出来的,而是系统创建的
        //(1)传统new对象
        /* ClassLoader 类
            public Class<?> loadClass(String name) throws ClassNotFoundException {
                return loadClass(name, false);
            }
        */
//        Cat cat = new Cat();//Debug追溯源码
        //(2)反射方式
        /*
            ClassLoader 类, 仍然是通过 ClassLoader 类加载 Cat 类的 Class 对象
            public Class<?> loadClass(String name) throws ClassNotFoundException {
                return loadClass(name, false);
            }
        */
        Class cls1 = Class.forName("reflection_.test.Cat");

        //3. 对于某个类的 Class 类对象,在内存中只有一份,因为类只加载一次
        Class cls2 = Class.forName("reflection_.test.Cat");
        System.out.println(cls1.hashCode());
        System.out.println(cls2.hashCode());//可以看出两个的hashCode()值一样
        Class cls3 = Class.forName("reflection_.test.Dog");
        System.out.println(cls3.hashCode());
    }
}

(2)Class类的常用方法

在这里插入图片描述

(3)应用实例

public class Class02 {
    public static void main(String[] args) throws ClassNotFoundException, InstantiationException, IllegalAccessException, NoSuchFieldException {
        String classAllPath="reflection_.test.Car";
        //1、获取到Car类对应的Class类
        //<?>表示不确定的Java类型
        Class<?> cls = Class.forName(classAllPath);
        //2、输出cls
        System.out.println(cls);
        System.out.println(cls.getClass());//输出cls的运行类型 java.lang.Class
        //3、得到包名
        System.out.println(cls.getPackage().getName());//reflection_.test
        //4、得到全类名
        System.out.println(cls.getName());//reflection_.test.Car
        //5、通过cls创建对象实例
        Object object = cls.newInstance();
        System.out.println(object);
        //6、通过反射获取属性
        Field brand = cls.getField("brand");
        System.out.println(brand.get(object));
        //7、通过反射给属性赋值
        brand.set(object,"问界m9智驾版");
        System.out.println(brand.get(object));
        //8、得到所有属性(字段)
        Field[] fields = cls.getFields();
        for (Field f :fields) {
            System.out.println(f.getName());//名称
        }
    }
}

(4)获取Class类对象

  1. 前提:已知一个类的全类名,且该类在类路径下,可通过Class类的静态方法forName()获取,可能会抛出ClassNotFoundException,(应用场景:多用于配置文件,读取类全路径,加载类)
  2. 前提:若已知具体的类,通过类的Class获取,该方式最为安全可靠,程序性能最高(应用场景:多用于参数传递,比如通过反射得到对应构造器对象)
  3. 前提:已知某个类的实例,调用该实例的getClass()方法获取Class对象(应用场景:通过创建好的对象,获取Class对象)
  4. 其他方式,通过类加载器(4种)来获取类的Class对象。先得到类加载器car->通过类加载器得到Class对象
  5. 基本数据(int,char,boolean,float,double,byte,long,short)按如下方式得到Class类对象。Class cls=基本数据类型.class
  6. 基本数据类型对应包装类,可以通过.TYPE得到Class类对象 Class cls=包装类.TYPE
public class GetClass_ {    //获取Class对象的方法
    public static void main(String[] args) throws ClassNotFoundException {
        //1、forName()
        String classAllPath="reflection_.test.Car";//通过读取配置文件获取
        Class<?> cls = Class.forName(classAllPath);
        System.out.println(cls);

        //2、类名.Class -> 多用于参数传递
        Class cls2= Car.class;
        System.out.println(cls2);

        //3、对象.getClass()->应用场景:有对象实例
        Car car = new Car();
        Class cls3 = car.getClass();
        System.out.println(cls3);

        //4、通过类加载器(4种)来获取类的Class对象
        //(1)先得到类加载器car
        ClassLoader classLoader = car.getClass().getClassLoader();
        //(2)通过类加载器得到Class对象
        Class cls4 = classLoader.loadClass(classAllPath);
        System.out.println(cls4);
        //cls、cls2、cls3、cls4是同一个对象
        System.out.println(cls==cls2&&cls==cls3&&cls==cls4);
        //5、基本数据类型(int,char,boolean,float,double,byte,long,short)按如下方式获取Class类对象
        Class<Integer> integerClass = int.class;
        Class<Character> characterClass = char.class;
        System.out.println(integerClass);//int

        //6、基本数据类型对应的包装类,可以通过.TYPE来得到Class类对象
        Class<Integer> type = Integer.TYPE;
        Class<Character> type1 = Character.TYPE;
        System.out.println(type);//int
        System.out.println(type1);//char

        System.out.println(integerClass.hashCode());
        System.out.println(type.hashCode());//他们两个的hashCode值是相同的
    }
}

(5)哪些类型有Class对象

在这里插入图片描述

应用实例:

public class AllTypeClass {     //有Class对象的类型
    public static void main(String[] args) {
        Class<String> cls1 = String.class;//外部类
        Class<Serializable> cls2 = Serializable.class;//接口
        Class<Integer[]> cls3 = Integer[].class;//数组
        Class<float[][]> cls4 = float[][].class;//二维数组
        Class<Deprecated> cls5 = Deprecated.class;//注解
        Class<Thread.State> cls6 = Thread.State.class;//枚举
        Class<Long> cls7 = long.class;//基本数据类型
        Class<Void> cls8 = void.class;//void数据类型
        Class<Class> cls9 = Class.class;

        System.out.println(cls1);
        System.out.println(cls2);
        System.out.println(cls3);
        System.out.println(cls4);
        System.out.println(cls5);
        System.out.println(cls6);
        System.out.println(cls7);
        System.out.println(cls8);
        System.out.println(cls9);
    }
}

(6)类加载

1>基本说明

反射机制是Java实现动态语言的关键,也就是通过反射实现类动态加载。

1、静态加载:编译时加载相关类,如果没有则报错,依赖性太强。

2、动态加载:运行时加载需要的类,如果运行时不用该类,即使不存在该类,则不报错,降低了依赖性

2>类加载时机

1、当创建对象是(new)//静态记载

2、当子类被加载时,父类也被加载//静态加载

3、调用类中的静态成员时//静态加载

4、通过反射//动态加载

3>类加载过程图

在这里插入图片描述

4>类加载各阶段完成任务

在这里插入图片描述

5>加载阶段(Loading)

在这里插入图片描述

6>连接阶段-验证
  1. 目的是为了确保Class文件的字节流中包含的信息符合当前虚拟机的要求,并且不会危害虚拟机自身的安全。
  2. 包括:文件格式验证(是否以魔数 oxcafebabe开头)、元数据验证、字节码验证和符号引用验证
  3. 可以考虑使用-Xverify:none 参数来关闭大部分的类验证措施,缩短虚拟机类加载的时间。
7>连接阶段-准备
  1. JVM会在该阶段对静态变量,分配内存并默认初始化(对应数据类型的默认初始化值如:0,0L,null,false等)。这些变量所使用的内存都将在方法区中进行分配
class A{
    //说明类加载的链接阶段-->准备阶段
    /*
    分析:1、n1是实例属性,不是静态变量,因此在准备阶段是不会分配内存的
         2、n2是静态变量,默认初始化为0,而不是20(20是在初始化阶段赋值)
         3、n3是static final为常量,他和静态变量不一样,因为一旦赋值就不会改变,n3=30
     */
    public int n1=10;
    public static int n2=20;
    public static final int n3=30;
}
8>连接阶段-解析

虚拟机将常量池内的符号引用替换为直接引用的过程。

9>初始化( Initialization)
  1. 到初始化阶段,才真正开始执行类中定义的Java程序代码,此阶段是执行() 方法的过程。
  2. () 方法是由编译器按照语句在源文件中出现的顺序,依次自动收集类中所有静态变量的赋值动作和静态代码块中的语句,并进行合并。
/*
分析: 1、加载B类,并生成B的Class对象
    2、链接 num=0 (静态)
    3、初始化阶段
        依次自动收集类中所有静态变量的赋值动作和静态代码块中的语句,并合并
        clinit(){
            System.out.println("B的静态代码块被执行~");
            //num=300;
            num=100;
        }
        合并之后num=100;
 */
  1. 虚拟机会保证一个类的() 方法在多线程环境中被正确地加锁、同步,如果多个线程同时去初始化一个类,那么只会有一个线程去执行该类的() 方法,其他线程都需要阻塞等待,直到活动线程执行() 方法完毕。
//看看加载类的时候是会有一个同步机制的(Debug)
/*
        protected Class<?> loadClass(String name, boolean resolve)
        throws ClassNotFoundException
    {
        synchronized (getClassLoadingLock(name)) {
        ...
        }
     }
 */

(7)通过反射获取类的结构信息

第一组: java.lang.Class 类

在这里插入图片描述

public void api_01() throws ClassNotFoundException {
    //得到Class对象
    Class<?> personcls = Class.forName("reflection_.text.Person");
    //getName 获取全类名
    System.out.println("<<=====getName 获取全类名=====>>");
    System.out.println(personcls.getName());
    //getSimpleName 获取简单类名
    System.out.println("<<=====getSimpleName 获取简单类名=====>>");
    System.out.println(personcls.getSimpleName());
    //getFields 获取所有public修饰的属性,包含本类以及父类的
    System.out.println("<<=====getFields 获取所有public修饰的属性,包含本类以及父类的=====>>");
    Field[] fields = personcls.getFields();
    for (Field f :fields) {
        System.out.println("本类以及父类的属性="+f.getName());
    }
    //getDeclaredFields() 获取本类中所有属性
    System.out.println("<<=====getDeclaredFields() 获取本类中所有属性=====>>");
    Field[] declaredFields = personcls.getDeclaredFields();
    for (Field f :declaredFields) {
        System.out.println("本类所有的属性="+f);
    }
    //getMethods() 获取所有public修饰的方法,包含本类以及父类的
    System.out.println("<<=====getMethods() 获取所有public修饰的方法,包含本类以及父类的=====>>");
    Method[] methods = personcls.getMethods();
    for (Method m :methods) {
        System.out.println(m);
    }
    //getDeclaredMethods() 获取本类中所有方法
    System.out.println("<<=====getDeclaredMethods() 获取本类中所有方法=====>>");
    Method[] declaredMethods = personcls.getDeclaredMethods();
    for (Method m :declaredMethods) {
        System.out.println(m);
    }
    //getConstructors() 获取本类所有public修饰的构造器
    System.out.println("<<=====getConstructors() 获取本类所有public修饰的构造器 =====>>");
    Constructor<?>[] constructors = personcls.getConstructors();
    for (Constructor constructor :constructors) {
        System.out.println(constructor);
    }
    //getDeclaredConstructors() 获取本类所有构造器
    System.out.println("<<=====getDeclaredConstructors() 获取本类所有构造器 =====>>");
    Constructor<?>[] declaredConstructors = personcls.getDeclaredConstructors();
    for (Constructor constructor :declaredConstructors) {
        System.out.println(constructor);
    }
    //getPackage() 以Package形式返回 包信息
    System.out.println("<<=====getPackage() 以Package形式返回 包信息 =====>>");
    System.out.println(personcls.getPackage());
    //getSuperclass() 以Class形式返回父类信息
    System.out.println("<<=====getSuperclass() 以Class形式返回父类信息 =====>>");
    System.out.println(personcls.getSuperclass());
    //getInterfaces() 以Class[]形式返回接口信息
    System.out.println("<<=====getInterfaces() 以Class[]形式返回接口信息 =====>>");
    Class<?>[] interfaces = personcls.getInterfaces();
    for (Class aClass :interfaces) {
        System.out.println(aClass);
    }
    //getAnnotations() 以Annotation[]形式返回注解信息
    System.out.println("<<=====getAnnotations() 以Annotation[]形式返回注解信息 =====>>");
    Annotation[] annotations = personcls.getAnnotations();
    for (Annotation annotation :annotations) {
        System.out.println(annotation);
    }
}
java.lang.reflect.Field 类, java.lang.reflect.Method 类, java.lang.reflect.Constructor 类

在这里插入图片描述

public void api_02() throws ClassNotFoundException {
    //得到Class对象
    Class<?> personcls = Class.forName("reflection_.text.Person");
    //getDeclaredFields() 获取本类中所有属性
    System.out.println("<<=====getDeclaredFields() 获取本类中所有属性=====>>");
    Field[] declaredFields = personcls.getDeclaredFields();
    for (Field f :declaredFields) {
        System.out.println("本类所有的属性="+f.getName()+" 该属性的修饰符="+f.getModifiers()
        +" 该属性的类型="+f.getType());
    }

    //getDeclaredMethods() 获取本类中所有方法
    System.out.println("<<=====getDeclaredMethods() 获取本类中所有方法=====>>");
    Method[] declaredMethods = personcls.getDeclaredMethods();
    for (Method m :declaredMethods) {
        System.out.println("==========");
        System.out.println("本类中所有的方法="+m.getName()+
                " 该方法的修饰符="+m.getModifiers()+" 该方法的返回类型="+m.getReturnType());
        Class<?>[] parameterTypes = m.getParameterTypes();
        for (Class<?> parameterType : parameterTypes) {
            System.out.println("该方法的参数类型="+parameterType);
        }
    }

    //getDeclaredConstructors() 获取本类所有构造器
    System.out.println("<<=====getDeclaredConstructors() 获取本类所有构造器 =====>>");
    Constructor<?>[] declaredConstructors = personcls.getDeclaredConstructors();
    for (Constructor constructor :declaredConstructors) {
        System.out.println("==============================================");
        System.out.println("本类中的所有构造器="+constructor+" 该构造器的修饰符="+constructor.getModifiers());
        Class[] parameterTypes = constructor.getParameterTypes();
        for (Class parameterType : parameterTypes) {
            System.out.println("该构造器的参数类型="+parameterType);
        }
    }
}

(8)通过反射创建对象

在这里插入图片描述

package reflection_.text;

import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;

public class ReflecCreateInstance {
    public static void main(String[] args) throws ClassNotFoundException, InstantiationException, IllegalAccessException, NoSuchMethodException, InvocationTargetException {
        //1、先获取到User类的Clas对象
        Class<?> userclass = Class.forName("reflection_.text.User");

        //2、通过public的无参构造器创建实例
        Object o = userclass.newInstance();
        System.out.println(o);

        //3、通过public的有参构造器创建实例
        /*
            constructor 对象就是
            public User(String name) {//public的有参构造器
                this.name = name;
            }
         */
        //3.1先得到对应构造器
        Constructor<?> constructor = userclass.getConstructor(String.class);
        //3.2创建实例,并传入实参
        Object o1 = constructor.newInstance("Ghost-D");
        System.out.println(o1);

        //4、通过非public的有参构造器创建实例
        //4.1先得到私有的构造器
        Constructor<?> declaredConstructor = userclass.getDeclaredConstructor(int.class, String.class);
        //4.2爆破(因为获得的对象实例是私有的需要爆破才能正常访问)通过反射可以访问private构造器,反射面前都是纸老虎
        declaredConstructor.setAccessible(true);//爆破
        //4.3创建实例,并传入参数
        Object o2 = declaredConstructor.newInstance(22, "Ghost-Dew");
        System.out.println(o2);

    }
}

class User {
    private int age=23;
    private String name="djt";

    public User() {
    }

    public User(String name) {//public的有参构造器
        this.name = name;
    }

    private User(int age, String name) {
        this.age = age;
        this.name = name;
    }

    @Override
    public String toString() {
        return "User{" +
                "age=" + age +
                ", name='" + name + '\'' +
                '}';
    }
}

(9)通过反射访问类中的成员

1>访问属性

在这里插入图片描述

package reflection_.text;

import java.lang.reflect.Field;

public class ReflecAccessProperty {
    public static void main(String[] args) throws ClassNotFoundException, InstantiationException, IllegalAccessException, NoSuchFieldException {
        //1、先得到Student对应的Class对象
        Class<?> stuClass = Class.forName("reflection_.text.Student");
        //2、创建对象
        Object o = stuClass.newInstance();
        System.out.println(o.getClass());//Student
        //3、使用反射得到age属性对象
        Field age = stuClass.getField("age");
        age.set(o,23);//通过反射来操作属性
        System.out.println(o);//调用toString
        System.out.println(age.get(o));//23
        //4、使用反射操作name属性(非public)
        Field name = stuClass.getDeclaredField("name");
        //对name进行爆破,来操作private属性
        name.setAccessible(true);
//        name.set(o,"djt");
        //当name属性为static修饰时
        name.set(null,"djt~");
        System.out.println(o);
        System.out.println(name.get(null));//要求name必须时static修饰的
    }
}
class Student{
    public int age;
    private static String name;

    public Student() {
    }

    @Override
    public String toString() {
        return  "Student [age=" + age + ", name=" + name + "]";
    }
}
2>访问方法

在这里插入图片描述

package reflection_.text;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;

public class ReflecAccessMethod {
    public static void main(String[] args) throws ClassNotFoundException, InstantiationException, IllegalAccessException, NoSuchMethodException, InvocationTargetException {
        //1、先得到Boss对应的Class对象
        Class<?> bossCls = Class.forName("reflection_.text.Boss");
        //2、创建对象
        Object o = bossCls.newInstance();

        //3、调用public的hi方法
        Method hi = bossCls.getMethod("hi", String.class);
        //3.1得到hi方法对象
//        Method hi = bossCls.getDeclaredMethod("hi", String.class);
        //3.2调用
        hi.invoke(o,"Ghost-D");

        //4、调用private static方法
        //4.1得到say方法对象
        Method say = bossCls.getDeclaredMethod("say", int.class, String.class, char.class);
        //4.2因为say方法时private,所以需要爆破,
        say.setAccessible(true);
        System.out.println(say.invoke(0,22,"张三",'男'));
        //4.3因为say方法时static的,还可以在对象传入时传入null
        System.out.println(say.invoke(null,23,"djt",'男'));

        //5、在反射中,如果方法有返回值,统一返回Object,但是他的运行类型和方法定义的返回类型一致
        Object reVal = say.invoke(null, 25, "李四", '男');
        System.out.println("reVal的运行类型="+reVal.getClass());//String类型

        //演示一个返回的案例
        Method m1 = bossCls.getDeclaredMethod("m1");
        Object reVal2 = m1.invoke(o);
        System.out.println("reVal2的运行类型="+reVal2.getClass());//Monster
    }
}
class Monster{}
class Boss{
    public int age;
    private static String name;

    public Boss() {
    }
    public Monster m1(){
        return new Monster();
    }
    private static String say(int n,String s,char c){//静态方法
        return n+" "+s+" "+c;
    }
    public void hi(String s){//普通public方法
        System.out.println("hi~"+s);
    }
}

(10)本章作业

1、

在这里插入图片描述

package HomeWork;

import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;

public class homework01 {
    public static void main(String[] args) throws ClassNotFoundException, NoSuchFieldException, InstantiationException, IllegalAccessException, NoSuchMethodException, InvocationTargetException {
        Class<?> cls = Class.forName("HomeWork.PrivateTest");
        Object o = cls.newInstance();
        Field name = cls.getDeclaredField("name");
        name.setAccessible(true);
        name.set(o,"Ghost-D");
        Method method = cls.getMethod("getName");
        System.out.println(method.invoke(o));;
    }
}
class PrivateTest{
    private String name="hellokitty";

    public String getName() {
        return name;
    }

}
2、

在这里插入图片描述

package HomeWork;

import java.io.File;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;

public class homework02 {
    public static void main(String[] args) throws ClassNotFoundException, InstantiationException, IllegalAccessException, NoSuchMethodException, InvocationTargetException {
        Class<?> cls = Class.forName("java.io.File");
        Constructor<?>[] declaredConstructors = cls.getDeclaredConstructors();
        for (Constructor<?> declaredConstructor : declaredConstructors) {
            System.out.println(declaredConstructor);
        }
//        Object o = cls.newInstance();
        Constructor<?> declaredConstructor = cls.getDeclaredConstructor(String.class);
        Object o = declaredConstructor.newInstance("D:\\IO.txt");
        Method createNewFile = cls.getDeclaredMethod("createNewFile");
        createNewFile.setAccessible(true);
        createNewFile.invoke(o);
    }
}

void main(String[] args) throws ClassNotFoundException, InstantiationException, IllegalAccessException, NoSuchMethodException, InvocationTargetException {
Class<?> cls = Class.forName("java.io.File"); Constructor<?>[] declaredConstructors = cls.getDeclaredConstructors();
for (Constructor<?> declaredConstructor : declaredConstructors) { System.out.println(declaredConstructor); } // Object o = cls.newInstance(); Constructor<?> declaredConstructor = cls.getDeclaredConstructor(String.class);
Object o = declaredConstructor.newInstance(“D:\IO.txt”);
Method createNewFile = cls.getDeclaredMethod(“createNewFile”);
createNewFile.setAccessible(true);
createNewFile.invoke(o);
}
}


  • 13
    点赞
  • 22
    收藏
    觉得还不错? 一键收藏
  • 4
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值