Java Class类

Class类的作用
Class类是一个特殊类,它用于表示JVM运行时类或接口的信息。
Class类提供很多方法用于获取类的各种信息,比如获取类名、判断该类是否是一个接口还是普通类等等。
在Java中枚举类是一种类,而注解是一个接口,数组也是一个类;Java原始类型(boolean, byte, char, short, int, long, float, and double)和关键字void也被表示为Class的对象。

在每一个基本类型的包装类中都有一个共有的静态变量,例如Integer:
public static final Class TYPE = (Class) Class.getPrimitiveClass(“int”);
TYPE就是这个基本类型的Class对象表示。

Class类的父类

Class类是java中的一个类和其他非继承类一样,默认的父类也是Object。

public class ClassParentTest {
	public static void main(String[] args) {
		boolean assignableFrom = Object.class.isAssignableFrom(Class.class);
		System.out.println(assignableFrom);
	}
}

Class#isAssignableFrom(Class<?> cls)方法用于判断cls的实例能否赋值给该Class的引用;换句话说,该方法可以用来判断cls类是否是该Class的子类或者如果Class是接口表示cls是否实现了该接口。
上边那段代码将输出true,说明Class类的父类是Object类

Class类的forName方法

用于手动加载一个类,该方法是一个公共静态方法,有多个重载。
方法签名:

public static Class<?> forName(String className)
public static Class<?> forName(String name, boolean initialize,ClassLoader loader)
        throws ClassNotFoundException
//下面这个是JDK9新增加的,用于从模块中加载一个类,不对类进行初始化
public static Class<?> forName(Module module, String name) 
//第一个和第二个都是调用下面的native方法forName0来加载类
private static native Class<?> forName0(String name, boolean initialize,
                                        ClassLoader loader,
                                        Class<?> caller)

关于参数boolean initialize
注意这里的参数boolean initialize表示是否对类进行初始化,这里的初始化指的是类加载过程中收集静态代码块和静态变量形成的方法的初始化,不是指类构造函数的执行(构造函数的执行是在类生成实例的时候执行的,是对实例变量的初始化,不要搞混)。

class A{
    private static final int i = 0;//#1
    private static final String str = "hello";//#2
    static {
        System.out.println("static block!"); //#3
    }
    public A(){
        System.out.println("constructor!");
    }
}

在类加载的过程中,会将#1,#2,#3按照顺序收集在一起形成<clinit>方法,为了帮助理解,可以表示成下面的伪代码:

<clinit>() {
	private static final int i = 0;//#1
	private static final String str = "hello";//#2
	System.out.println("static block!"); //#3
 }

参数boolean initialize就是来表示是否在类加载的时候执行这个<clinit>方法!

public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, 			               IllegalAccessException, InvocationTargetException, InstantiationException {
        Class<A> aClass = (Class<A>) Class.forName("com.company.A",
                true,Test4.class.getClassLoader());
}

上边的代码将参数initialize设置为true,执行会输出static block!,说明执行了类的初始化!
如果改成false,将不会输出static block!,也就是不执行类的初始化,这将类的初始化延迟到第一次创建该类的实例!

String hello = "hello";
boolean isStr = String.class.isInstance(hello);


类的构造函数是类实例化时执行的。

A a = aClass.getConstructor().newInstance();

通过以上方式创建A类的实例将输出constructor!

Class类的isInstance和isAssignableFrom方法

这两个方法都是native方法。

isInstance

public native boolean isInstance(Object obj);

isInstance用于判断obj对象是否是该Class或该Class子类的一个实例。

String hello = "hello";
boolean isStr = String.class.isInstance(hello);

isStrtrue

boolean is = Number.class.isInstance(Integer.valueOf(1));

istrue,因为IntegerNumber的子类。
该方法还可以用于类型转换时,为了避免对象的转换异常,进行类型检查:

public void method(Object str){
		String str1;
		if(String.class.isInstance(str)){
			str1 = (String) str;
		}
}

但是我们一般不会这样写,因为java给我提供了instanceof

isAssignableFrom

public native boolean isAssignableFrom(Class<?> cls);

该方法用于判断cls的实例能否赋值给该Class的引用;换句话说,该方法可以用来判断cls类是否是该Class的子类或者如果Class是接口表示cls是否实现了该接口。

  boolean is = Number.class.isAssignableFrom(Integer.class);
  boolean is2 = List.class.isAssignableFrom(ArrayList.class);

is和is2都是true,因为Integer继承了Number,ArrayList间接的实现了List接口。

看Spring中的一段代码(代码摘自MapMethodProcessor类,HandlerMethodArgumentResolver的实现类,用于自动注入Controller方法参数):

@Override
public boolean supportsParameter(MethodParameter parameter) {
	return Map.class.isAssignableFrom(parameter.getParameterType()) &&
	parameter.getParameterAnnotations().length == 0;
}

它使用isAssignableFrom方法来判断方法参数是否是Map类型。

Class类的isXXXX

Class类还提供了isXXXX的方法,这些方法大多用于判断Class的类型。

方法名方法签名作用
isInterfacepublic native boolean isInterface()判断该Class是否是一个接口
isArraypublic native boolean isArray()判断该Class是否是一个数组 (数组在Java中也是类)
isPrimitivepublic native boolean isPrimitive()判断该Class是否是基本类型
isAnnotationpublic boolean isAnnotation()判断该Class是否是一个注解,如果该方法返回true,isInterface方法也将返回true,因为注解是特殊的接口
isSyntheticpublic boolean isSynthetic()当且仅当该Class是Java语言规范定义的合成类时为true。
isAnonymousClasspublic boolean isAnonymousClass()当且仅当该Class是匿名类时返回true。Runnable runnable = new Runnable() { public void run() { }};boolean is = runnable.getClass().isAnonymousClass();为true
isLocalClasspublic boolean isLocalClass()当且仅当该Class是局部类时返回true。
isMemberClasspublic boolean isMemberClass()当且仅当该Class是一个类的成员返回true
isAnnotationPresentpublic boolean isAnnotationPresent(Class<? extends Annotation> annotationClass)判断该类是否有注解annotationClass
isEnumpublic boolean isEnum()判断是否是枚举类

Class类还有其他方法,但常用的也就这些了

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Bridge Fish

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值