关于class类反射知识小总结

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与上面代码类似

方法的反射

  1. 如何获取某个方法
    方法的名称和方法的参数列表才能唯一决定某个方法
  2. 方法反射的操作
    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
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值