概述

将类的各个组成部分封装成其他对象,称作反射机制,反射被称作是框架设计的灵魂,通过反射这面镜子来窥探类的结构,java.lang.reflect类库里面主要的类

类名 说明
Class 每个类都要一个对应的Class对象
Field 类中的成员的变量
Method 类中的方法
Constructor 类的构造方法
Array 提供了动态的创建数组和访问数组元素的静态方法

作用

在运行时判断任意一个对象所属的类。
在运行时判断任意一个类所具有的成员变量和方法。
在运行时任意调用一个对象的方法
在运行时构造任意一个类的对象

Class

Java的Class类是java反射机制的基础,通过Class类我们可以获得关于一个类的相关信息
Java.lang.Class是一个比较特殊的类,它用于封装被装入到JVM中的类(包括类和接口)的信息。当一个类或接口被装入的JVM时便会产生一个与之关联的java.lang.Class对象,可以通过这个Class对象对被装入类的详细信息进行访问。
虚拟机为每种类型管理一个独一无二的Class对象。也就是说,每个类(型)都有一个Class对象。运行程序时,Java虚拟机(JVM)首先检查是否所要加载的类对应的Class对象是否已经加载。如果没有加载,JVM就会根据类名查找.class文件,并将其Class对象载入。
**

Class类也是类的一种,Class类只有一个私有的构造函数,只有JVM可以创建Class类的实例

  1. public final class Class<T> implements java.io.Serializable,
  2. GenericDeclaration,
  3. Type,
  4. AnnotatedElement {}

Class 是首字母大写,不同于class小写,class是定义类的关键字
Java除了基本类型其他都是Class,包括interface,String,Object Runnable,Exception
Class的本质是数据类型Type,
无继承关系的数据类型无法赋值
class/insterface的数据类型是Class
每加载一个class,JVM就为其创建一个Class类型的实例,并关联起来。
JVM持有的每个Class实例都指向一个数据类型

Class对象

同一个字节码文件(*.class)在一次程序运行过程中,只会被加载一次,无论通过哪一种方式获取的Class对象都是同一个。JVM中只有唯一一个和类相对应的Class对象来描述其类型信息。
获取Class对象的三种方式:

方法 说明
类名.class 通过一个 Class 的静态变量 class 获取
对象实例.getClass () 有该类的对象实例,该方法由 java.lang.Object 类提供
Class.forName (“包名.类名”) 如果知道一个类的完整包名,可以通过 Class 类的静态方法 forName() 获得 Class 对象

Class.forName()

Class类的静态方法forName,Class.forName,传入参数一个类的全限定名称,它包括包名+类名,即

  1. Class.forName("全类名")

eg:

  1. try {
  2. Class<?> aClass = Class.forName("cn.bx.reflect.Foo");
  3. System.out.println(aClass);
  4. } catch (ClassNotFoundException e) {
  5. e.printStackTrace();
  6. }

类名.class

通过类名的class属性获取,主要用于参数传递

  1. System.out.println(Foo.class);
  2. System.out.println(int.class);
  3. System.out.println(String.class);
  4. 输出结果
  5. class cn.bx.reflect.Foo
  6. int
  7. class java.lang.String

对象.getClass()

getClass()方法在object类中定义 ,通过一个类的实例的 getClass() 方法就能获取到它的 Class。这种方法不适合基本类型如 int、float 等基本数据类型。

  1. package cn.bx.reflect;
  2. class Foo {
  3. }
  4. public class ClassObject {
  5. public static void main(String[] args) {
  6. Foo foo = new Foo();
  7. Class<? extends Foo> aClass = foo.getClass();
  8. System.out.println(aClass);
  9. }
  10. }

Class方法

  1. getName()// 获取全类名
  2. getSimpleName()
  3. getPackage()
  1. Class<Foo> fooClass = Foo.class;
  2. System.out.println(fooClass.getName());
  3. System.out.println(fooClass.getSimpleName());
  4. System.out.println(fooClass.getCanonicalName());

Field

通过Class实例获取字段field信息:

  1. getField(name):获取某个publicfield(包括父类)
  2. getDeclaredField(name):获取当前类的某个field(不包括父类)
  3. getFields():获取所有publicfield(包括父类)
  4. getDeclaredFields():获取当前类的所有field(不包括父类)
  1. class Person{
  2. public int id;
  3. private String name;
  4. }
  5. class Student extends Person{
  6. String school;
  7. private String grade;
  8. protected String className;
  9. }
  10. public class ClassObject {
  11. public static void main(String[] args) {
  12. Class<Student> studentClass = Student.class;
  13. try {
  14. Field name = studentClass.getDeclaredField("grade");
  15. System.out.println(name);
  16. } catch (NoSuchFieldException e) {
  17. e.printStackTrace();
  18. System.out.println("getDeclaredField "+e.getMessage());
  19. }
  20. try {
  21. Field name = studentClass.getField("id");
  22. System.out.println(name);
  23. } catch (NoSuchFieldException e) {
  24. e.printStackTrace();
  25. System.out.println("getField "+e.getMessage());
  26. }
  27. Field[] filed1 = studentClass.getDeclaredFields();
  28. for ( Field f : filed1 ) {
  29. System.out.println("Declared Field :"+f.getName());
  30. }
  31. Field[] filed2 = studentClass.getFields();
  32. for ( Field f : filed2 ) {
  33. System.out.println("Field :"+f.getName());
  34. }
  35. }
  36. }

打印结果

  1. private java.lang.String cn.bx.reflect.Student.grade
  2. public int cn.bx.reflect.Person.id
  3. Declared Field :school
  4. Declared Field :grade
  5. Declared Field :className
  6. Field :id

getFields 只能获取public的方法

  1. Class c = Person.class;
  2. Field[] fields = c.getFields();
  3. for (Field f :fields){
  4. System.out.println(f);
  5. }

getDeclaredFields()可以获取所有的成员变量 修饰符对其不影响。

  1. Class c = Person.class;
  2. Field[] fields = c.getDeclaredFields();
  3. for(Field f :fields){
  4. System.out.println(f);
  5. }

Field对象包含一个field的所有信息:

  1. getName()
  2. getType()
  3. getModifiers() // 获取修饰符

获取和设置field的值:

  1. get(Object obj)// 获取一个实例对象的该字段的值
  2. set(Object, Object)// 设置一个实例对象的该字段的值
  1. Person p = new Person();
  2. p.setGender("male");
  3. Field f = Person.class.getField("gender");
  4. Object value = f.get(p);
  5. System.out.println(value);
  6. f.set(p,"female");
  7. System.out.println(p.getGender());

对私有变量的修改,暴力反射setAccessible(true)

  1. Person p = new Person();
  2. p.setName("xiaoming");
  3. Field f = Person.class.getDeclaredField("name");
  4. f.setAccessible(true);
  5. Object value = f.get(p);
  6. System.out.println(value);
  7. f.set(p,"xiaowang");
  8. System.out.println(p.getName());

Constructor构造方法

Java 类java.lang.reflect.Constructor实例是对类构造器(Constructor)的反射。Constructor类继承自通用抽象父类Executable,其自身是不可变(Immutable)类。

  1. public final class Constructor<T> extends Executable


方法 描述
Constructor<?>[] getConstructors() 返回目标类中所有公开(public)构造方法,返回值为构造器对象数组Constructor<?>[]。
Constructor<?>[] getDeclaredConstructors() 返回目标类中所有(public、private、protected、default)构造方法,返回值为构造器对象数组Constructor<?>[]
Constructor getConstructor(Class<?>… parameterTypes) 根据构造方法名与参数类型取得目标构造方法对象Constructor,如果构造方法不存在,则抛出NoSuchMethodException异常
Constructor getDeclaredConstructor(Class<?>… parameterTypes) 根据参数类型获取构造方法。

构造函数创建对象newInstance

  1. Constructor constructor = Person.class.getConstructor(String.class,int.class);
  2. Object p = constructor.newInstance("xiaoming",20);

空参数构造可以使用class方法newInstance

Methord成员方法

  1. Methods []getMethods // 获取所有的public成员方法(包括父类方法)
  2. Method getMethod(String name,类<?>...parameterTypes)
  3. Method[] getDeclaredMethods()
  1. Method[] methods = Person.class.getDeclaredMethods();

获取方法赋值invoke

  1. Method setName = Person.class.getMethod("setName",String.class);
  2. Person p = new Person();
  3. setName.invoke(p,"xiaoming");

获取成员方法名称

  1. Method[] methods = Person.class.getMethods();
  2. for(Method m :methods){
  3. System.out.println(m.getName());
  4. }

修饰符

Java 开发中定义一个类,往往是要通过许多修饰符来配合使用的。它们大致分为 4 类。

  • 用来限制作用域,如 public、protected、priviate。
  • 用来提示子类复写,abstract。
  • 用来标记为静态类 static。
  • 注解。

    1. public class ClassObject {
    2. private class Foo {
    3. }
    4. protected static class Bar{
    5. }
    6. public static void main(String[] args) {
    7. Class<Foo> fooClass = Foo.class;
    8. System.out.println(fooClass.getModifiers());
    9. System.out.println(Modifier.toString(fooClass.getModifiers()));
    10. System.out.println(Modifier.toString(Bar.class.getModifiers()));
    11. System.out.println(Modifier.isPublic(fooClass.getModifiers()));
    12. }
    13. }

返回值

  1. 2
  2. private
  3. protected static
  4. false

修饰符返回的是一个数字,用一个 int 数值来记录所有的修饰符,然后不同的位对应不同的修饰符

  1. public class Modifier {
  2. public static final int PUBLIC = 0x00000001;
  3. public static final int PRIVATE = 0x00000002;
  4. public static final int PROTECTED = 0x00000004;
  5. public static final int STATIC = 0x00000008;
  6. public static final int FINAL = 0x00000010;
  7. public static final int SYNCHRONIZED = 0x00000020;
  8. public static final int VOLATILE = 0x00000040;
  9. public static final int TRANSIENT = 0x00000080;
  10. public static final int NATIVE = 0x00000100;
  11. public static final int INTERFACE = 0x00000200;
  12. public static final int ABSTRACT = 0x00000400;
  13. public static final int STRICT = 0x00000800;
  14. public static String toString(int mod) {
  15. StringBuilder sb = new StringBuilder();
  16. int len;
  17. if ((mod & PUBLIC) != 0) sb.append("public ");
  18. if ((mod & PROTECTED) != 0) sb.append("protected ");
  19. if ((mod & PRIVATE) != 0) sb.append("private ");
  20. /* Canonical order */
  21. if ((mod & ABSTRACT) != 0) sb.append("abstract ");
  22. if ((mod & STATIC) != 0) sb.append("static ");
  23. if ((mod & FINAL) != 0) sb.append("final ");
  24. if ((mod & TRANSIENT) != 0) sb.append("transient ");
  25. if ((mod & VOLATILE) != 0) sb.append("volatile ");
  26. if ((mod & SYNCHRONIZED) != 0) sb.append("synchronized ");
  27. if ((mod & NATIVE) != 0) sb.append("native ");
  28. if ((mod & STRICT) != 0) sb.append("strictfp ");
  29. if ((mod & INTERFACE) != 0) sb.append("interface ");
  30. if ((len = sb.length()) > 0) /* trim trailing space */
  31. return sb.toString().substring(0, len-1);
  32. return "";
  33. }
  34. }