RTTI 运行时类型信息 与 Reflect 反射

RTTI,Run Time Type Information,运行时类型信息。

要理解RTTI在java中的工作原理,必须知道 类型信息 在 运行时 是如何表示的。每个类都有一个字段“Class class;”,好晕啊,类名和对象名一样

每当编写并编译了一个新类,就会产生一个Class对象,被保存在同名的.class文件中。JVM的类加载器会去用它。

1.Class

public final class Class<T> implements java.io.Serializable, GenericDeclaration,Type,AnnotatedElement{}

这是Class类的定义。

Class<?> java.lang.Class.forName(String className)

这个静态方法可以取得Class对象的引用,参数必须为完全限定名。

String java.lang.Class. getSimpleName()
不含包名的类名。
String java.lang.Class. getName()

全限定的类名。

java.lang.Class#getGenericSuperclass()

获取带有泛型信息的Type. 详见泛型章节.

1.1 构造函数

java.lang.reflect.Constructor<T>

代表类型T的构造函数。

Constructor<T> java.lang.Class.getDeclaredConstructor(Class<?>... parameterTypes) 

获得构造函数。

Object java.lang.reflect.Constructor.newInstance(Object... initargs) 

通过构造函数获得新对象。

1.2函数

java.lang.reflect.Method

表示类或接口的一个方法。
Method java.lang.Class. getMethod(String name, Class<?>... parameterTypes) throws NoSuchMethodException, SecurityException
得到当前类的指定方法。
Object java.lang.reflect.Method. invoke(Object obj, Object... args) throws IllegalAccessException, IllegalArgumentException, InvocationTargetException

在对象obj上调用这个方法。

void java.lang.reflect.AccessibleObject.setAccessible(boolean flag)

Field与Method类都继承了AccessibleObject。所以可以使用这个方法将访问权限从private改为public,再干想干的事,多棒啊。

1.3字段

java.lang.reflect.Field

表示类或接口的一个字段。

Field[] java.lang.Class.getFields()

返回所有public权限的字段。

Field java.lang.Class.getField(String name)
返回名为name的Field对象,只对public权限的字段有效。

Field[] java.lang.Class.getDeclaredFields()

返回所有声明的字段,即便private权限也有效。

Field java.lang.Class.getDeclaredField(String name) 

返回名为name的Field对象,即便private权限也有效。
double java.lang.reflect.Field.getDouble(Object obj) 
一批类似方法有getDouble\getInt\getLong等。返回obj对象的这个字段的值。
Object java.lang.reflect.Field.get(Object obj)
对于非基本类型,返回obj对象的这个字段的值。

//: generics/LatentReflection.java
// Using Reflection to produce latent typing.
import java.lang.reflect.*;

import static net.mindview.util.Print.*;

interface Performs {
	void speak();
	void sit();
} // /:~

class Robot implements Performs {
	@Override
	public void speak() {
		print("Click!");
	}
	@Override
	public void sit() {
		print("Clank!");
	}
	public void oilChange() {
	}
}

// Does not implement Performs:
class Mime {
	public void walkAgainstTheWind() {
	}
	public void sit() {
		print("Pretending to sit");
	}
	public void pushInvisibleWalls() {
	}
	public String toString() {
		return "Mime";
	}
}

// Does not implement Performs:
class SmartDog {
	public void speak() {
		print("Woof!");
	}
	public void sit() {
		print("Sitting");
	}
	public void reproduce() {
	}
}

class CommunicateReflectively {
	public static void perform(Object speaker) {
		Class<?> spkr = speaker.getClass();
		try {
			try {
				Method speak = spkr.getMethod("speak");
				speak.invoke(speaker);
			} catch (NoSuchMethodException e) {
				print(speaker + " cannot speak");
			}
			try {
				Method sit = spkr.getMethod("sit");
				sit.invoke(speaker);
			} catch (NoSuchMethodException e) {
				print(speaker + " cannot sit");
			}
		} catch (Exception e) {
			throw new RuntimeException(speaker.toString(), e);
		}
	}
}

public class LatentReflection {
	public static void main(String[] args) {
		CommunicateReflectively.perform(new SmartDog());
		CommunicateReflectively.perform(new Robot());
		CommunicateReflectively.perform(new Mime());
	}
} 
/*
 * Woof!
Sitting
Click!
Clank!
Mime cannot speak
Pretending to sit
 */
//使用反射,达到调用私有构造函数的目的
import java.lang.reflect.Constructor;

 class Phone {
	int price;
	String brand;
	private Phone(){
		
	}
	private Phone(int price,String brand){
		this.price = price;
		this.brand = brand;
	}
	@Override
	public String toString() {
		return price + "\t"+brand;
	}
	
}
 public class ReflectTest {
		/*通过Constru.newInstance()创建新的类示例*/ 
		private void newInstanceByConstructor(){ 
			try {
				/*可以使用相对路径,同一个包中可以不用带包路径*/ 
				Class c = Class.forName("Phone"); 
				/*以下调用无参的、私有构造函数*/ 
				
				Constructor c0=c.getDeclaredConstructor(); 
				c0.setAccessible(true); 
				
				Phone po=(Phone)c0.newInstance(); 
				System.out.println("不带参的构造函数\t"+po);
				
				/*以下调用带参的、私有构造函数*/ 
				Constructor c1=c.getDeclaredConstructor(new Class[]{int.class,String.class}); 
				c1.setAccessible(true); 
				Phone p1=(Phone)c1.newInstance(new Object[]{1,"诺基亚"}); 
				System.out.println("带参的构造函数\t"+p1);
			} catch (Exception e) { 
				e.printStackTrace(); 
			} 
		}
		public static void main(String[] args) throws Exception{ 
			ReflectTest b=new ReflectTest(); 
			System.out.println("通过Constructor.newInstance()调用私有构造函数:"); 
			b.newInstanceByConstructor(); 
		} 
 }
 /*通过Constructor.newInstance()调用私有构造函数:
不带参的构造函数	0	null
带参的构造函数	1	诺基亚
*/

2.获取class与创建对象

微笑问:有哪些方法可以获得一个类的Class对象呢?
答:有三种,class.forName(‘类的完全限定名’),类名.class,对象.getClass()。
微笑问:java创建对象的方法有几种?
答:4中。new 一个对象,反序列化一个对象,通过clone()得到对象,通过反射newInstance()创建对象。

3.对象转换

两个类A与B,字段完全一致,现有 A的对象a,如何快速构造一个B类的b对象?
//有两个类,它们的字段完全一致,使用反射快速地实现对象复制
public static RulePojo pojoTranslateFun(RulePojoOld rulePojoOld) throws IllegalArgumentException, IllegalAccessException, NoSuchFieldException, SecurityException {
	RulePojo obj=new RulePojo();
	Class<?> newClass=obj.getClass();
	Class<?> oldClass=rulePojoOld.getClass();
	Field[] fieldArr=newClass.getFields();
	for(Field newField:fieldArr){
		Field oldField=oldClass.getField(newField.getName());
		newField.set(obj, oldField.get(rulePojoOld));
	}
	return obj;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值