Java 基础 - 反射

发布时间:2024年01月24日

Java 基础 - 反射

1 什么是类对象

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

类对象:类加载的产物,封装了一个类的所有信息(类名、父类、接口、属性、方法、构造方法、包) ,每个类只有一个类对象。

反射:把Java类中的各种成分映射成单独的Java对象进行操作。

如图:

在这里插入图片描述

注意:每个类加载到内存都会生成一个唯一的类对象。

2 获取类对象的方法

通过类的对象,获取类对象。

Student s = new Student();
Class c = s.getClass();

通过类名获取类对象。

Class c = 类名.class;

通过静态方法获取类对象。

Class c=Class.forName(“包名.类名”);

代码演示:

Student:

package StageOne.day24.demo1;

import java.io.Serializable;

/**
 * @author 胡昊龙
 * @version 1.0
 * @description: TODO
 * @date 2024/1/19 10:13
 */
public class Student implements Serializable{
    private String name;
    private int age;

    public Student() {
    }

    public Student(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;
    }

    //普通方法
    public void show() {
        System.out.println("学生信息: 姓名 "+this.name+" 年龄 "+this.age);
    }

    public void show(String address) {
        System.out.println("学生地址: "+address);
    }

    public String getInfo() {
        return this.name+"..."+this.age;
    }
    public static void method1() {
        System.out.println("静态方法");
    }
    private void method2() {
        System.out.println("私有方法");
    }

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

TestReflect:

package StageOne.day24.demo1;

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

/**
 * @author 胡昊龙
 * @version 1.0
 * @description: TODO
 * @date 2024/1/19 10:20
 */
public class TestReflect {
    public static void main(String[] args) throws Exception{
        reflect1();
    }

    //反射操作1: 获取类对象
    public static void reflect1() throws Exception {
        //方式1 通过类的实例获取
        Student student = new Student();
        Class<?> aClass = student.getClass();
        System.out.println(aClass.hashCode());

        //方式2 通过class获取
        Class<?> class2 = Student.class;
        System.out.println(class2.hashCode());

        //方式3 通过Class.forName(类的全名称)获取(耦合性低,灵活性高)
        Class<?> class3 = Class.forName("StageOne.day24.demo1.Student");
        System.out.println(class3.hashCode());
    }
}

3 反射通用操作【重点

3.1 常见方法

方法名描述
public String getName()获取类的完全名称
public Package getPackage()获取包信息
public Class<? super T> getSuperclass()获取父类
public Class<?>[] getInterfaces()获取实现父接口
public Field[] getFields()获取字段信息
public Method[] getMethods()获取方法信息
public Constructor<?>[] getConstructors()获取构造方法
public T newInstance()反射创建对象

3.2 通用操作

反射通用操作:使用反射机制获取类对象,并使用Class对象的方法获取表示类成员的各种对象(比如Constructor、Method、Field等),实现反射各种应用。

案例演示:反射操作。

Person类:

public class Person implements Serializable,Cloneable{
	//姓名
	private String name;
	//年龄
	private int age;
	
	public Person() {
		System.out.println("无参构造执行了...");
	}
	
	public Person(String name, int age) {
		super();
		this.name = name;
		this.age = age;
		System.out.println("带参构造方法执行了...");
	}


	//吃
	public void eat() {
		System.out.println(name+"正在吃东西......");
	}


	@Override
	public String toString() {
		return "Person [name=" + name + ", age=" + age + "]";
	}
	//带参的方法
	public void eat(String food) {
		System.out.println(name+"开始吃...."+food);
	}
	
	//私有的方法
	private void privateMethod() {
		System.out.println("这是一个私有方法");
	}
	
	//静态方法
	public static void staticMethod() {
		System.out.println("这是一个静态方法");
	}
}

TestPerson类:

public class TestPerson {
	public static void main(String[] args) throws Exception {
		//调用测试以下方法
        //代码略
	}
	//获取类对象的三种方式
	public static void getClazz() throws Exception {
		//1使用对象获取类对象
		Person zhangsan=new Person();
		Class<?> class1=zhangsan.getClass();
		System.out.println(class1.hashCode());
		//2使用类名.class属性
		Class<?> class2=Person.class;
		System.out.println(class2.hashCode());
		//3使用Class的静态方法[推荐使用]
		Class<?> class3=Class.forName("com.qf.chap17_1.Person");
		System.out.println(class3.hashCode());
	}
	
	//1 使用反射获取类的名字、包名、父类、接口
	public static void reflectOpe1() throws Exception {
		//(1)获取类对象 Person
		Class<?> class1=Class.forName("com.qf.chap17_1.Person");
		//getName();
		System.out.println(class1.getName());
		//getPackage();
		System.out.println(class1.getPackage().getName());
		//getSuperClass();
		System.out.println(class1.getSuperclass().getName());
		//getInterfaces();
		Class<?>[] classes=class1.getInterfaces();
		System.out.println(Arrays.toString(classes));
		
		System.out.println(class1.getSimpleName());
		System.out.println(class1.getTypeName());
		
	}
	
	//2使用反射获取类的构造方法,创建对象
	public static void reflectOpe2() throws Exception{
		//(1)获取类的类对象
		Class<?> class1=Class.forName("com.qf.chap17_1.Person");
		//(2)获取类的构造方法 Constructor
		Constructor<?>[] cons=class1.getConstructors();
		for (Constructor<?> con : cons) {
			System.out.println(con.toString());
		}
		//(3)获取类中无参构造
		Constructor<?> con=class1.getConstructor();
		Person zhangsan=(Person)con.newInstance();
		Person lisi=(Person)con.newInstance();
		System.out.println(zhangsan.toString());
		System.out.println(lisi.toString());
		//简便方法:类对象.newInstance();
		Person wangwu=(Person)class1.newInstance();
		System.out.println(wangwu.toString());
		//(4)获取类中带参构造方法
		Constructor<?> con2=class1.getConstructor(String.class,int.class);
		Person xiaoli=(Person)con2.newInstance("晓丽",20);
		System.out.println(xiaoli.toString());
		
	}
	
	//3使用反射获取类中的方法,并调用方法
	public static void reflectOpe3() throws Exception{
		//(1)获取类对象
		Class<?> class1=Class.forName("com.qf.chap17_1.Person");
		//(2)获取方法  Method对象
		//2.1getMethods() 获取公开的方法,包括从父类继承的方法
		//Method[] methods=class1.getMethods();
		//2.2getDeclaredMethods() 获取类中的所有方法,包括私有、默认、保护的 、不包含继承的方法
		Method[] methods=class1.getDeclaredMethods();
		for (Method method : methods) {
			System.out.println(method.toString());
		}
		//(3)获取单个方法
		//3.1eat
		Method eatMethod=class1.getMethod("eat");
		//调用方法
		//正常调用方法  Person zhangsan=new Person();  zhangsan.eat();
		Person zhangsan=(Person)class1.newInstance();
		eatMethod.invoke(zhangsan);//zhangsan.eat();
		System.out.println("------------------");
		//3.2toString
		Method toStringMethod=class1.getMethod("toString");
		Object result=toStringMethod.invoke(zhangsan);
		System.out.println(result);
		System.out.println("-------------------");
		//3.3带参的eat 
		Method eatMethod2=class1.getMethod("eat", String.class);
		eatMethod2.invoke(zhangsan, "鸡腿");
		
		//3.4获取私有方法
		Method privateMethod=class1.getDeclaredMethod("privateMethod");
		//设置访问权限无效
		privateMethod.setAccessible(true);
		privateMethod.invoke(zhangsan);
		
		//3.4获取静态方法
		Method staticMethod=class1.getMethod("staticMethod");
		//正常调用 Person.staticMethod
		staticMethod.invoke(null);
		
	}
	
	//4使用反射实现一个可以调用任何对象方法的通用方法
	public static Object invokeAny(Object obj,String methodName,Class<?>[] types,Object...args) throws Exception {
		//1获取类对象
		Class<?> class1=obj.getClass();
		//2获取方法
		Method method=class1.getMethod(methodName, types);
		//3调用
		return method.invoke(obj, args);
	}
	
	//5使用反射获取类中的属性
	public static void reflectOpe4() throws Exception{
		//(1)获取类对象
		Class<?> class1=Class.forName("com.qf.chap17_1.Person");
		//(2)获取属性(字段) 公开的字段,父类继承的字段
		//Field[] fields=class1.getFields(); 
		//getDeclaredFields()获取所有的属性,包括私有,默认 ,包含,
		Field[] fields=class1.getDeclaredFields();
		System.out.println(fields.length);
		for (Field field : fields) {
			System.out.println(field.toString());
		}
		//(3)获取name属性
		Field namefield=class1.getDeclaredField("name");
		namefield.setAccessible(true);
		//(4)赋值  正常调用  Person zhangsan=new Person(); zhangsan.name="张三";
		Person zhangsan=(Person)class1.newInstance();
		namefield.set(zhangsan, "张三"); //zhangsan.name="张三";
		//(5) 获取值
		System.out.println(namefield.get(zhangsan));// zhangsan.name
	}
}

4 内省

内省:采用反射实现对属性进行操作的一种机制。

  • PropertyDescriptor:属性描述符 ,代表一个属性
  • BeanInfo:实体类信息 ,包含类的信息
  • Introspector:工具类

代码演示:

Dog:

package StageOne.day24.demo2;

/**
 * @author 胡昊龙
 * @version 1.0
 * @description: TODO
 * @date 2024/1/19 15:57
 */
public class Dog {
    private String breed;
    private int age;

    public Dog() {
    }

    public Dog(String breed, int age) {
        this.breed = breed;
        this.age = age;
    }

    public String getBreed() {
        return breed;
    }

    public void setBreed(String breed) {
        this.breed = breed;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

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

Test:

package StageOne.day24.demo2;

import java.beans.BeanInfo;
import java.beans.Introspector;
import java.beans.PropertyDescriptor;
import java.lang.reflect.Method;

/**
 * @author 胡昊龙
 * @version 1.0
 * @description: TODO
 * @date 2024/1/19 15:57
 */
public class Test {
    public static void main(String[] args) throws Exception {
        Class<?> aClass = Class.forName("StageOne.day24.demo2.Dog");
        Dog dog = (Dog) aClass.newInstance();

        PropertyDescriptor breed = new PropertyDescriptor("breed", aClass);
        Method setBreed = breed.getWriteMethod();
        Method getBreed = breed.getReadMethod();

        PropertyDescriptor age = new PropertyDescriptor("age", aClass);
        Method setAge = age.getWriteMethod();

        setBreed.invoke(dog,"二哈");
        setAge.invoke(dog,1);

        System.out.println(dog);

        //BeanInfo类信息: 封装了 类的所有属性
        /*
        内省内容中的属性含义:
            如果类中有getXxx(); 或 setXxx(); 或 isXxxv(); 方法
            则认为类中包含Xxx属性
         */
        BeanInfo beanInfo = Introspector.getBeanInfo(aClass);
        PropertyDescriptor[] pds = beanInfo.getPropertyDescriptors();
        for (PropertyDescriptor pd : pds) {
            System.out.println(pd.getName());
        }
    }
}
文章来源:https://blog.csdn.net/weixin_50858647/article/details/135764917
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。