Java——反射、Class类详解

一、反射的概念

1.反射的引入

    一般情况情况下:我们在使用一个类的时候,我们都知道这个类是什么,有哪些方法。所以可以直接创建这个对象进行操作

Student student = new Student();
student.setName("小学生");

    但是若是在程序运行期间,接收到了一个外部传入的一个对象,这个对象的编译类型为Object,但是程序又要调用这个对象的方法的方法:

  1. 若是在编译时期就知道该对象属于什么类型,则可以使用instanceof判断后,再进行强转

  2. 若是在编译时期也不知道该对象是属于什么类型,程序只有在运行时进行处理,则就需要使用反射

反射:就是在运行时期能获取自身的信息,并且可以进行相应的操作。即在运行时期才知道要操作的类是什么,并且可以在运行时期获取类的完整结构,并调用相应的方法。

    

2.Class类和Class类实例

java 程序中的各个 Java 类属于同一类事物,描述这类事物的 Java 类就是 Class 类。

①对比提问:众多的人用一个什么类表示?众多的 Java 类用一个什么类表示?

人            Person

Java 类       Class

②对比提问: Person 类代表人,它的实例对象就是张三,李四这样一个个具体的人,Class类代表 Java 类,它的各个实例对象又分别对应什么呢?

就是对应各个类在内存中的字节码,例如,Person 类的字节码,ArrayList 类的字节码,等等;

 

个类被类加载器加载到内存中,占用一片存储空间,这个空间里面的内容就是类的字节码,不同的类的字节码是不同的,所以它们在内存中的内容是不同的;

用类来描述对象,类:描述数据的结构

用元数据来描述 Class,MetaData(元数据):描述数据结构的结构;

反射就是得到元数据的行为;

备注:一个类在虚拟机中只有一份字节码;即手动编写的每个class类,无论创建多少个实例对象,在JVM中都只有一个Class对象,即在内存中每个类有且只有一个相对应的Class对象

 

二、怎么用

1.获取Class对象

    首先我们要知道:

  1. Class类也是类的一种, 与class关键字是一样的

  2. Class对象只有私有构造函数,因此对应的Class对象只有JVM才能创建和加载

    Class类的部分源码:

public final class Class<T> implements java.io.Serializable,
                              GenericDeclaration,
                              Type,
                              AnnotatedElement {
    private static final int ANNOTATION= 0x00002000;
    private static final int ENUM      = 0x00004000;
    private static final int SYNTHETIC = 0x00001000;
    private static native void registerNatives();
    static {
        registerNatives();
    }
    /*
     * Private constructor. Only the Java Virtual Machine creates Class objects.
     * This constructor is not used and prevents the default constructor being
     * generated.
     */
    private Class(ClassLoader loader) {
        // Initialize final field for classLoader.  The initialization value of non-null
        // prevents future JIT optimizations from assuming this final field is null.
        classLoader = loader;
    }
}

    获取Class对象一共有三种方式:

1、调用某个类的 class 属性获取 Class 对象,如 Date.class 会返回 Date 类对应的 Class 对象(其实就是得到一个类的一份字节码文件);

//一:调用属性
Class<String> c = String.class;
System.out.println(c);//打印结果:class java.lang.String
Class<String> c2 = String.class;
System.out.println(c == c2);//true都是String类的字节码  证:一个类在虚拟机中只有一份字节码;

2、使用 Class 类的 forName(String className)静态方法,className 表示全限定名;如 String 的全限定名:java.lang.String;

//二:使用forName()方法
//Class cla = Class.forName("String");//ERROR, Class<String> cla =
(Class<String>)Class.forName("java.lang.String");// 必须用上全限定名,否则报错
System.out.println(c == cla);//true

3、调用某个对象的 getClass()方法。该方法属于 Object 类; Class<?> clz = new Date().getClass();

//三:利用对象调用Object的getClass方法;
Class c3 = new String().getClass();
System.out.println(c == c3);//ture

通过Class对象创建对象一共有两种方式:

1.通过newInstancae()方法

Class clz = String.class;
String str = (String)clz.newInstance();

2.通过获取该类的构造对象,再获取该类的对象

Class clz = String.class;
Constroctor constroctor =clz.getConstructor(String.class);
// 通过该Constroctor实例的newInstance()方法获取对象
String str = (String)constroctor.newInstance("哈哈");

2.Class类常用的API

 

1.获取包名

public Package getPackage() 

2.获取全限定名

public String getName()

3.获取类的简称

public String getSimpleName()

4.获取父类的Class

public native Class<? super T> getSuperclass()

5.获取接口的Class

public Class<?>[] getInterfaces() 

6.获取该 Class 对象表示类的指定的 public 构造方法

public Constructor<T> getConstructor(Class<?>... parameterTypes)

7.获取该 Class 对象表示类的所有 public 构造方法

public Constructor<?>[] getConstructors()

8.获取该 Class 对象表示类的指定的构造方法(不受访问权限影响)

public Constructor<T> getDeclaredConstructor(Class<?>... parameterTypes)

9.返回该 Class 对象表示类的所有构造方法(不受访问权限影响)

public Constructor<?>[] getDeclaredConstructors()

10.获取该 Class对象表示类的所有包含父类的方法)public 修饰的方法

public Method[] getMethods() 

11.获取该 Class对象表示类的指定public修饰的方法

public Method getMethod(String name, Class<?>... parameterTypes)

12.获取该 Class对象表示类的所有方法(不受访问权限影响,但不包括继承的方法,只可以对当前类有效)

public Method[] getDeclaredMethods()

13.获取该 Class对象表示类的指定方法(不受访问权限影响,但不包括继承的方法,只可以对当前类有效)

public Method getDeclaredMethod(String name, Class<?>... parameterTypes)

14..获取该 Class对象表示类的所有public修饰的字段

public Field[] getFields()

15..获取该 Class对象表示类的指定public修饰的字段

public Field getField(String name)

16.获取该 Class对象表示类的所有字段(不受访问权限影响,但不包括继承的方法,只可以对当前类有效)

public Field[] getDeclaredFields()

17.获取该 Class对象表示类的指定字段(不受访问权限影响,但不包括继承的方法,只可以对当前类有效)

public Field getDeclaredField(String name)

18.获取该 Class对象表示类的所有注解

public Annotation[] getAnnotations() 

19.获取该 Class对象表示类的特定注解

public <A extends Annotation> A getDeclaredAnnotation(Class<A> annotationClass) 

3.Method类常用API

1.获取该Method对象的名字

public String getName()

2.获取该Method对象的参数Class实例列表(按照声明顺序)

public Class<?>[] getParameterTypes()

3.获取该Method对象的所抛出异常的Class实例列表(按照声明顺序)

public Class<?>[] getExceptionTypes()

4.获取该Method对象返回Class实例

public Class<?> getReturnType()

5.获取声明该Method的类或者接口的Class实例

public Class<?> getDeclaringClass()

6.获取该Method对象的参数类型列表(按照声明顺序)

public Type[] getGenericParameterTypes()

7.获取该Method对象的异常类型列表(按照声明顺序)

public Type[] getGenericExceptionTypes()

8.获取该Method对象返回类型

public Type getGenericReturnType() 

9.获取该Method对象的修饰符编码

public int getModifiers() 

10.将该Method对象装换为字符串(包括类型参数)

public String toGenericString()

11.如果存在该元素的指定类型的注释,则返回这些注释,否则返回 null

public <T extends Annotation> T getAnnotation(Class<T> annotationClass)

12.获取该Method上的所有注释

public Annotation[] getDeclaredAnnotations()

13.获取该Method上的参数列表中的所有注释(按照声明顺序)

public Annotation[] getDeclaredAnnotations() 

14.如果此方法是 bridge 方法,则返回 true;否则,返回 false

public boolean isBridge()

15.如果此方法为复合方法,则返回 true;否则,返回 false

public boolean isVarArgs()

16.如果将此方法声明为带有可变数量的参数,则返回 true;否则,返回 false

public boolean isSynthetic()

17.执行该Method方法,指定参数列表和值

public Object invoke(Object obj, Object... args)

4.Field类常用API

1.获取该Field对象的名字

public String getName()

2.获取该Field对象的修饰符编码

public int getModifiers() 

3.将该Field对象装换为字符串

public String toGenericString()

4.获取该Field指定类型的注释,则返回这些注释,否则返回 null

public <T extends Annotation> T getAnnotation(Class<T> annotationClass)

5.获取该Field上的所有注释

public Annotation[] getDeclaredAnnotations()

6.获取该Field对象的声明类型

public Type getGenericType() 

7.获取该Field对象的声明类型的Class对象

public Class<?> getType() 

8.返回指定对象上此Field表示的字段的值。如果该值是一个基本类型值,则自动将其包装在一个对象中

public Object get(Object obj)

9.将指定对象变量上此Field对象表示的字段设置为指定的新值。如果底层字段的类型为基本类型,则对新值进行自动解包

public void set(Object obj, Object value)

 

5.Modifier类中所声明的修饰符的编码

// 1
public static final int PUBLIC = 0x00000001;               

// 2
public static final int PRIVATE = 0x00000002;               

// 4

public static final int PROTECTED = 0x00000004;

// 8
public static final int STATIC = 0x00000008;

// 16
public static final int FINAL = 0x00000010;

// 32
public static final int SYNCHRONIZED = 0x00000020;

// 64
public static final int VOLATILE = 0x00000040;

// 128
public static final int TRANSIENT = 0x00000080;

// 256
public static final int NATIVE = 0x00000100;

// 512
public static final int INTERFACE = 0x00000200;

// 1024
public static final int ABSTRACT = 0x00000400;

// 2048
public static final int STRICT = 0x00000800;

 

 

 

 

 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值