Class类
Class类是用来保存Java虚拟机(JVM)运行时类型信息的类,其内部封装了一个对象或接口运行时的方法、变量、接口、类名、类修饰符等信息。
Class类没有公共构造方法。Class对象是在加载类时由JVM以及通过调用类加载器中的defineClass方法自动构造的,因此不能显式地声明一个Class对象。JVM为每个类(型)管理一个独一无二的Class对象。当程序运行时,JVM首先检查所要加载的类对应的Class对象是否已经加载,如果没有加载,JVM就会根据类名查找.class文件,并将其Class对象载入。
基本的Java类型(boolean、byte、char、short、int、long、float和double)和关键字void也都对应一个Class对象。每个数组属于被映射为Class对象的一个类,所有具有相同元素类型和维数的数组都共享该Class对象(详见扩展内容章节)。
一般某个类的Class对象被载入内存,它就用来创建这个类的所有对象。
Class类的常用方法
获取Class对象的方法
- .class
Class userClass = User.class;
- Class.forName()
Class.forName()方式适用于运行时动态获取Class对象,只需将类的完全限定名作为forName方法的参数即可获取
try{
Class userClass= Class.forName("com.most.User");
}
catch(ClassNotFoundException e){
System.out.println("找不到User类");
}
- 实例对象的getClass方法
User user = new User();
Class userClass = user.getClass();
获取类的信息
- 获取类名
- getName():获取包含包信息的类名
- getTypeName():获取类的类型名称,包含包信息
- 除数组外,getTypeName()和getName()获取的值相同
- getSimpleName():只是获取类名,不包含包信息,是对getTypeName()获取的字符串的截取
package com.most;
public class User {
public static void main(String[] args) {
Class userClass = User.class;
System.out.println("------------------普通类类名------------------");
System.out.println(userClass.getName());
System.out.println(userClass.getTypeName());
System.out.println(userClass.getSimpleName());
Class petClass = Pet.class;
System.out.println("------------------内部类类名------------------");
System.out.println(petClass.getName());
System.out.println(petClass.getTypeName());
System.out.println(petClass.getSimpleName());
Pet[] pets = new Pet[2];
Class<? extends Pet[]> petsClass = pets.getClass();
System.out.println("------------------数组类类名------------------");
System.out.println(petsClass.getName());
System.out.println(petsClass.getTypeName());
System.out.println(petsClass.getSimpleName());
}
private static class Pet {
}
}
输出结果
------------------普通类类名------------------
com.most.User
com.most.User
User
------------------内部类类名------------------
com.most.User1$Pet
com.most.User1$Pet
Pet
------------------数组类类名------------------
[Lcom.most.User1$Pet;
com.most.User1$Pet[]
Pet[]
- 获取类修饰符
- 类修饰符有public、private等类型,getModifiers()可以获取一个类的修饰符,但是返回的结果是int,结合Modifier提供的方法,就可以确认修饰符的类型
package com.most;
import java.lang.reflect.Modifier;
public class User {
public static void main(String[] args) {
Class userClass = User.class;
System.out.println("------------------普通类类修饰符------------------");
System.out.println(userClass.getModifiers());
System.out.println(Modifier.isPublic(userClass.getModifiers()));
Class petClass = Pet.class;
System.out.println("------------------内部类类修饰符------------------");
System.out.println(petClass.getModifiers());
System.out.println(Modifier.isPublic(petClass.getModifiers()));
}
private class Pet{
}
}
输出结果
------------------普通类类修饰符------------------
1
true
------------------内部类类修饰符------------------
2
false
获取包信息
- getPackage():获取包信息
package com.most;
public class User {
public static void main(String[] args) {
Class petClass = Pet.class;
System.out.println("------------------包信息------------------");
System.out.println(petClass.getPackage());
}
private class Pet {
}
}
输出结果
------------------包信息------------------
package com.most
获取父类的Class对象
- getSuperclass():返回直接继承的父类,不包含泛型参数
- getGenericSuperclass():返回直接继承的父类,包含泛型参数
package com.most;
import java.lang.reflect.Type;
import java.util.List;
public class User {
public static void main(String[] args) {
Class petClass = Pet.class;
Class superclass = petClass.getSuperclass();
Type genericSuperclass = petClass.getGenericSuperclass();
System.out.println("------------------父类信息------------------");
System.out.println(superclass.getName());
System.out.println(superclass.getTypeName());
System.out.println(genericSuperclass.getTypeName());
}
private static class Pet extends Animal<String> {
}
private static class Animal<T> {
private List<T> foods;
}
}
输出结果
------------------父类信息------------------
com.most.User$Animal
com.most.User$Animal
com.most.User$Animal<java.lang.String>
获取接口信息
- getInterfaces():返回直接实现的接口数组,不包含泛型参数
- getGenericInterfaces():返回直接实现的接口数组,包含泛型参数
import java.lang.reflect.Type;
import java.util.List;
public class User {
public static void main(String[] args) {
Class petClass = Pet.class;
Class[] interfaces = petClass.getInterfaces();
Type[] genericInterfaces = petClass.getGenericInterfaces();
System.out.println("------------------接口信息------------------");
for (Class anInterface : interfaces) {
System.out.println(anInterface.getTypeName());
}
System.out.println("------------------泛型接口信息------------------");
for (Type genericInterface : genericInterfaces) {
System.out.println(genericInterface.getTypeName());
}
}
private static class Pet extends Animal<String> implements Flyable<Integer> {
}
private static class Animal<T> {
private List<T> foods;
}
private interface Flyable<T> {
}
}
输出结果
------------------接口信息------------------
com.most.User$Flyable
------------------泛型接口信息------------------
com.most.User$Flyable<java.lang.Integer>
获取构造函数信息
- 获取构造函数
- getConstructor(Class<?>... types):获取声明为public的参数为传入参数列表的构造函数
- getDeclaredConstructor(Class<?>... types):获取所有声明的参数为传入参数列表的构造函数,和修饰符无关
- getConstructors():获取所有声明为public的构造函数
- getDeclaredConstructors():获取所有声明的构造函数,和修饰符无关
- 获取构造函数的参数
- getParameterTypes():获取指定构造函数的参数类型数组
package com.most;
import java.lang.reflect.Constructor;
public class User {
public static void main(String[] args) throws Exception {
Class petClass = Pet.class;
Constructor[] constructors = petClass.getConstructors();
Constructor[] declaredConstructors = petClass.getDeclaredConstructors();
Constructor specific = petClass.getConstructor(String.class);
System.out.println("------------------所有public构造函数------------------");
for (Constructor constructor : constructors) {
System.out.println(constructor.getName());
}
System.out.println("------------------所有声明的构造函数------------------");
for (Constructor constructor : declaredConstructors) {
System.out.println(constructor.getName());
}
System.out.println("------------------指定参数的构造函数------------------");
System.out.println(specific.getName());
System.out.println("------------------指定参数的构造函数的参数------------------");
Class[] parameterTypes = specific.getParameterTypes();
for (Class parameterType : parameterTypes) {
System.out.println(parameterType.getName());
}
}
private static class Pet {
private String name;
private Pet() {
}
public Pet(String name) {
this.name = name;
}
}
}
输出结果
------------------所有public构造函数------------------
com.most.User$Pet
------------------所有声明的构造函数------------------
com.most.User$Pet
com.most.User$Pet
------------------指定参数的构造函数------------------
com.most.User$Pet
------------------指定参数的构造函数的参数------------------
java.lang.String
获取方法信息(包括成员方法和类方法)
- 获取方法
- getMethod(Class<?>... types):获取声明为public的参数为传入参数列表的方法
- getDeclaredMethod(Class<?>... types):获取声明的参数为传入参数列表的方法,和修饰符无关
- getMethods():获取到所有public修饰的方法,返回Method[]数组
- getDeclaredMethods():获取所有声明的方法,和修饰符无关
- 注意:无参的getMethods()和getDeclaredMethods()都只能获取到类声明的方法,不能获取到继承父类的方法,带参的getMethod()和getDeclaredMethod()可以获取到继承自父类的方法
- 获取方法参数
- getParameterTypes():获取指定方法的参数类型数组
- 获取方法返回类型
- getReturnType():获取指定方法的返回类型
package com.most;
import java.lang.reflect.Method;
public class User {
public static void main(String[] args) throws Exception {
Class petClass = Pet.class;
System.out.println("------------------所有声明方法------------------");
Method[] methods = petClass.getDeclaredMethods();
for (Method method : methods) {
System.out.println(method.getName());
}
Method specific = petClass.getMethod("sayHi", String.class);
System.out.println("------------------指定方法------------------");
System.out.println(specific.getName());
System.out.println("------------------参数类型------------------");
Class<?>[] parameterTypes = specific.getParameterTypes();
for (Class<?> parameterType : parameterTypes) {
System.out.println(parameterType.getName());
}
System.out.println("------------------返回类型------------------");
Class<?> returnType = specific.getReturnType();
System.out.println(returnType.getName());
}
private static class Pet extends Animal {
private String name;
public void showName() {
System.out.println(name);
}
public static void sayHello() {
System.out.println("Hello!");
}
@Override
public String toString() {
return "Pet[name=" + name + "]";
}
}
private static class Animal {
public String sayHi(String name) {
return "Hi! " + name;
}
}
}
输出结果
------------------所有声明方法------------------
toString
showName
sayHello
------------------指定方法------------------
sayHi
------------------参数类型------------------
java.lang.String
------------------返回类型------------------
java.lang.String
获取变量信息(包括成员变量和类变量)
- 获取变量
- getField(String type):获取声明为public的参数为传入参数列表的方法
- getDeclaredField(String type):获取声明的参数为传入参数列表的方法,和修饰符无关
- getFields():获取到所有public修饰的变量,返回Field[]数组
- getDeclaredFields():获取所有声明的变量,和修饰符无关
- 注意:以上四种方法都不能获取到继承自父类的变量
- 获取变量类型
- getType():获取变量类型
package com.most;
import java.lang.reflect.Field;
public class User {
public static void main(String[] args) throws Exception {
Class petClass = Pet.class;
System.out.println("------------------所有声明成员变量------------------");
Field[] fields = petClass.getDeclaredFields();
for (Field field : fields) {
System.out.println(field.getName());
}
// 以下注释语句会抛出异常
// Field feet = petClass.getDeclaredField("age");
System.out.println("------------------指定成员变量------------------");
System.out.println(petClass.getDeclaredField("name"));
System.out.println("------------------成员变量数据类型------------------");
Field name = petClass.getDeclaredField("name");
Class<?> parameterType = name.getType();
System.out.println(parameterType.getName());
}
public static class Pet extends Animal {
private static Integer count = 0;
private String name;
}
public static class Animal {
public Integer age;
}
}
执行结果
------------------所有声明成员变量------------------
count
name
------------------指定成员变量------------------
private java.lang.String com.most.User$Pet.name
------------------成员变量数据类型------------------
java.lang.String
获取注解信息
- 以下以获取类注解信息来进行说明,成员变量,方法,参数与此类似
- getAnnotations():获取类的所有注解信息集合
- getDeclaredAnnotations():获取类直接声明的注解信息集合
- getAnnotationsByType(Class type): 获取所有指定类型的注解信息集合
- getDeclaredAnnotationsByType(Class type):获取所有直接声明的指定类型的注解信息集合
- getAnnotation(Class type):获取指定类型的注解信息
- getDeclaredAnnotation(Class type):获取直接声明的指定类型的注解信息
- isAnnotationPresent(Class type):判断是否具有某个注解,包括通过继承得到的注解
注意:以上获取注解的方法中,带
Declare
的方法不能获取到通过继承得到的注解,不带Declare
的方法可以获取到通过继承得到的注解
获取泛型信息
- 泛型属性类型
- getGenericType():获取到类的泛型变量(静态属性或实例属性)信息
- 泛型方法参数类型
- getGenericParameterTypes():获取方法的泛型参数信息
- 泛型方法返回类型
- getGenericReturnType():获取方法的泛型返回值信息
package com.most;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.List;
public class User {
public static void main(String[] args) throws Exception {
System.out.println("------------------泛型属性类型------------------");
Field field = Pet.class.getDeclaredField("foods");
Type genericFieldType = field.getGenericType();
if (genericFieldType instanceof ParameterizedType) {
ParameterizedType aType = (ParameterizedType) genericFieldType;
Type[] fieldArgTypes = aType.getActualTypeArguments();
for (Type fieldArgType : fieldArgTypes) {
Class fieldArgClass = (Class) fieldArgType;
System.out.println("genericFieldType = " + fieldArgClass);
}
}
System.out.println("------------------泛型方法参数类型------------------");
Method setMethod = Pet.class.getMethod("setFoods", List.class);
Type[] genericParameterTypes = setMethod.getGenericParameterTypes();
for(Type genericParameterType : genericParameterTypes){
if(genericParameterType instanceof ParameterizedType){
ParameterizedType aType = (ParameterizedType) genericParameterType;
Type[] parameterArgTypes = aType.getActualTypeArguments();
for(Type parameterArgType : parameterArgTypes){
Class parameterArgClass = (Class) parameterArgType;
System.out.println("genericFieldType = " + parameterArgClass);
}
}
}
System.out.println("------------------泛型方法返回类型------------------");
Method getMethod = Pet.class.getMethod("getFoods");
Type returnType = getMethod.getGenericReturnType();
if(returnType instanceof ParameterizedType){
ParameterizedType type = (ParameterizedType) returnType;
Type[] typeArguments = type.getActualTypeArguments();
for(Type typeArgument : typeArguments){
Class typeArgClass = (Class) typeArgument;
System.out.println("genericFieldType = " + typeArgClass);
}
}
}
public static class Pet {
private List<String> foods;
public List<String> getFoods() {
return foods;
}
public void setFoods(List<String> foods) {
this.foods = foods;
}
}
}
输出结果
------------------泛型属性类型------------------
genericFieldType = class java.lang.String
------------------泛型方法参数类型------------------
genericFieldType = class java.lang.String
------------------泛型方法返回类型------------------
genericFieldType = class java.lang.String
Java反射
Java反射机制是指在运行状态中,对于任意一个类,通过Class类中的方法,动态访问这个类创建的对象的任意一个方法和属性。
反射的常用方法
初始化对象
- 获取到类的构造器之后,通过newInstance()方法就可以生成类对象
package com.most;
import java.lang.reflect.Constructor;
public class User {
public static void main(String[] args) throws Exception {
Class petClass = Pet.class;
Constructor specific = petClass.getConstructor(String.class);
Pet instance = (Pet) specific.newInstance("猪小明");
System.out.println(instance);
}
private static class Pet {
private String name;
public Pet() {
}
public Pet(String name) {
this.name = name;
}
@Override
public String toString() {
return "Pet[name=" + name + "]";
}
}
}
输出结果
Pet[name=猪小明]
invoke()方法
package com.most;
import java.lang.reflect.Constructor;
import java.lang.reflect.Method;
public class User {
public static void main(String[] args) throws Exception {
Class petClass = Pet.class;
// 如果内部类没有使用static的修饰符,则此处会报错,这种情况下有以下两种方式解决
// 第一种:使用static修饰
// 第二种:将内部类移到User类外部
Constructor constructors = petClass.getDeclaredConstructor();
Method method = petClass.getMethod("sayHi", String.class);
System.out.println("------------------方法调用结果------------------");
System.out.println(method.invoke(constructors.newInstance(), "猪小明"));
}
public static class Pet extends Animal {
}
public static class Animal {
public String sayHi(String name) {
return "Hi! " + name;
}
}
}
特别注意:在以上示例中,如果内部类没有static修饰符时,通过getDeclaredConstructor()将获取不到对应的构造函数,需使用static修饰或者将Pet类移到User类之外才能获取到
输出结果
------------------方法调用结果------------------
Hi! 猪小明
- 使用反射可以在运行时检查和调用类声明的成员方法,可以用来检测某个类是否有getter和setter方法(getter和setter是java bean必须有的方法),getter和setter方法有下面的一些规律:
- getter方法以get为前缀,无参,有返回值
- setter方法以set为前缀,有一个参数,返回值可有可无
成员变量赋值和取值
- 一旦获取到成员变量的Field引用,就可以获取通过get()方法获取变量值,通过set()方法给变量赋值
package com.most;
import java.lang.reflect.Field;
public class User {
public static void main(String[] args) throws Exception {
Pet pet = new Pet("猪小明");
Class petClass = Pet.class;
Field field = petClass.getDeclaredField("name");
field.setAccessible(true);
System.out.println("------------------获取属性的值------------------");
Object value = field.get(pet);
System.out.println(value);
System.out.println("------------------设置属性的值------------------");
field.set(pet, "猪小强");
value = field.get(pet);
System.out.println(value);
}
public static class Pet extends Animal {
private String name;
public Pet(String name) {
this.name = name;
}
}
public static class Animal {
public String sayHi(String name) {
return "Hi! " + name;
}
}
}
执行结果
------------------获取属性的值------------------
猪小明
------------------设置属性的值------------------
猪小强
访问私有属性和私有方法
- 使用getDeclaredMethod(Class<?>... types)/getDeclaredField(String type)和getDeclaredMethods()/getDeclaredFields()方法可以获取到私有属性和方法
- 访问前需要调用各自的setAccessible(true)后才能调用私有方法和访问属性
扩展内容
基础数据类型及其包装类的成员变量赋值和取值常用操作
基础数据类型和包装类型判断
- 判断一个类是否为基础数据类型
/**
* 判断是否是基础数据类型,包括int,double,long等8中基础数据类型和void
*/
public static boolean isCommonDataType(Class clazz){
return clazz.isPrimitive();
}
- 判断一个类是否为基础类型的包装类型
/**
* 判断是否是基础数据类型的包装类型
*
* @param clz
* @return
*/
public static boolean isWrapClass(Class clz) {
try {
return ((Class) clz.getField("TYPE").get(null)).isPrimitive();
} catch (Exception e) {
return false;
}
}
判断一个类型是否为int或者Integer
- 前置等式
int.class == Integer.TYPE
int.class.equals(Integer.TYPE)
- 判断方式
boolean isInteger = c.equals(Integer.class) || c.equals(Integer.TYPE);
boolean isInteger = c.equals(Integer.class) || c.equals(int.class);
boolean isInteger = c == Integer.class || c == Integer.TYPE;
boolean isInteger = c == Integer.class || c == int.class ;
各种数据类型的Class对象表示方法
// 基础类型,以int为例
int
// 基础类型包装类,以Integer为例
class java.lang.Integer
// 普通类,以下Animal为自定义的一个普通类
class com.most.obj.Animal
// 接口,以下Flyable为自定义的一个接口
interface com.most.obj.Flyable
// 基础类型数组,以int[]为例
class [I
// 基础类型包装类数组,以Integer[]为例
class [Ljava.lang.Integer;
// 字符串数组
class [Ljava.lang.String;
// 自定义类数组,以下Animal为自定义的一个普通类
class [Lcom.most.obj.Animal;
// 自定义接口,以下Flyable为自定义的一个接口
class [Lcom.most.obj.Flyable;