Java反射总结

本文详细介绍了Java中的反射机制,包括如何通过Class类获取类信息,创建对象,判断继承关系,访问成员变量和调用方法。还展示了如何使用反射调用构造方法,以及instanceof运算符和isAssignableFrom()方法在判断类型关系中的应用。
摘要由CSDN通过智能技术生成

反射:在运行期根据当前传入的类型,得到类型(class对象)。也就是说只有在运行期才能知道某种类型。根据这种类型创建class实例,并获取该实例的所有信息。

一、反射使用场景:运行期才能确定对象的类型。
二、常见的类:
Class类:

1、获取class对象的三种方法(以String类为例)

通过类名访问class:

    通过类名访问class
    Class stringCls1 = String.class;

通过实例访问getClass():

    String s = "";
	Class stringCls2 = s.getClass();

通过Class类的静态方法forName:

    String s = "";
	Class stringCls2 = s.getClass();

2、Class类的常见方法

        //得到String类的Class对象
        Class cls = String.class; 

        //类名
		System.out.println("类的名称:"+cls.getSimpleName());
		System.out.println("完全限定名:"+cls.getName());
		System.out.println("类的类型名称:"+cls.getTypeName());
        
        //获取继承关系:父类、接口
		//父类
		Class superCls = cls.getSuperclass();
		System.out.println("类的父类:"+superCls.toString());
        System.out.println("类的父类的父类:"+superCls.getSuperclass().getName());
		//实现的接口
		Class[] interfaceCls = cls.getInterfaces();
		System.out.println("当前类实现的接口:");
		for(Class clss : interfaceCls) {
			System.out.println(clss);
		}

		//包
		Package pck = cls.getPackage();
        //判断该类的包是否为空
		if(pck != null) {
			System.out.println("类所在包的名称:"+pck.getName());
		}
		//判断类型
		System.out.println("是否为接口:"+cls.isInterface());
		System.out.println("是否为数组:"+cls.isArray());
		System.out.println("是否为枚举:"+cls.isEnum());

3、创建某个类的对象

    //通过Class类的静态方法forName   
    //得到该类的Class对象      
    Class cls = Class.forName(String);
    //创建对象,
    //newInstance():调用无参构造方法
    Object obj = cls.newInstance();
    System.out.println(obj);
Constructor类:可以调用任何类型的构造方法

1、Constructor类的getConstructors()方法能获取所有定义的构造方法,但获取的构造方法是public公有的。

public class Demo05 {
	public static void main(String[] args) throws NoSuchMethodException, SecurityException, InstantiationException, IllegalAccessException, IllegalArgumentException, InvocationTargetException {
		//得到Exemple类的Class对象
		Class cls = Exemple.class;
		
		//调用无参构造方法创建Exemple类型的对象
		Exemple ex1 = (Exemple)cls.newInstance();
		System.out.println(ex1);
		
		//获取所有的构造方法
		//获取所有public公有的构造方法
		Constructor[] constructArray = cls.getConstructors();
		System.out.println("所有的构造方法:");
		for(Constructor constructor1 : constructArray) {
			System.out.println(constructor1);
		}
		
		System.out.println("-----------分隔符------------------");
		
		//调用有参构造方法创建Exemple类型的对象
		//1.获取指定参数类型的构造方法
		//无参构造
		Constructor constructor2 = cls.getConstructor();
		Exemple ex2 = (Exemple)constructor2.newInstance();
		System.out.println("无参构造:"+ex2);
		
		//有一个参数的构造方法,传入参数类型
		Constructor constructor3 = cls.getConstructor(int.class);
		Exemple ex3 = (Exemple)constructor3.newInstance(512);
		System.out.println("有1个参数的构造方法:"+ex3);
		
		//有2个参数的构造方法
		Constructor constructor4 = cls.getConstructor(int.class,double.class);
		System.out.println(constructor4);
		//执行构造方法,创建Exemple类型的对象
		Exemple ex4 = (Exemple)constructor4.newInstance(1024,3.1415926);
		System.out.println("有2个参数的构造方法:"+ex3);
	}
}
class Exemple{
	public Exemple(){
		System.out.println("Exemple类的无参构造方法!");
	}
	public Exemple(int a){
		System.out.printf("Exemple类的有参构造方法,a=%d\n",a);
	}
	public Exemple(int a,double b){
		System.out.printf("Exemple类的有参构造方法,a=%d,b=%f\n",a,b);
	}
}

2、Constructor类的getDeclaredConstructors()方法能获取所有定义的构造方法(任意修饰符修饰的)。

public class Demo06 {
	public static void main(String[] args) throws NoSuchMethodException, SecurityException, InstantiationException, IllegalAccessException, IllegalArgumentException, InvocationTargetException {
		//得到Exemple类的Class对象
		Class cls = Exempl.class;
		
		//获取所有定义的构造方法(任意修饰符修饰)
		Constructor[] constructArray = cls.getDeclaredConstructors();
		System.out.println("所有定义的构造方法");
		for(Constructor constructor : constructArray) {
			System.out.println(constructor);
		}
		//获取一个带一个参数的私有构造方法
		Constructor privateConstruct = cls.getDeclaredConstructor(String.class);
		//调用私有的构造方法
		privateConstruct.setAccessible(true);
		Exempl ex = (Exempl)privateConstruct.newInstance("just");
		System.out.println(ex);
	}
}

class Exempl{
	private Exempl(String s){
		System.out.printf("Exemple类的有参构造方法,s=%s\n",s);
	}
	protected Exempl(Float f){
		System.out.printf("Exemple类的有参构造方法,f=%d\n",f);
	}
	public Exempl(){
		System.out.println("Exemple类的无参构造方法!");
	}
	public Exempl(int a){
		System.out.printf("Exemple类的有参构造方法,a=%d\n",a);
	}
	public Exempl(int a,double b){
		System.out.printf("Exemple类的有参构造方法,a=%d,b=%f\n",a,b);
	}
}
三、判断继承关系

instanceof 运算符:判断“引用”和“类型”之间的关系

        //instanceof 运算符:判断“引用”和“类型”之间的关系
		Object obj = Integer.valueOf(9876);

        //是否为Integer类型
		                                 // “引用”           “类型”
		System.out.println("是否为Integer?"+(obj instanceof Integer));//true

		//是否为Double类型
		System.out.println("是否为Double?"+(obj instanceof Double));//false

		//Integer类继承自Number抽象类,实现Comparable接口
		System.out.println("是否为Number?"+(obj instanceof Number));//true
		System.out.println("是否为Comparable接口?"+(obj instanceof Comparable));//true

isAssignableFrom()方法:判断“类型”和“类型”之间的关系

        //Integer类和Integer类之间是否存在可以赋值的关系
		System.out.println("Integer <= Integer:"+Integer.class.isAssignableFrom(Integer.class));//true
		
		//相当于:Number n = Integer.valueOf();
		System.out.println("Number <= Integer:"+Number.class.isAssignableFrom(Integer.class));//true
		
		//相当于:Integer i = Number.valueOf();
		System.out.println("Integer <= Number:"+Integer.class.isAssignableFrom(Number.class));//false
		
		System.out.println("Double <= Integer:"+Double.class.isAssignableFrom(Integer.class));//false
		
		//一个接口的引用可以指向实现类的对象
		System.out.println("Comparable <= Integer:"+Comparable.class.isAssignableFrom(Integer.class));//true
四、访问成员变量(字段):每个字段都会被封装成一个Field对象
public class Demo03 {
	public static void main(String[] args) {
		//得到Book类的Class对象
		Class cls = Book.class;
		
		//所有public访问修饰符定义的字段(包含父类)
		//Field[] fields = cls.getFields();
		
		//所有定义的字段(仅包含子类)
		Field[] fields = cls.getDeclaredFields();
		for (Field field : fields) {
			//返回值为int   1:public,  2:private
			System.out.println("成员变量访问修饰符(int):"+field.getModifiers());
			System.out.println("成员变量访问修饰符:"+Modifier.toString(field.getModifiers()));
			System.out.println("成员变量类型:"+field.getType());
			System.out.println("成员变量名称):"+field.getName());
			System.out.println();
		}
		
	}
}
class Book{
	private int stack;
	public String bookName;
	private double sale;
	public int getStack() {
		return stack;
	}
	public void setStack(int stack) {
		this.stack = stack;
	}
	public String getBookName() {
		return bookName;
	}
	public void setBookName(String bookName) {
		this.bookName = bookName;
	}
	public double getSale() {
		return sale;
	}
	public void setSale(double sale) {
		this.sale = sale;
	}
	@Override
	public String toString() {
		return "Book [stack=" + stack + ", bookName=" + bookName + ", sale=" + sale + "]";
	}
	public void dosth(int a,double b,String c) {
		
	}
}
五、使用反射的方式,完成成员变量保存值(set方法)
public static void main(String[] args) throws InstantiationException, IllegalAccessException, NoSuchFieldException, SecurityException {
		//运行期
		//使用反射的方式,完成成员变量保存值
		
		//获取Class类型对象
		Class cls = Book.class;
		//通过反射创建Book类的对象
		Object obj = cls.newInstance();
		
		//public字段
		//按照字段名称,获取指定字段
		Field field1 = cls.getDeclaredField("bookName");
        //set()方法:给成员变量保存值
		//参数1:目标Book对象
		//参数2:存入成员变量的值
		field1.set(obj, "小王子");
		System.out.println(obj);
		
		//private字段
		//按照字段名称,获取指定字段
		Field field2 = cls.getDeclaredField("sale");
		//设置允许访问私有成员变量
		field2.setAccessible(true);
        //set()方法:给成员变量保存值
		//参数1:目标Book对象
		//参数2:存入成员变量的值
		field2.set(obj, 0.8);
		System.out.println(obj);
	}
六、访问对象中的成员变量(字段)值(get方法)
public class Demo05 {
	public static void main(String[] args) throws IllegalArgumentException, IllegalAccessException {
		//创建Book类的对象
		Book book = new Book();
		//赋值
		book.setBookName("唐诗三百首");
		book.setStack(300);
		book.setSale(0.8);
		//调用静态方法,并传入对象
		printInfo(book);
	}
	public static void printInfo(Object obj) throws IllegalArgumentException, IllegalAccessException {
		//获取Class类型对象
		Class cls = obj.getClass();
		
		//获取所有的成员变量
		Field[] fields = cls.getDeclaredFields();
		for (Field field : fields) {
			System.out.println("成员变量名称:"+field.getName());
			//判断是否可以访问(private)
			if(!field.isAccessible()) {
				//设置私有成员变量允许访问
				field.setAccessible(true);
			}
			//get()方法:访问成员变量值,传入目标对象
			System.out.println("成员变量内容:"+field.get(obj));
		}
	}
}
七、获取调用方法(getMethod()方法)
public class Demo06 {
	public static void main(String[] args) throws InstantiationException, IllegalAccessException, NoSuchMethodException, SecurityException, IllegalArgumentException, InvocationTargetException {
		//获取Class对象
		Class cls = Base.class;
		//创建Base类的对象
		Object obj = cls.newInstance();
		
		//按照方法名称和“参数类型”获取Method方法对象
		//create()
		//Method method = cls.getMethod("create");
		
		//create(int x)
		Method method = cls.getMethod("create", int.class);
		
		//Method对象的invoke()作用:以反射的方式执行create()方法
		//参数1:目标对象(具体给哪个对象执行create方法)
		//参数2:参数值
		int r = (int)method.invoke(obj,5);
		System.out.println(r);
	}
}

class Base{
	public int create() {
		return 1;
	}
	public int create(int x) {
		return x;
	}
}
八、以反射方式调用静态方法
public static void main(String[] args) throws NoSuchMethodException, SecurityException, IllegalAccessException, IllegalArgumentException, InvocationTargetException {
		//计算以10为底的对数
		//获取某个指定数字的位数
		System.out.println((int)Math.log10(123456) + 1);
		
		//反射调用
		//得到Math类的Class对象
		Class cls = Math.class;
		
		//按照方法名称和“参数类型”获取Method方法对象
		Method methodLog10 = cls.getMethod("log10", double.class);
		
		//以反射的方式执行methodLog10()方法
		int size = Double.valueOf((double)methodLog10.invoke(null, 123456)).intValue() + 1;
		System.out.println(size);
	}
九、多态:目标对象决定了调用归属

Person类定义了hello()方法,其子类也重写了hello()方法,那么从Person实例中获取hello()方法,作用于Student实例,调用的是父类的hello方法还是子类的hello方法?运行结果是:调用了子类的hello方法。所以使用反射调用方法时,仍然遵循多态原理,调用实例的方法

public class Demo08 {
	public static void main(String[] args) throws NoSuchMethodException, SecurityException, IllegalAccessException, IllegalArgumentException, InvocationTargetException {
		//获取Person的hello方法
		Method h = Person.class.getMethod("hello");
		//对Student实例调用hello方法
		h.invoke(new Student());
	}
}
class Person{
	public void hello(){
		System.out.println("Person hello!");
	}
}
class Student extends Person{
	public void hello() {
		System.out.println("Student hello!");
	}
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值