zngjie

it2022-05-05  179

反射:重点----每天都用反射,但是每天都不写反射 Java的反射技术是java程序的特征之一,它允许运行中的Java程序对自身进行检查,或者说“自审”,并能直接操作程序的内部属性。

使用反射可以获得Java类中各个成员的名称并显示出来。简单的说,反射就是让你可以通过名称来得到对象(类,属性,方法)的技术。

反射的作用 可以通过反射机制发现对象的类型,发现类型的方法/属性/构造器 可以创建对象并访问任意对象方法和属性等

主要点:运行时探究和使用编译时未知的类

Dog d1 = new Dog();这样一个类在创造的时候经历了哪些过程呢?简单的来说类加载:由类加载器完成,类的class文件读入内存后,就会创建一个java.lang.Class对象。一旦某个类被载入JVM中,同一个类就不会再次被载入。 连接:把类的二进制数据合并到JRE中。

初始化 :JVM负责对类进行初始化,也就是对静态属性进行初始化。在Java类中,对静态属性指定初始值的方式有两种:(1)声明静态属性时指定初始值;(2)使用静态初始化块为静态属性指定初始值。

在我们上边的案例中:1.JVM利用DogClassLoader先将Dog类加载到内存,然后马上产生了一个Class类型的对象,该对象可以看成是一个模型,以后无论创建多少个Dog类的实例都是利用该模型来生成。---所以一个类所对应的Class类型的对象只有一个。

根据这个模型生成Dog类实例反射正是利用了java的这种加载方式主动完成了对象的创建及使用。

使用反射:

遵循三个步骤第一步是获得你想操作的类的 java.lang.Class 对象第二步是调用诸如 getDeclaredMethods 的方法第三步使用 reflection API 来操作这些信息

简单案例01: Class c1 = String.class; Class c2 = Class.forName("java.lang.String"); Class c3 = "abc".getClass();

实验2:通过反射做一些事情 Integer a=13; Class c=a.getClass();//获得了a的类型

案例03: Integer a=13; Class c=a.getClass(); Field[] field=c.getDeclaredFields(); for(Field f:field){ System.out.print(f.getType()+" ");\ System.out.println(f.getName()); }我们获得了Integer类中的所有属性那能不能修改呢? Dog d=new Dog(); Class clazz=d.getClass(); Field field=clazz.getDeclaredField("num"); field.set(d, 1000); System.out.println(field.get(d));

 

案例04: Class c1=Outer.class; Method[] methods=c1.getDeclaredMethods(); for(Method method:methods){ System.out.print(method.getName()+" "); System.out.print(method.getReturnType()+" "); System.out.println(method.getParameterTypes());//这里如果是数组的话该怎么处理 }获得该类中所有的方法 Dog d=new Dog(); Class clazz=d.getClass(); Method method=clazz.getDeclaredMethod("show",int.class,String.class); method.invoke(d,10,"zhangsan");

案例05: Integer a=13; Class c=a.getClass(); Class c1=Outer.class; Constructor [] constructors=c.getDeclaredConstructors(); for(Constructor constructor:constructors){ System.out.print(constructor.getName()+" "); System.out.println(Arrays.toString(constructor.getParameterTypes())); }获得所有的构造函数

 

重点:通过反射来创造类的实例

实验01:通过类名来创建类实例 Class cls=Outer.class;//obj指向的A类的对象 总体来说还是Object Object o=cls.newInstance();------------------------------------------------------注意它和我们的实例对象一样吗 Class<?> clazz=Class.forName("包名.类名"); Wode o=(Wode) clazz.newInstance();

注意点:Class.forName() 静态方法,可以利用类名在 CLASSPATH 中查找对应的类,并且装载到内存, 返回这个” class“Class.forName()加载类的过程采用” 懒惰方式,即检查发现如果已经加载了(内存中存在)就丌再加载,直接返回已经加载的类,相当于“手工”去 检查内存中是否已经加载了某个类

.newInstance()方法,会利用默认(无参数)构造器创建类实例(实例对象)

补充点:获得class对象三种方式方式一:如果一个类的实例已经得到,你可以使用 【Class c = 对象名.getClass(); 】 例: TextField t = new TextField(); Class c = t.getClass(); Class s = c.getSuperclass();

方式二:如果你在编译期知道类的名字,你可以使用如下的方法 【 Class c = JButton.class; 】 或者 Class c = Integer.TYPE;

如果类名在编译期不知道, 但是在运行期可以获得, 你可以使用下面的方法 【 Class c = Class.forName(strg); 】

在这里要注意:newInstance: 弱类型。低效率。只能调用无参构造。new: 强类型。相对高效。能调用任何public构造。newInstance()是实现IOC、反射、面对接口编程 和 依赖倒置 等技术方法的必然选择,new 只能实现具体类的实例化,不适合于接口编程。

通过反射操作对象属性

Class clss=Outer.class; Object o=clss.newInstance(); Field field=clss.getDeclaredField("num"); Object val=field.get(o); System.out.println(val);

上边的实验,我们发现用这种方式也是可以的Class cls=Outer.class;--------------------------接着上边的实验,我们发现了 Object val=field.get(o); val=15; Object val2=field.get(o); System.out.println(val);通过这种方式完全可以修改我们的属性

转载于:https://www.cnblogs.com/Bingley123/p/5458018.html

相关资源:各显卡算力对照表!

最新回复(0)