1.获得class的三种方式
package reflect;
/**
*
* @author liguoping
*
*/
public class ClassDemo1 {
public static void main(String[] args) {
// 第一种方式,类名.class
Class class1 = Foo.class;
// 第二种方式,实例.getClass()
Foo foo1 = new Foo();
Class class2 = foo1.getClass();
// 第三种方式 Class.forname("类的全限定类名") 动态加载类,在运行时刻加载
Class class3 = null;
try {
class3 = Class.forName("reflect.Foo");
} catch (ClassNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println(class1==class2);
System.out.println(class2==class3);
}
}
class Foo{}
创建实例,必须要用无参的构造方法,这里可以强制转换成一个公共的接口,子类实现接口.这样在需求改变的时候只需要更改子类实现即可.需要强调的是Class.forName创建实例是动态加载的,只有在运行是才会加载.
Foo foo = (Foo)class1.newInstance();
foo.print();
2 .Class 类的基本操作
package reflect;
import java.lang.reflect.Method;
/**
* 打印类的信息,包括类的成员函数,成员变量
*
* @author liguoping
*
*/
public class ClassUtil {
public static void printClassMessage(Object obj) {
Class c = obj.getClass();
// 获取类的名称
System.out.println("类的名称是:" + c.getName());
/**
* Method类,方法对象 一个成员方法就是一个Method对象
* getMethods()方法获取的是所有的public函数,包括父类继承来的方法
* getDeclaredMethods()获取的是所有该类自己声明的方法,不问访问权限
*
*/
Method[] methods = c.getMethods();
for (Method method : methods) {
// 得到方法名称的类类型,例如String.class
Class returnType = method.getReturnType();
System.out.print(returnType+" ");
String methodName = method.getName();
System.out.print(methodName + "(");
// 获得参数列表的类型
Class[] parameterTypes = method.getParameterTypes();
for (Class class1 : parameterTypes) {
System.out.print(class1.getName()+",");
}
System.out.println(")");
}
}
public static void main(String[] args) {
String hello = "Hello World";
ClassUtil.printClassMessage(hello);
}
}
成员变量和构造函数同上,class.getFields()和class,class.getConstructors()
java集合中的泛型都是只在编译阶段有效的,也就是仅仅为了防止开发人员错误的加入不同类型的数据到集合中去,但是一旦过了编译阶段,其实集合的泛型是去泛型化的,通过反射可以验证这一点,因为反射的所有操作都是动态的,都是在编译完成以后进行的,这样在集合中就可以添加任何类型的元素,正好验证了集合的泛型在编译以后是去泛型化的。