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与创建对象
3.对象转换
//有两个类,它们的字段完全一致,使用反射快速地实现对象复制
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;
}