Java反射机制

文章详细介绍了Java反射机制,包括反射的基本概念,如何通过Class类获取类信息,调用构造方法,获取类的继承关系,访问和修改字段,以及动态调用方法,包括静态方法、非public方法和多态调用。这些内容展示了Java反射在运行时对类和对象的强大操作能力。
摘要由CSDN通过智能技术生成

目录

一、反射的基本概念

        1、反射的定义

二、Class类

        1、获取Class实例的三种方法

        2、Class常用方法

三、调用构造方法

        1、Constructor类

四、获取继承关系

        1、获取父类的Class

        2、获取interface

        3、继承关系

五、访问字段

        1、获取Field字段

 六、调用方法

        1、Method类

         2、调用方法

        3、调用静态方法

        4、调用非public方法

        5、多态


一、反射的基本概念

        1、反射的定义

        概念:反射就是把Java类中的各个组成部分映射成相应的Java类。

        简单来说,Java反射机制指的是程序在运行时,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意一个方法和属性。为了更好的学习反射,我们需要了解两个概念:编译期和运行期。

        编译期:把Java代码编译成class文件的过程。编译器只是做了一些翻译功能,并没有把代码放在内存中运行起来,而只是把代码当成文本进行操作。比如:检查语法错误。

        运行期:把编译后的文件交给计算机执行,直到程序运行结束。

二、Class类

        1、获取Class实例的三种方法

        方法一:直接通过一个class的静态变量class获取。

Class cls = String.class;

        方法二:如果我们有一个实例变量,可以通过该实例变量提供的getClass()获取。

String s = "Hello";
Class cls = s.getClass();

        方法三:如果知道一个class的完整类名,可以通过静态方法Class.forName获取。

Class cls = Class.forName("java.lang.String");
        2、Class常用方法
类型访问方法返回值类型说明
包路径getPackage()Package对象获取该类的存放路径
类名称getName()String对象获取该类的名称
继承类getSuperclass()Class对象获取该类继承的类
实现接口getInterfaces()Class型数组获取该类实现的所有接口
构造方法getConstructors()Constructor型数组获取所有权限为public的构造方法
getDeclaredConstructors()Constructor对象获取当前对象的所有构造方法
方法getMethods()Methods型数组获取所有权限为public的方法
getDeclaredMethods()Methods对象获取当前对象的所有方法
成员变量getFields()Field型数组获取所有权限为public的成员变量
getDeclaredFields()Field对象获取当前对象的所有成员变量

三、调用构造方法

        1、Constructor类

        为了调用任意的构造方法,Java的反射API提供了Constructor对象,它包含一个构造方法的所有信息,可以创建一个实例。Constructor对象是一个构造方法,调用结果总是返回实例。

public class Main {
     public static void main(String[] args) throws Exception {
         // 获取构造方法
         Constructor cons1 = Integer.class.getConstructor(int.class); 

        // 调用构造方法
        Integer n1 = (Integer) cons1.newInstance(123); 
        System.out.println(n1); 

        // 获取构造方法
        Constructor cons2 = Integer.class.getConstructor(String.class); 
        Integer n2 = (Integer) cons2.newInstance("456"); 
        System.out.println(n2); 
    } 
}

四、获取继承关系

        1、获取父类的Class
public class Main { 
    public static void main(String[] args) throws Exception { 
        Class i = Integer.class; 
        Class n = i.getSuperclass(); 
        System.out.println(n);//class java.lang.Number

        Class o = n.getSuperclass(); 
        System.out.println(o);//class java.lang.Object 
        System.out.println(o.getSuperclass());//null
    } 
}

运行代码发现,Integer的父类类型是Number,Number的父类是Object,Object的父类是null。除Object外,其他任何非interface的Class都必定存在一个父类类型。

        2、获取interface

        我们通过Class就可以查询到实现的接口类型。

Class s = Integer.class; 
Class[] is = s.getInterfaces(); 
		
for (Class i : is) { 
	System.out.println(i);//interface java.lang.Comparable
} 
        3、继承关系

调用isAssignableFrom()判断向上转型是否成立。

System.out.println("Interger=>Integer:"+
        Integer.class.isAssignableFrom(Integer.class));//true

System.out.println("Interger=>Double:"+
        Double.class.isAssignableFrom(Integer.class));//false

System.out.println("Interger=>Number:"+
        Number.class.isAssignableFrom(Integer.class));//true
	
System.out.println("Number=>Integer:"+
        Integer.class.isAssignableFrom(Number.class));//false

System.out.println("Interger=>Comparable:"+
        Comparable.class.isAssignableFrom(Integer.class));//true

五、访问字段

        1、获取Field字段
  • getName():返回字段名称。
  • getType():返回字段类型,也是一个Class实例。
  • getModifiers:返回字段的修饰符,它是一个int。
Class cls = obj.getClass();
Field[] fields = cls.getDeclaredFields();
		
for(Field field : fields) {
	System.out.println("访问修饰符:"+field.getModifiers());
	System.out.println("访问修饰符:"+Modifier.toString(field.getModifiers()));
	System.out.println("成员变量类型:"+field.getType());
	System.out.println("成员变量名称:"+field.getName());
	if(!field.isAccessible()) {
		field.setAccessible(true);
	}
	System.out.println("成员变量内容:"+field.get(obj));
	System.out.println();

 六、调用方法

        1、Method类
  • getName():返回方法名称。
  • getReturnType():返回方法返回值类型,也是一个Class实例。
  • getParameterTypes():返回方法的参数类型,是一个Class数组。
  • getModifiers():返回方法的修饰符,它是一个int,不同的value表示不同的访问修饰符。
Class cls = Order.class;
		
Method[] methods = cls.getDeclaredMethods();
		
for(Method method : methods) {
	System.out.println("访问修饰符:"+Modifier.toString(method.getModifiers()));
	System.out.println("返回值类型:"+method.getReturnType());
	System.out.println("方法名称:"+method.getName());
	System.out.println();
			
	Parameter[] params = method.getParameters();
	for(Parameter par : params) {
		System.out.println(par.getName());
		System.out.println(par.getType());
		System.out.println();
	}
}
         2、调用方法
//获取Class对象
Class cls = Base.class;
Object obj = cls.newInstance();//创建Base对象
		
//按照方法名称和“参数类型”获取Method方法对象
Method method = cls.getMethod("create",int.class);
		
//Method对象的invoke()作用
//以反射的方式执行create()方法
int b = (int) method.invoke(obj, 1000);
System.out.println(b);

class Base{

	public void create() {
		System.out.println("随机数为10");
	}

	public int create(int a) {
		return (int)(Math.random()*a);
	}
	
}
        3、调用静态方法

        如果获取到的Method表示一个静态方法,调用静态方法时,由于无需指定实例对象,所以invoke方法传入的第一个参数永远为null。

//计算以10为底的对数
//获取某个指定数字的位数
System.out.println((int)Math.log10(123456789)+1);//9

//反射调用
Class cls = Math.class;
Method methodLog10 = cls.getMethod("log10", double.class);
		
int size = Double.valueOf((double)methodLog10.invoke(null, 12345552)).intValue() + 1;
System.out.println(size);//8
        4、调用非public方法

        为了调用非public方法,我们通过Method.setAccessible(true)允许其调用。

public static void main(String[] args) throws Exception {
    Person p = new Person();
    Method m = p.getClass().getDeclaredMethod("setName", String.class); 

m.setAccessible(true); 
m.invoke(p, "Bob"); 
System.out.println(p.name); 
    }

class Person {
    String name; 
    private void setName(String name) {
    this.name = name;
    }
}
        5、多态

        使用反射调用方法时,仍然遵循多态原则。

public class Main { 
    public static void main(String[] args) throws Exception { 
        // 获取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"); 
    } 
}

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值