反射相关:[利用反射的各种操作都是在运行期进行的. ]1.在面向对象的世界里,万事万物皆对象.
但是java语言中,静态的成员 与基本数据类型类 不是对象.
类是不是对象? 谁的对象呢?
类是对象,任何类都是java.lang.Class类的实例对象.
2.类java.lang.Class的对象到底如何表示呢?(与普通类的对象区别)
[There is a class named 'Class'] 一个名叫Class的类.
//官方称呼为: (一个类的)类类型(Class Type).
//一个类只能有一个类类型,或者理解成,它只是Class类的一个具体的实例对象.
所以,不管通过以下三种中任何一种方式,得到同一个类的类类型都是相同的.(都是同一个Class类的实例对象).
[上面关于类类型的理解一定要把握好.]
已知一个类Foo, Foo f1=new Foo();
1.Class c1=Foo.class;[实际在告诉我们任何一个类都有一个隐含的静态成员变量class]
2.Class c2=f.getClass();[通过某个类的一个对象获取此类的类类型]
3.Class c3=Class.forName("包名.类名");[直接指定类的全称进行获取]
并且,c1==c2==c3.因为都是指Class的同一个实例对象Foo.该类称为Foo的类类型.
得到了某个类的类类型后,我们就可以通过它去创建该类的实例对象:
Foo f2 = (Foo) c1.newInstance();[前提是此类(Foo)必须要有无参构造方法]
3.Java动态加载类
1.Class.forName("类的全称").第三种途径则是动态加载类.
.不仅表示了类的类类型,还代表了是动态加载类.
.要区分开编译与运行.
.编译时刻加载类是静态加载类/运行时刻加载类是动态加载类.
public Class Office{
public static void main(String[] args){
//使用NEW关键字创建对象,是静态加载类,在编译时刻就需要
//加载所有的可能用到的类.所以相关的类不论是否用到都必须存在.
if("Word".equals(args[0]){
Word w=new Word();
w.start();
}
if("Excel".equals(args[0]){
Excel e=new Excel();
e.start();
}
}
}
但是,我们更希望在使用的时候,用到哪个类(功能)去加载哪个类,不用的不加载.那么上面的例子是做不到的.因为不论用到哪个,其他的类必须全部存在.
那么,如何解决?----动态加载类,在运行时,用到哪个类再去加载哪个类.
public Class OfficeBetter{
public static void main(String [] args){
//动态加载指定类.
Class c=Class.forName(args[0]);
OfficeAble oa=(OfficeAble)c.newInstance();
//多态:实际是哪个类,就调用实际类中此项功能.
oa.start();
}
}
//给各个类制定一个统一的标准.(多态的应用)
public interface OfficeAble{
void start();
}
这样在编译OfficeBetter时,是完全通过的.而在运行时,需要你去指定具体用到哪个类,它就会去加载这个类.(非常好的设计思想@_@)
[所以,以后功能性的类尽量用这种设计思想,尽量用动态加载.这样更新的时候,只需要添加,删除各个功能类并且让各个功能类实现这一统一的标准(接口)]
4.反射获取方法的信息(返回值类型,方法名,参数类型)
Class c1=int.class;
Class c2=String.class;
Class c3=double.class;//与下面的Double完全不同.
Class c4=Double.class;
Class c5=void.class;
基本数据类型,void都有对应的类类型.
public Class ClassUtil{
public static void PRintMethodInfo(Object obj){
//首先获取对象所属类的类类型
Class c=obj.getClass();
//获取类的类名称
system.out.println("类的名称:"+c.getName());
//java.lang.reflect.Method类,万事万物皆对象,那么任何一条方法也是这//Method类的对象.
//此方法获取的是所有的public 的函数,包括从父类继承来的方法(肯定是public方法)
Method[] methods=c.getMethods();
//此方法返回的是此类自己声明的所有方法(包括public&private方法)
Method[] methods1=c.getDeclaredMethods();
for(int i=0;i<methods.length;i++){
//得到返回值类型的类类型(int.class,void.class)
Class returnType=methods[i].getReturnType();
//得到了返回值类型的名字.
system.out.print(returnType.getName());
//得到了方法的名字.
system.out.print(methods[i].getName());
//得到方法的参数类的类类型
Class[] paramTypes=method[i].getParameterTypes();
for(int j=0;j<paramTypes.length;j++){
//得到具体某个参数类型的名字
system.out.print(paramTypes[j].getName());
}
}
}
//成员变量也是对象.
//java.lang.reflect.Field类的对象.
//此类封装了关于成员变量的操作.
//getFields():获取所有public的成员变量
//getDeclaredFields():获取所有此类自己声明的成员变量(public&private)
public static void printFieldInfo(Object obj){
Class c=obj.getClass();
Field[] fields=c.getDeclaredFields();
for(Field field:fields){
//获得此成员变量的类类型
Class fieldType=field.getType();
String typeName=fieldType.getName();
//得到成员变量的名字.
String fieldName=field.getName();
system.out.println("fieldType:"+typeName+","+"fieldName:"+fieldName);
}
}
public static void printConstructorInfo(Object object) {//1.由某个类的对象,得到 该类的 类类型.Class<?> cls=object.getClass();//2.由该类的类类型,得到该类的所有指定的构造函数.Constructor[] constructors=cls.getDeclaredConstructors();for (Constructor constructor : constructors) {System.out.print("构造器名称: "+constructor.getName()+" :参数类型:");Class[] paramTypes=constructor.getParameterTypes();for (Class class1 : paramTypes) {System.out.print(class1.getName()+";");}System.out.println();}}
}
5.方法反射来调用方法.
语法:m.invoke(obj,参数);
obj.print(参数);
//b.print(10,20);方法的反射操作是用method为进行方法调用.与b.print(10,20)效//果一样.可变参数Object...可以写成new Object[]{10,20},也可以直接写入各个参//数:10,20;
public class Test4 { /** * 学习如何获得方法对象,通过方法对象调用方法执行. * @param args */ public static void main(String[] args) { B b=new B(); Class<?> cls=b.getClass(); try { Method method=cls.getDeclaredMethod("print", new Class[]{int.class,int.class}); Object object=method.invoke(b, 10,20); Method method2=cls.getDeclaredMethod("print", new Class[]{String.class,String.class}); Object object2=method2.invoke(b, new String[]{"Manny","HaiXia"}); /** * 学习如何获得字段对象,并且更改它的值; */ Field field=cls.getDeclaredField("count"); field.setaccessible(true); field.set(b, 100); System.out.println(field.get(b)); } catch (NoSuchMethodException | SecurityException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (IllegalAccessException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (IllegalArgumentException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (InvocationTargetException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (NoSuchFieldException e) { // TODO Auto-generated catch block e.printStackTrace(); } }}class B{ private int count; public void printCount() { System.out.println(count); } 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()); }}6.通过反射了解集合泛型 的本质;/** * 集合泛型 的本质是编译期起检查作用的.而反射是在运行期进行的,自然就绕过了编译期的检查. * @param args */ public static void main(String[] args) { ArrayList<String> list1=new ArrayList<>(); ArrayList list2=new ArrayList(); list2.add("hello"); list1.add("hello"); list2.add(20); Class cls1=list1.getClass(); Class cls2=list2.getClass(); //运行期时,list1&list2的类的类型没有区别;即不存在了泛型这个检查; System.out.println(cls1==cls2); try { Method method=cls1.getDeclaredMethod("add",Object.class); method.invoke(list1 , 20); System.out.println(list1.size()); //取出时仍然要用反射,绕过编译期的泛型检查. //所以泛型不仅要检查放的数据类型是否符合泛型,还要检查拿出的数据类型是否符合泛型; Method method2=cls1.getDeclaredMethod("get", int.class); System.out.println(method2.invoke(list1, 1)); /*for(int i=0;i<list1.size();i++){ System.out.println(list1.get(i)); }*/ /*Method[] eMethods=cls1.getDeclaredMethods(); for (Method method : eMethods) { System.out.print(method.getName()+";"); Class[] paraTypes = method.getParameterTypes(); for (Class class1 : paraTypes) { System.out.print(class1.getName()); } System.out.println(); }*/ } catch (SecurityException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (IllegalArgumentException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (NoSuchMethodException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (IllegalAccessException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (InvocationTargetException e) { // TODO Auto-generated catch block e.printStackTrace(); } }
新闻热点
疑难解答