Java反射和常用操作

一、什么是反射

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

Class类表示什么???

很多的人—>可以定义为一个Person类(有姓名、性别、年龄)
很多的车—>可以定义一个Car类(有颜色、车牌,品牌)
很多个类—>可以定义一个Class类(有类名、属性、方法)

1.1 类对象

类加载的产物,封装了一个类中的所有属性(包名、类名、父类、接口、属性、方法、构造方法)

1.2 类的对象

基于某个类new出来的对象,也称实例对象

二、获取类对象的三种方法

  • Object类中的getClass()方法
  • 类.class
  • 通过Class类的forName()方法

创建一个Person类,后面使用

package com.javase.reflection;

public class Person {
    
    
    public int type;
    private String name;//私有属性
    int age;//默认属性
    protected String sex;
    public Person() {
    
    
        System.out.println("无参构造方法被调用了!!!");
    }//无参构造方法
    //带三个参数的构造方法
    public Person(String name, int age, String sex) {
    
    
        this.name = name;
        this.age = age;
        this.sex = sex;
        System.out.println("带参构造方法被调用了!!!");
    }
    public void eat(){
    
    //无参方法
        System.out.println(this.name+"吃饭!!!");
    }
    public void eat(String food){
    
    //一个参数方法
        System.out.println(this.name+"吃"+food);
    }
    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 String getSex() {
    
    
        return sex;
    }
    public void setSex(String sex) {
    
    
        this.sex = sex;
    }
    //重写toString方法
    @Override
    public String toString() {
    
    
        return "Person{" +
                "name='" + name + '\'' +
                ", age=" + age +
                ", sex='" + sex + '\'' +
                '}';
    }
}

2.1 Object类中的getClass()方法

public class Test {
    
    
    public static void main(String[] args) throws ClassNotFoundException {
    
    
        Person person = new Person();
        //第一种方法:Object中的getClass()方法
        Class<? extends Person> aClass = person.getClass();
        System.out.println(aClass);
    }
}

2.2 类.class

public class Test {
    
    
    public static void main(String[] args) throws ClassNotFoundException {
    
    
        //第二中方法:类.class
        Class<Person> bClass = Person.class;
        System.out.println(bClass);
    }
}

2.3 通过Class类的forName()方法

public class Test {
    
    
    public static void main(String[] args) throws ClassNotFoundException {
    
    
        //第三重方法:Class.forName()方法 (推荐使用第三种方式)
        Class<?> cClass = Class.forName("com.javase.reflection.Person");
        System.out.println(cClass);
    }
}

三种方法的结果
在这里插入图片描述

三、使用反射进行类的实例化操作

3.1 调用无参构造方法进行实例化

  • public Constructor<T> getConstructor()获取类的无参构造方法
  • public T newInstance()创建对象实例
public class TestCode01 {
    
    
    public static void main(String[] args) throws Exception {
    
    
        //通过反射实例化对象
        Class<?> aClass = Class.forName("com.javase.reflection.Person");
        //使用newInstance()方法创建实例,调用的是无参构造方法
        Person p1 = (Person) aClass.newInstance();
        //获取无参构造方法
        Constructor<?> con = aClass.getConstructor();
        Person p2 = (Person)con.newInstance();
    }
}

在这里插入图片描述

3.2 调用有参构造方法进程实例化

public Constructor<T> getConstructor(类<?>... parameterTypes)获取返回一个Constructor对象,该对象反映Constructor对象表示的类的指定的公共类函数。

public class TestCode01 {
    
    
    public static void main(String[] args) throws Exception {
    
    
        //通过反射实例化对象
        Class<?> aClass = Class.forName("com.javase.reflection.Person");
        Constructor<?> con = aClass.getConstructor(String.class, int.class, String.class);
        Person p = (Person)con.newInstance("张三", 20, "男");
    }
}

在这里插入图片描述

四、反射的常用操作

4.1 使用反射获取类名、包名、父类、接口

  • public String getName()获取类的名字
  • public Package getpackage()获取类的包名
  • public Class<? super T> getSuperclass()获取类的父类
  • public Class<?>[] getInterfaces()获取类的接口
public class TestCode01 {
    
    
    public static void main(String[] args) throws ClassNotFoundException, InstantiationException, IllegalAccessException {
    
    
        //通过反射实例化对象
        Class<?> aClass = Class.forName("com.javase.reflection.Person");
        //获取类的名字
        String name = aClass.getName();
        System.out.println(name);
        //获取类的包名
        Package aPackage = aClass.getPackage();
        System.out.println(aPackage.toString());
        //获取类的父类
        Class<?> superclass = aClass.getSuperclass();
        System.out.println(superclass.toString());//Object是所有类的父类
        //获取类的接口
        Class<?>[] interfaces = aClass.getInterfaces();//一个类可以继承多个接口,返回的是一个数组
        System.out.println(interfaces.toString());
    }
}

在这里插入图片描述

4.2 使用反射获取类的属性

  • getFields()获取运行时类和父类中被public修饰的属性
  • getDeclaredFields()获取运行中的所有属性
  • getField(String name),getDeclarreField(String name)获取指定属性
  • 属性.getType()获取属性的数据类型
  • 属性.getModifiers()获取属性的修饰符
  • 属性.set(Object obj,Object value)给属性赋值
import java.lang.reflect.Field;
import java.lang.reflect.Modifier;

public class TestCode02 {
    
    
    public static void main(String[] args) throws Exception {
    
    
        Class<?> aClass = Class.forName("com.javase.reflection.Person");
        //获取运行时类和父类中被public修饰的属性
        Field[] fields = aClass.getFields();
        for (Field f : fields) {
    
    
            System.out.println(f);
        }
        System.out.println("--------------------");
        //获取运行中的所有属性
        Field[] declaredFields = aClass.getDeclaredFields();
        for(Field f : declaredFields){
    
    
            System.out.println(f);
        }
        System.out.println("--------------------");
        //获取指定属性
        Field name = aClass.getDeclaredField("name");
        System.out.println(name);
        System.out.println("--------------------");
        //获取属性的数据类型
        Class<?> type = name.getType();
        System.out.println(type);
        System.out.println("--------------------");
        //获取属性的修饰符
        int modifiers = name.getModifiers();
        System.out.println(modifiers);
        System.out.println(Modifier.toString(name.getModifiers()));
        System.out.println("--------------------");
        //给属性赋值
        Field type1 = aClass.getField("type");
        Person p =(Person) aClass.newInstance();
        type1.set(p,22);
        System.out.println(p.type);
    }
}

在这里插入图片描述

4.3 使用反射获取类的构造方法

public Constructor<?>[] getConstructors()获取类的构造方法

public class TestCode01 {
    
    
    public static void main(String[] args) throws Exception {
    
    
        //通过反射实例化对象
        Class<?> aClass = Class.forName("com.javase.reflection.Person");
        //获取类的构造方法
        Constructor<?>[] constructors = aClass.getConstructors();
        for (Constructor<?> con:constructors){
    
    
            System.out.println(con.toString());
        }
    }
}

在这里插入图片描述

4.4 使用反射获取类中的方法并调用

  • getMethods()获取public 的方法,包括从父类继承过来的方法
  • getDeclaredMethods()获取类中所有的方法,不包含继承方法
public class TestCode01 {
    
    
    public static void main(String[] args) throws Exception {
    
    
        //通过反射实例化对象
        Class<?> aClass = Class.forName("com.javase.reflection.Person");
        //获取类中public方法,包括父类继承过来的方法
        Method[] methods = aClass.getMethods();
        for (Method method : methods) {
    
    
            System.out.println(method.toString());
        }
        //获取类中所有的方法,包括private修饰的方法
        Method[] declaredMethods = aClass.getDeclaredMethods();
        for (Method method : declaredMethods) {
    
    
            System.out.println(method.toString());
        }
    }
}

在这里插入图片描述

  • getMethod(String name, 类<?>...parameterTypers)获取单个方法,参数为方法名,参数类型
  • invoke(Object obj,Object... args)在具有指定参数的方法对象上调用此方法对象表示的基础方法
public class TestCode01 {
    
    
    public static void main(String[] args) throws Exception {
    
    
        //通过反射实例化对象
        Class<?> aClass = Class.forName("com.javase.reflection.Person");
        //获取单个方法,无参方法并调用
        Method eat1 = aClass.getMethod("eat");
        Person p =(Person) aClass.newInstance();//创建对象
        eat1.invoke(p);//==p.eat();
        //获取一个带参的方法
        Method eat2 = aClass.getMethod("eat", String.class);
        eat2.invoke(p,"小龙虾!");
    }
}

在这里插入图片描述

  • getDeclaredMethod()可以获取类中的私有方法,但是私有方法不能直接调用,只能在类中调用,如果使用,就要设置它访问权限无效
  • setAccessible(boolean b)设置访问权限无效
public class TestCode01 {
    
    
    public static void main(String[] args) throws Exception {
    
    
        //通过反射实例化对象
        Class<?> aClass = Class.forName("com.javase.reflection.Person");
        Person p = (Person) aClass.newInstance();
		//获取私有方法
        Method privateMethod = aClass.getDeclaredMethod("privateMethod");
        //设置访问权限无效
        privateMethod.setAccessible(true);
        //调用方法
        privateMethod.invoke(p);
    }
}

获取调用静态方法,使用invoke()方法不需要传入对象–>invoke(null)

public class TestCode01 {
    
    
    public static void main(String[] args) throws Exception {
    
    
        //通过反射实例化对象
        Class<?> aClass = Class.forName("com.javase.reflection.Person");
		//获取私有方法
        Method staticMethod = aClass.getDeclaredMethod("staticMethod");
        //调用方法
        staticMethod.invoke(null);//==p.staticMethod
    }
}

猜你喜欢

转载自blog.csdn.net/weixin_47383392/article/details/124567961