Class类的使用
类是java.lang.class类的实例对象(称为类类型 class type),而这个实例对象有三种表示方式
-第一种表达方式:任何一个类都有一个隐含的静态成员变量
Class c1 = Foo.class;
-第二种表达方式:通过对象的getClass的方法获取
Class c2 = foo1.getClass();
-第三种表达方式:通过Class.forName()获取
Class c3 = null;
c3 = Class.forName(“类的全称”);
-c1/c2/c3都代表了class type ,一个类只可能是class类的一个实例对象
System.out.println(c1==c2);
System.out.println(c1==c3);
输出都为true
-可以通过类类型创建该类的实例对象(需要有无参数的构造方法)
Foo foo = (Foo)c1.newInstance();
动态加载类与静态加载类
-编译时刻加载的类为静态加载类,运行时刻加载的类为动态加载类
-new 创建对象的静态加载类,在编译时刻就需要加载所有可能使用到的类
静态加载时会加载所有可能用到的类,若部分类不存在则会报错
-通过Class.forName()获取类为动态加载
动态加载时按需要加载,若用到的类不存在则报错
动态加载时要通过接口来实现加载(软件小规模的在线升级往往是对实现了接口的类进行修改)
方法的反射
Class基本API
-获取类的class type
Class c = obj.getClass();
-获取类的名称
c.getName();
-获取方法(获取了包括父类的方法)
Method[] ms = c.getMethods();
-获取方法(自己声明的方法,不包括父类的方法)
Method[] ms = c.getDeclaredMethods();
-得到方法的返回值类型的class type
ms[i].getReturnType();
-获取方法名
ms[i].getName();
-获取方法参数类型(得到参数类的class type)
Class[] paramType = ms[i].getParamTypes();
-方法的反射小demo
A a1 = new A();
Class c = a1.getClass();
// Method m = c.getMethod("print",new Class[]{int.class,int.class});
Method m = c.getMethod("print",int.class,int.class});
// 没有返回值返回null,有返回值返回具体的返回值
Ocject obj = m.invoke(a1,new Object[]{10,20});
// 下面的代码等同于上面
Ocject obj = m.invoke(a1,10,20);
class A{
public void print(int a , int b){
System.out.println(a+b);
}
public void print(String a , String b){
System.out.println(a.toUpperCase()+b.toLowerCase());
}
}
成员变量的反射
-获取public成员变量的信息
Field[] fs = c.getFields();
-获取该类自己声明的成员变量的信息
Field[] fs = c.getDeclaredFields();
-获得成员变量的class type
Class fieldType = field.getType();
String typename = fieldType.getName();
-获得成员变量的名称
String fieldName = field.getName();
构造函数的反射
-构造函数也是对象
-java.lang.Constructor中封装了构造函数的信息
获取所public得构造方法
Constructor[] cs = c.getConstructors();
获取自己声明的构造方法
Constructor[] cs = c.getDeclaredConstructors();
获得构造函数的参数列表的classtype
Class[] paramTypes = cs.getParameterTypes();
通过Class,Method来认识泛型本质
-集合的泛型是防止进行错误输入的
-但泛型的本质是相同的
-Java的泛型为伪泛型
-一个类只可能是class类的一个实例对象
ArrayList list = new ArrayList();
ArrayList<String> list1 = new ArrayList<String>();
list1.add("hello");
//list1.add(20);该句会报错
Class c1 = list1.getClass();
Class c2 = list1.getClass();
System.out.println(c1==c2);
-打印结果为true
-反射的操作都是编译以后的操作,在运行时刻执行的
-c1/c2的结果返回为true说明编译后的结果是去泛型化的
-Java中的泛型的是防止错误输入的,只在编译阶段有效,绕过编译就无效了
-可通过方法的反射操作绕过编译进行操作
-以下为验证代码
Method m = c2.getMethod("add",Object.class);
m.invoke(list1,100);
System.out.println(list);
-代码输出[hello,100]
-说明绕过编译即可绕过泛型
-不可同foreach遍历,因为进行遍历时会以String类型进行遍历会抛出异常