JavaSE 第六十二讲: Class类、Method类及Field类的使用方式深度剖析

1. 在上一讲中,我们知道Java中,无论生成某个类的多少对象,这些对象都会对应于同一个Class对象。

    这边的Class对象是非常重要的概念,这个Class对象描述了类的本身结构,这个对象是由JVM生成的,是在类转载的时候生成的,并不是在new出一个对象的时候生成的。在以后学习JVM的时候会详细剖析。

2.要想使用反射,首先需要获得待处理类或对象所对应的 Class 对象。有两种获得方式,详细查看上一讲内容。

3.练习以下一个程序,掌握反射

定义一个方法,这个方法的功能是:接受一个Customer类型的对象,讲对象的属性拷贝出来,生成一个新的对象,然后将新的对象返回回来,相当于一个对象的拷贝

如果使用传统的方式比较容易:比如先有一个Customer对象,再去生成一个Customer对象,调用新生成对象的set方法和已有对象的get方法,将get的值set到新对象里面,就返回到新的对象

如果使用反射的话,这个功能就会想比较难

package com.ahuier.reflect;

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

public class ReflectTest {
	/*
	 * 定义一个方法实现对象的拷贝,使用反射.该方法实现对Customer对象的拷贝操作
	 * 所谓的拷贝,就是将原有对象属性属性拷贝出来放到新的对象,将对象返回回来
	 */

	public Object copy(Object object) throws Exception{
		
		//获取class对象的第三种方式
		Class<?> classType = object.getClass();
		
/*		System.out.println(classType); //直接打印输出class对象的全称:class com.ahuier.reflect.Customer
		System.out.println(classType.getName()); //打印出class对象它所关联的类的全称:com.ahuier.reflect.Customer
*/		
		//这边要新生成一个对象,以便将这个对象接受到的属性值返回给调用端。
	//查看JDK Doc文档 java.lang.Class.newInstance()方法 和 java.lang.reflect下的Constructor<T>类的newInstance()方法
		
/*		Constructor cons = classType.getConstructor(new Class[]{}); //这边调用不带参数的构造方法
		Object obj = cons.newInstance(new Object[]{});
		对于调用不接受参数的构造方法,以上两行代码等价于 Object obj2 = classType.newInstance();*/
		
/*		Constructor cons = classType.getConstructor(new Class[]{String.class, int.class}); //这边调用带参数的构造方法
		Object obj = cons.newInstance(new Object[]{"Hello", 3});*/
		
	//	System.out.println(obj); //输出:com.ahuier.reflect.Customer@497934 说明生成的对象是Constructor对象
		
		Object objectCopy = classType.getConstructor(new Class[]{})
				.newInstance(new Object[]{});
		
		//获得对象的所有成员变量,查看JDK Doc文档,class里的getDeclaredFields()
		Field[] fields = classType.getDeclaredFields();
		for(Field field : fields){
		//	System.out.println(field); 可以查看这边的field输出内容呢
			String name = field.getName(); //获取到属性的名字
			
			//这边观察set()方法get()方法他们与属性的规律 "set" + 属性首字母大写 + 属性其他字母小写
			//这边查看String的方法,substring(0, 1)获取字符串的子字符串0与1之间的字符串内容
			//toUpperCase()字符转换大写
			String firstLetter = name.substring(0,1).toUpperCase();//将属性的首字母转换为大写
			
			//获取get和set方法的名字
			String getMethodName = "get" + firstLetter + name.substring(1);
			String setMethodName = "set" + firstLetter + name.substring(1);
		//	System.out.println(getMethodName + "," + setMethodName);
			
			//获得Method对象
			Method getMethod = classType.getMethod(getMethodName, new Class[]{});
			Method setMethod = classType.getMethod(setMethodName, new Class[]{field.getType()}); //获取属性本身的类型:field.getType()
			
			Object value = getMethod.invoke(object, new Object[]{});//这边第一个参数object表示调用方法的目标对象,这里的对象是传递进去的参数
			
			setMethod.invoke(objectCopy, new Object[]{value}); 			
		}
		
		
		return objectCopy;
	}
	public static void main(String[] args) throws Exception{
		
		Customer customer = new Customer("Tom", 20);
		customer.setId(1L);
		
		ReflectTest test = new ReflectTest();
		Customer customer2 = (Customer)test.copy(customer);
		System.out.println(customer2.getId() + "," + customer2.getName() + "," + customer2.getAge());
	}

}

class Customer{
	private Long id; //注意这边是包装类型的Lang
	private String name;
	private int age;
	
	public Customer(){
		
	}
	public Customer(String name, int age){
		this.name = name;
		this.age = age;
	}
	public Long getId() {
		return id;
	}
	public void setId(Long id) {
		this.id = id;
	}
	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;
	}
	
}

编译执行结果:

1,Tom,20


1. 获取某个类或某个对象所对应的 Class 对象的常用的 3 种方式:

a) 使用 Class 类的静态方法 forNameClass.forName(“java.lang.String”); 

b) 使用类的.class 语法:String.class; 

c) 使用对象的 getClass()方法:String s = “aa”; Class<?> clazz = s.getClass(); 


查看JDK Doc文档Object类中的getClass对象:

getClass
public final Class<?> getClass()
   Returns the runtime class of this Object. The returned Class object is the object that is locked by static synchronized methods of the represented class.

[返回这个对象的运行期的类的实例,也就是说对于任何的Object对象,只要我调用getClass()方法,就会获得与之相关联的class对象,而且这个方法还定义为final,子类没法去重写这个方法,所以对于他的任何子类调用这个方法返回的都是与这个子类对应的class对象,这也就更加的表面这是一种运行期的行为]


2.若想通过类的不带参数的构造方法来生成对象,我们有两种方式:

a) 先获得 Class 对象,然后通过该 Class 对象的 newInstance()方法直接生成即可: 

    Class<?> classType = String.class; Object obj = classType.newInstance(); 

b) 先获得 Class 对象,然后通过该对象获得对应的 Constructor 对象,再通过该 Constructor 对的 newInstance()方法生成: 

    Class<?> classType = Customer.class; 

    Constructor cons = classType.getConstructor(new Class[]{});

    Object obj = cons.newInstance(new Object[]{}); 

4. 若想通过类的带参数的构造方法生成对象,只能使用下面这一种方式: 

    Class<?> classType = Customer.class;

    Constructor cons = classType.getConstructor(new Class[{String.class, int.class});

    Object obj = cons.newInstance(new Object[]{“hello”, 3}); 




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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值