关于class类反射知识小总结

it2022-05-05  79

class类

1、在面向对象的世界里,万事万物皆对象 我们提供的每一个类也是对象

问:类是谁的对象? 答:类是对象,类是java.lang.class类的实例对象 写一个student类,student类是class类的对象

There is a class named Class

2、这个对象怎么表示?

public class ClassDemo1 { public static void main(String[] args) { //Foo的实例对象如何表示 Foo foo1 = new Foo(); //Foo这个类也是一个实例对象,class类的实例对象,如何表示呢 //不能通过New //只有Java虚拟机才能创建class类的实例对象 //任何一个类都是class的实例对象,这个实例对象有三种表示方式 //第一种表示方式-->实际在告诉我们任何一个类都有一个隐含的静态成员变量class Class c1 = Foo.class; //第二种表达方式,已知道该类的对象通过getClass的方法 Class c2 = foo1.getClass(); //官网 c1,c2表示了Foo类的类类型(class type) //Foo这个类本身就是一个对象,是class对象 //但是Foo类也有一个对象 //这个对象(类)称为该类的类类型 //class type两种翻译 1:类类型 2:类的实例对象 System.out.println(c1 == c2); //不管c1或者c2都代表了Foo类的类类型,一个类只可能是class类的一个实例对象 //第三种方式 Class c3 = null; try { c3 = Class.forName("com.imooc.reflect.Foo"); } catch (ClassNotFoundException e) { // TODO Auto-generated catch block e.printStackTrace(); } System.out.println(c2 == c3); //我们完全可以通过类的类类型创建该类的对象--->通过c1 or c2 or c3 创建Foo的实例 try { //做强制类型转换 Foo foo = (Foo)c1.newInstance(); //需要有无参数的构造方法 foo.print(); } catch (InstantiationException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (IllegalAccessException e) { // TODO Auto-generated catch block e.printStackTrace(); } } } class Foo{ void print() { System.out.println("foo"); } }```

动态加载类

Class类 Class.forName(“类的全称”)

不仅表示了类的类类型,还代表了动态加载类请大家区分编译、运行(使用cmd)编译时刻加载类是静态加载类(通过new)、运行时刻加载类是动态加载类

动态加载类其实就是当程序的部分类的功能丧失的时候,任何能够加载已经完成了的类的程序,通过class.forName()方法可得

new创建对象 是静态加载类,在编译时刻就需要加载所有可能使用到的类 通过动态加载类可以解决这个问题

基本的数据类型也对应有类类型,void关键字都存在类类型

class类的基本API操作

打印类的信息,包括类的成员函数、成员变量、该对象所属类的信息 获取方法的信息的步骤: 1、获取类的类类型(.class) 2、Java的reflect包里面有一个Method类,有个getMethods的方法,一个成员方法就是一个Method对象 其中:getMethods()方法是获取所有public的函数,包括父类继承而来的 getDeclaredMethods()方法获取所有该类自己声明的方法,不问访问权限

public class ClassUtil { /* * 打印类的信息,包括类的成员函数、成员变量 * 该对象所属类的信息 */ public static void printClassMessage(Object obj) { //要获取类的信息, 首先要获取类的类类型 Class c = obj.getClass(); //传递的是哪个子类的对象,c是该子类的类类型 System.out.println("类的名称是:" + c.getClass()); /* * Method类,方法对象 * 一个成员方法就是一个Method对象 * getMethods()方法获取的是所有Public的函数,包括父类继承而来的 * getDeclaredMethods()获取所有该类自己声明的方法,不问访问权限 */ Method[] ms = c.getMethods(); //c.getDeclaredMethods() c.getDeclaredMethods(); for(int i = 0; i < ms.length; i++) { //得到方法的返回值类型的类类型 //如果返回的是String 即返回String.class Class returnType = ms[i].getReturnType(); System.out.print(returnType.getName() + " "); //得到方法的名称 System.out.print(ms[i].getName() + "("); //获取参数类型 -->得到的是参数列表的类型的类类型 Class[] paramTypes = ms[i].getParameterTypes(); for(Class class1 : paramTypes) { System.out.print(class1.getName() + ","); } System.out.println(")"); } } }

其中还有关于构造函数等的反射的api与上面代码类似

方法的反射

如何获取某个方法 方法的名称和方法的参数列表才能唯一决定某个方法方法反射的操作 method.invoke(对象,参数列表) 例子: mport java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; public class MethodDemo1 { public static void main(String[] args) { //要获取print(int,int)方法 // 1、要获取一个方法就是获取类的信息,获取类的信息首先获取类的类类型 A a1 = new A(); Class c = a1.getClass(); /* * 2、获取方法 名称和参数列表来决定 * getMethod()获取的是public的方法 * getDeclaredMethod()自己声明的方法 * 其中传入的参数是方法名+数组 */ try { Method m = c.getDeclaredMethod("print", new Class[] {int.class,int.class}); //方法的反射操作 //a1.print(10, 20); //方法的反射操作是使用m对象来进行方法的调用 和a1.print调用方法的效果完全相同 //方法如果没有返回值返回null,有返回值返回具体的返回值 Object o = m.invoke(a1, new Object[] {10,20}); } catch (NoSuchMethodException e) { e.printStackTrace(); } catch (SecurityException e) { e.printStackTrace(); } catch (IllegalAccessException e) { e.printStackTrace(); } catch (IllegalArgumentException e) { e.printStackTrace(); } catch (InvocationTargetException e) { e.printStackTrace(); } } } 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()); } }

关于类类型的进一步解释

Class类被创建后的对象就是Class对象,注意Class对象表示的是自己手动编写类的类型信息,比如创建一个shape类,那么,JVM就会创建一个shapes对应的Class类的Class的对象,该Class对象保存了Shapes类相关的类型信息。实际上Java中每个类都有一个Class对象,每当我们编写并且编译一个新创建的类就会产生一个对应的Class对象并且这个Class对象会被保存在同名.class文件里(编译后的字节码文件或者文件保存的就是Class对象) 问题是:那么为什么需要这样一个Class对象呢? 是这样的,当我们new一个新对象或者引用静态成员变量时,Java虚拟机中的类的加载器子系统会将对应Class对象加载到JVM中,然后JVM再根据这个类型信息相关的Class对象创建我们需要的实例对象或者提供静态变量的引用值。 需要特别注意的是,手动编写的每个class类,无论创建多少个实例对象,在JVM中都只有一个Class对象,即在内存中每个类有且只有一个相对应的Class对象。 所以我们可以得到的信息是:

Class类也是类的一种,与class关键字不同手动编写的类被编译后会产生一个Class对象,其表示的是创建类的类型信息,而且这个Class对象保存在同名.class的文件中(字节码文件),比如创建一个Shapes类,编译Shapes类后会创建其包含Shapes类相关类型的Class对象,并保存在Shapes.class字节码文件中每个通过关键字class标识的类,在内存中有且只有一个与之对应的Class对象来描述其类型信息Class类只存私有构造函数,因此对应Class对象只有JVM创建和加载Class类的对象作用是运行时提供或获得某个对象的类型信息。

最后一点需要阐明反射的作用功能: 1、在运行时判断任意一个对象所属的类 2、在运行时构造任意一个类的对象 3、在运行时判断任意一个类所具有的成员变量和方法 4、在运行时调用任意一个对象的方法 5、生成动态代理

参考博客: 添加链接描述


最新回复(0)