java反射的基本使用

java反射机制的使用是相当广泛,以前掌握的不是太好,趁最近有时间来复习一番。得意

百度百科中对于反射机制是这么介绍的:JAVA反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意一个方法和属性;

一般我们都是通过new关键字来创建对象的,这个反射到底是何方婶婶?怎么那么牛?

不要急,我们先来看一下下面的示意图:

每一个.class文件加载到内存的时候都是一个Class类的对象!把Demo.class加载到内存的时候,他就是一个Class<Demo>的对象。与反射相关的类有一下的四种:

Class,Field,Method,Constructor,分别表示:类,成员变量,方法,和构造器。

获取Class通常有一下的3种方法:

1.通过类名称.class,对基本类型也支持;

 Class c = int.class

 Class c = int[].class

 Class c = String.class

2.通过对象.getClass()方法

Class c = obj.getClass();

3.Class.forName()通过类名称加载类,这种方法只要有类名称就可以得到Class

Class c = Class.forName(“类名”);(不要忘记包名)

********************************************************************************************

Class类的常用方法

String getName():获取类名称,包含包名;

String getSimpleName():获取类名称,不包含包名;

Class getSupperClass():获取父类的Class

例如:new Integer(100).getClass().getSupperClass()返回的是Class<Number>

new Object().getSupperClass()返回的是null,因为Object没有父类;

 T newInstance():使用本类无参构造器来创建本类对象;

 boolean isArray():是否为数组类型;

 boolean isAnnotation():是否为注解类型;

 boolean isAnnotationPresent(Class annotationClass):当前类是否被annotationClass注解了;

 boolean isEnum():是否为枚举类型;

 boolean isInterface():是否为接口类型;

 boolean isPrimitive():是否为基本类型;

 boolean isSynthetic():是否为引用类型;

下面举个例子来总结一下:

package lsj.pc;

public class Test {
	@org.junit.Test
	public void fun1() throws Exception {
		Class<?> clazz = Class.forName("lsj.pc.User"); 
		User user = (User)clazz.newInstance();
		user.setPassword("1234567");
		user.setUsername("TOM");
		System.out.println(user);
	}

}
class User {
    
    private String username;
    private String password;
    
    public User(String username, String password) {
        
        this.username = username;
        this.password = password;
    }
    
    public User() {
        
    }

    public String getUsername() {
        return username;
    }
    public void setUsername(String username) {
        this.username = username;
    }

    public String getPassword() {
        return password;
    }

    public void setPassword(String password) {
        this.password = password;
    }

    @Override
   public String toString() {
        return "用户名:"+ username + ", 密码:" + password ;
    }
}
执行的结果如下:

User [username=TOM, password=1234567]

上面的例子中,通过反射获取了User类的Class对象,然后通过Class对象的newInstance()方法创建了一个user对象的实例。

2)获取玩Class对象,接下来获取构造器Constructor对象。

获取的方式有以下4种:

Constructor getConstructor(Class… parameterTypes)通过指定的参数类型获取公有构造器反射对象;

 Constructor[] getConstructors()获取所有公有构造器对象;

 Constructor getDeclaredConstructor(Class… parameterTypes)通过指定参数类型获取构造器反射对象。可以是私有构造器对象;

 Constructor[] getDeclaredConstructors()获取所有构造器对象。包含私有构造器;

Construcator类常用方法

 String getName():获取构造器名;

 Class getDeclaringClass():获取构造器所属的类型;

 Class[] getParameterTypes():获取构造器的所有参数的类型;

 Class[] getExceptionTypes():获取构造器上声明的所有异常类型;

 T newInstance(Object… initargs):通过构造器反射对象调用构造器。

下面举个例子:

public class Test {
	@org.junit.Test
	public void fun1() throws Exception {
		Class<?> clazz = Class.forName("lsj.pc.User"); 
		Constructor<?> c=clazz.getConstructor(String.class,String.class);
		User user=(User) c.newInstance("TOM","1234567");
		/*User user = (User)clazz.newInstance();
		user.setPassword("1234567");
		user.setUsername("TOM");*/
		System.out.println(user);
	}

3)获取方法

 Method getMethod(String name, Class… parameterTypes)

通过方法名和方法参数类型获取方法反射对象,包含父类中声明的公有方法,但不包含所有私有方法;

Method[] getMethods()

获取所有公有方法,包含父类中的公有方法,但不包含任何私有方法;

 Method getDeclaredMethod(String name, Class… parameterTypes)

通过方法名和方法参数类型获取本类中声明的方法的反射对象,包含本类中的私有方法,但不包含父类中的任何方法;

Method[] getDeclaredMethods()

获取本类中所有方法,包含本类中的私有方法,但不包含父类中的任何方法。

下面是一些常用的方法:

 String getName():获取方法名;

 Class getDeclaringClass():获取方法所属的类型;

Class[] getParameterTypes():获取方法的所有参数的类型;

 Class[] getExceptionTypes():获取方法上声明的所有异常类型;

 Class getReturnType():获取方法的返回值类型;

 Object invode(Object obj, Object… args)

通过方法反射对象调用方法,如果当前方法是实例方法,那么当前对象就是obj,如果当前方法是static方法,那么可以给obj传递nullargs表示是方法的参数;

现在我们试着获取User的toString方法。

<span style="color:#000000;">public class Test {
	@org.junit.Test
	public void fun1() throws Exception {
		Class<?> clazz = Class.forName("lsj.pc.User"); 
		Constructor<?> c=clazz.getConstructor(String.class,String.class);
		User user=(User) c.newInstance("TOM","1234567");
		Method method=clazz.getMethod("toString");
		String result =(String) method.invoke(user);
		/*User user = (User)clazz.newInstance();
		user.setPassword("1234567");
		user.setUsername("TOM");*/
		System.out.println(result);
	}

}</span>
结果 :用户名:TOM, 密码:1234567
4)获取类的成员变量

 Field getField(String name):通过名字获取公有成员变量的反射对象,包含父类中声明的公有成员变量;

 Field[] getFields():获取所有公有成员变量反射对象,包含父类中声明的公有成员变量;

 Field getDeclaredField(String name):通过名字获取本类中某个成员变量,包含本类的private成员变量,但父类中声明的任何成员变量都不包含;

 Field[] getDeclaredFields():获取本类中声明的所有成员变量,包含private成员变量,但不包含父类中声明的任何成员变量;

Fileld类有以下的一些常用的方法:

 String getName():获取成员变量名;

 Class getDeclaringClass():获取成员变量的类型;

Class getType():获取当前成员变量的类型;

Object get(Object obj):获取obj对象的成员变量的值;

 void set(Object obj, Object value):设置obj对象的成员变量值为value

下面举一个例子:

import java.lang.reflect.Field;
public class Test {
	@org.junit.Test
	public void fun1() throws Exception {
		Class<?> clazz = Class.forName("lsj.pc.User"); 
		User user=new User("老王","123");
		Field field1=clazz.getDeclaredField("username");
		Field field2=clazz.getDeclaredField("password");
		String username=(String) field1.get(user);
		String password=(String) field2.get(user);
		System.out.println(username+","+password);
		field1.set(user,"lisi");
		field2.set(user,"456");
		System.out.println(user);
	}

}
class User {
	
	public String username;
	public String password;
	
	public User(String username, String password) {
		
		this.username = username;
		this.password = password;
	}
	
	public User() {
		
	}

	public String getUsername() {
		return username;
	}
	public void setUsername(String username) {
		this.username = username;
	}

	public String getPassword() {
		return password;
	}

	public void setPassword(String password) {
		this.password = password;
	}

	@Override
	public String toString() {
		return "用户名:"+ username + ", 密码:" + password ;
	}
}
输出结果:

老王,123
用户名:lisi, 密码:456

5)获取AccessibleObject

AccessibleObject类是ConstructorMethodField三个类的父类。AccessibleObject最为重要的方法如下:

boolean isAccessible():判断当前成员是否可访问;

void setAccessible(boolean flag):设置当前成员是否可访问。

ConstructorMethodField为私有时,如果我们想反射操作,那么就必须先调用反射对象的setAccessible(true)方法,然后才能操作。

把刚才的User类中的两个属性改成private类型。

	public void fun1() throws Exception {
		Class<?	> clazz = Class.forName("lsj.pc.User"); 
		User user=new User("老王","123");
		Field field1=clazz.getDeclaredField("username");
		Field field2=clazz.getDeclaredField("password");
		field1.setAccessible(true);
		field2.setAccessible(true);
		String username=(String) field1.get(user);
		String password=(String) field2.get(user);
		System.out.println(username+","+password);
		field1.set(user,"lisi");
		field2.set(user,"456");
		System.out.println(user);
	}

这样就可以访问私有的成员变量了。


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值