你的位置:首页 > Java教程

[Java教程]反射——类(Class)

本文原创,转载请注明原处!

 

 

红色代表的是基本组件:包(Package),修饰符(modifier),类(Class),字段(Field),构造器(Constructor)和方法(Method)。

黄色代表的是泛型组件:可定义泛型的元素(GenericDeclaration),类型(Type),泛型(TypeVariable),泛型参数类(ParameterizedType),泛型数组(GenericArrayType),通配符(WildcardType)。

蓝色代表的是注解组件:可被注解的元素(AnnotatedElement),注解后的类型(AnnotatedType),注解(Annotation),其它。

 

类(Class)

类不是单纯的指class定义的类,它是包括基本数据类型和数组,还包括class,interface,@interface,enum等定义出来的类型。

平常所用到的,所定义出来的类型,都可以归为现在所讲述的这个“类”,但它不包括泛型,虽然说泛型可以作为一个类型来使用。 

接口:Type,GenericDeclaration,AnnotatedElement

 

名称

  • getName():String
  • getCanonicalName():String
  • getSimpleName():String
  • s+forName(String):Class<?>
  • s+forName(String, boolean, ClassLoader):Class<?>

示例:

public class Test {  public static void main(String[] params) throws ClassNotFoundException {    Class<?> clazz = Class.forName("test.TestClass$TestInnerClass");    System.out.println(clazz.getName());    System.out.println(clazz.getCanonicalName());    System.out.println(clazz.getSimpleName());        /*      运行结果:      test.TestClass$TestInnerClass      test.TestClass.TestInnerClass      TestInnerClass     */  }}

test/TestClass.java

public class TestClass {  public class TestInnerClass {      }}

  

类型

  • isPrimitive():boolean
    查看是否基本数据类型。
  • isArray():boolean
    查看是否数组类型。
  • isInterface():boolean
    查看是否接口类型。
  • isAnnotation():boolean
    查看是否注解类型。
  • isEnum():boolean
    查看是否枚举类型。
public class Test {  public static void main(String[] params) {    print("基本数据类型", int.class);    /*      输出结果:      基本数据类型 -> 是否基本数据类型=true      基本数据类型 -> 是否数组=  false      基本数据类型 -> 是否接口=  false      基本数据类型 -> 是否注解=  false      基本数据类型 -> 是否枚举=  false     */        System.out.println("-------------------------");    print("数组", int[].class);    /*      输出结果:      数组 -> 是否基本数据类型=false      数组 -> 是否数组=  true      数组 -> 是否接口=  false      数组 -> 是否注解=  false      数组 -> 是否枚举=  false     */        System.out.println("-------------------------");    print("接口", TestInterface.class);    /*      输出结果:      接口 -> 是否基本数据类型=false      接口 -> 是否数组=  false      接口 -> 是否接口=  true      接口 -> 是否注解=  false      接口 -> 是否枚举=  false     */        System.out.println("-------------------------");    print("注解", TestAnnotation.class);    /*      输出结果:      注解 -> 是否基本数据类型=false      注解 -> 是否数组=  false      注解 -> 是否接口=  true      注解 -> 是否注解=  true      注解 -> 是否枚举=  false     */        System.out.println("-------------------------");    print("枚举", TestEnum.class);    /*      输出结果:      枚举 -> 是否基本数据类型=false      枚举 -> 是否数组=  false      枚举 -> 是否接口=  false      枚举 -> 是否注解=  false      枚举 -> 是否枚举=  true     */        System.out.println("-------------------------");    print("类", TestClass.class);    /*      输出结果:      类 -> 是否基本数据类型=false      类 -> 是否数组=  false      类 -> 是否接口=  false      类 -> 是否注解=  false      类 -> 是否枚举=  false     */  }    public static void print(String name, Class<?> clazz){    System.out.println(name + " -> 是否基本数据类型=" + clazz.isPrimitive());    System.out.println(name + " -> 是否数组=\t" + clazz.isArray());    System.out.println(name + " -> 是否接口=\t" + clazz.isInterface());    System.out.println(name + " -> 是否注解=\t" + clazz.isAnnotation());    System.out.println(name + " -> 是否枚举=\t" + clazz.isEnum());  }  public static class TestClass { }  public static interface TestInterface { }  public static @interface TestAnnotation { }  public static enum TestEnum { }}

注意:注解既是注解类型,又是接口类型,但它不能像接口一样,可以被实现。

  • getComponentType():Class<?>
    该类为数组类型时,可通过此方法获取其组件类型。

示例:

public class Test {  public static void main(String[] params) {    System.out.println(int[].class.getComponentType());    System.out.println(int[][].class.getComponentType());        /*      输出结果:      int      class [I     */  }}

 

  • getPackage():Package
    获取类在定义时所在的包。

 

修饰符

  • getModifiers():int

示例:

public class Test {  public static void main(String[] params) {    System.out.println(Modifier.toString(TestClass.class.getModifiers()));        // 输出结果:    // public static final  }    public static final class TestClass {      }}

 

内部定义

网络上查阅中,其中对内部类的划分有常规内部类,静态内部类,局部内部类,匿名内部类。下面的述语中,成员内部类是指常规内部类与静态内部类。

  • getDeclaringClass():Class<?>
    获取成员内部类在定义时所在的类。
  • getEnclosingClass():Class<?>
    获取内部类在定义时所在的类。
  • getEnclosingConstructor():Constructor
    获取局部或匿名内部类在定义时所在的构造器。
  • getEnclosingMethod():Method
    获取局部或匿名内部类在定义时所在的方法。
  • isMemberClass():boolean
    查看是否成员内部类。
  • isLocalClass():boolean
    查看是否局部内部类。
  • isAnonymousClass():boolean
    查看是否匿名内部类。

示例:

public class Test {  public static void main(String[] params) {    new Test().test();  }    public void test(){    printInnerClass("常规内部类", Test.InnerClass.InnerClass2.class);    /*      输出结果:      常规内部类 -> DeclaringClass=  class Test$InnerClass      常规内部类 -> EnclosingClass=  class Test$InnerClass      常规内部类 -> EnclosingConstructor=null      常规内部类 -> EnclosingMethod=  null      常规内部类 -> 是否成员内部类=  true      常规内部类 -> 是否局部内部类=  false      常规内部类 -> 是否匿名内部类=  false     */    System.out.println("---------------------------------------------------------------------------------------");    printInnerClass("静态内部类", StaticInnerClass.StaticInnerClass2.class);    /*      输出结果:      静态内部类 -> DeclaringClass=  class Test$StaticInnerClass      静态内部类 -> EnclosingClass=  class Test$StaticInnerClass      静态内部类 -> EnclosingConstructor=null      静态内部类 -> EnclosingMethod=  null      静态内部类 -> 是否成员内部类=  true      静态内部类 -> 是否局部内部类=  false      静态内部类 -> 是否匿名内部类=  false     */    System.out.println("---------------------------------------------------------------------------------------");    class LocalInnerClass { }    printInnerClass("局部内部类", LocalInnerClass.class);    /*      输出结果:      局部内部类 -> DeclaringClass=  null      局部内部类 -> EnclosingClass=  class Test      局部内部类 -> EnclosingConstructor=null      局部内部类 -> EnclosingMethod=  public void Test.test()      局部内部类 -> 是否成员内部类=  false      局部内部类 -> 是否局部内部类=  true      局部内部类 -> 是否匿名内部类=  false     */    System.out.println("---------------------------------------------------------------------------------------");    Object obj = new Object(){ };    printInnerClass("匿名内部类", obj.getClass());    /*      输出结果:      匿名内部类 -> DeclaringClass=  null      匿名内部类 -> EnclosingClass=  class Test      匿名内部类 -> EnclosingConstructor=null      匿名内部类 -> EnclosingMethod=  public void Test.test()      匿名内部类 -> 是否成员内部类=  false      匿名内部类 -> 是否局部内部类=  false      匿名内部类 -> 是否匿名内部类=  true     */  }    public static void printInnerClass(String name, Class<?> clazz){    System.out.println(name + " -> DeclaringClass=\t" + clazz.getDeclaringClass());    System.out.println(name + " -> EnclosingClass=\t" + clazz.getEnclosingClass());    System.out.println(name + " -> EnclosingConstructor=" + clazz.getEnclosingConstructor());    System.out.println(name + " -> EnclosingMethod=\t" + clazz.getEnclosingMethod());    System.out.println(name + " -> 是否成员内部类=\t" + clazz.isMemberClass());    System.out.println(name + " -> 是否局部内部类=\t" + clazz.isLocalClass());    System.out.println(name + " -> 是否匿名内部类=\t" + clazz.isAnonymousClass());  }    public class InnerClass {    public class InnerClass2 {          }  }    public static class StaticInnerClass {    public static class StaticInnerClass2 {          }  }}

 

父子关系

  • getSuperclass():Class<? super T>
    获取继承的父类。
  • getGenericSuperclass():Type
  • getAnnotatedSuperclass():AnnotatedType

示例:

public class Test {  public static void main(String[] params) {    System.out.println(TestClass.class.getSuperclass());    System.out.println(TestClass.class.getGenericSuperclass());    System.out.println(TestClass.class.getAnnotatedSuperclass());    /*      运行结果:      class Test$TestSuperClass      Test.Test$TestSuperClass<java.lang.Integer>      sun.reflect.annotation.AnnotatedTypeFactory$AnnotatedParameterizedTypeImpl@a14482     */  }    public class TestSuperClass<T> {      }    public class TestClass extends @TestAnnotation TestSuperClass<Integer>{      }    @Target(ElementType.TYPE_USE)  @Retention(RetentionPolicy.RUNTIME)  public @interface TestAnnotation {      }}

  • getInterfaces():Class<?>[]
    获取实现的接口集。
  • getGenericInterfaces():Type[]
  • getAnnotatedInterfaces():AnnotatedType[]

示例:

public class Test {  public static void main(String[] params) {    System.out.println(Arrays.toString(TestClass.class.getInterfaces()));    System.out.println(Arrays.toString(TestClass.class.getGenericInterfaces()));    System.out.println(Arrays.toString(TestClass.class.getAnnotatedInterfaces()));    /*      运行结果:      [interface Test$TestInterface]      [Test.Test$TestInterface<java.lang.Integer>]      [sun.reflect.annotation.AnnotatedTypeFactory$AnnotatedParameterizedTypeImpl@a14482]     */  }    public interface TestSuperInterface {      }    public interface TestInterface<T> extends TestSuperInterface {      }    public class TestClass implements @TestAnnotation TestInterface<Integer>{      }    @Target(ElementType.TYPE_USE)  @Retention(RetentionPolicy.RUNTIME)  public @interface TestAnnotation {      }}

  • asSubclass(Class<U>):Class<? extends U>
    把该类型(子类)转换为目标类型(父类)。
  • isAssignableFrom(Class<?>):boolean
    测试该类型(父类)是否为目标类型(子类)的父类。

用例:

public class Test {  public static void main(String[] params) {    test(Object.class);    System.out.println("---------------------------------");    test(TestClass.class);        /*      输出结果:      test方法 -> 获得一个clazz,但不确定它是否为TestSuperClass类型或其子类      test方法 -> 这个clazz不是TestSuperClass类型或其子类      ---------------------------------      test方法 -> 获得一个clazz,但不确定它是否为TestSuperClass类型或其子类      test方法 -> 确认这个clazz是TestSuperClass类型或其子类     */  }    public static Class<? extends TestSuperClass> test(Class<?> clazz){    System.out.println("test -> 获得一个clazz,但不确定它是否为TestSuperClass类型或其子类");    if(TestSuperClass.class.isAssignableFrom(clazz)){      System.out.println("test -> 确认这个clazz是TestSuperClass类型或其子类");      return clazz.asSubclass(TestSuperClass.class);    }    System.out.println("test -> 这个clazz不是TestSuperClass类型或其子类");    return null;  }    public class TestSuperClass {      }    public class TestClass extends TestSuperClass {      }}

  

成员类

  • getClasses():Class<?>[]
  • getDeclaredClasses():Class<?>[]

示例:

public class Test {  public static void main(String[] params) {    System.out.println(Arrays.toString(TestClass.class.getClasses()));    System.out.println("---------------------------------");    System.out.println(Arrays.toString(TestClass.class.getDeclaredClasses()));        /*      输出结果:      [class Test$TestClass$TestMemberClass3, class Test$TestSuperClass$TestSuperMemberClass3]      ---------------------------------      [class Test$TestClass$TestMemberClass1, class Test$TestClass$TestMemberClass2, class Test$TestClass$TestMemberClass3]     */  }      public class TestSuperClass {        private class TestSuperMemberClass1 {          }        protected class TestSuperMemberClass2 {          }        public class TestSuperMemberClass3 {          }  }    public class TestClass extends TestSuperClass {        private class TestMemberClass1 {          }        protected class TestMemberClass2 {          }        public class TestMemberClass3 {          }      }}

  

构造器

  • getConstructor(Class<?>...):Constructor<T>
  • getConstructors():Constructor<?>[]
  • getDeclaredConstructor(Class<?>...):Constructor<T>
  • getDeclaredConstructors():Constructor<?>[]

示例:

public class Test {  public static void main(String[] params) {    System.out.println(Arrays.toString(TestClass.class.getConstructors()));    System.out.println(Arrays.toString(TestClass.class.getDeclaredConstructors()));        /*      运行结果:      [public Test$TestClass(Test,long)]      [private Test$TestClass(Test,short), protected Test$TestClass(Test,int), public Test$TestClass(Test,long)]     */  }  public class TestClass {    private TestClass(short i){          }        protected TestClass(int i){          }        public TestClass(long l){          }  }}

  

方法

  • getMethod(String, Class<?>...):Method
  • getMethods():Method[]
  • getDeclaredMethod(String, Class<?>...):Method
  • getDeclaredMethods():Method[]

示例:

public class Test {  public static void main(String[] params) {    System.out.println(Arrays.toString(TestClass.class.getMethods()));    System.out.println("----------------------------------");    System.out.println(Arrays.toString(TestClass.class.getDeclaredMethods()));        /*      运行结果:      [public void Test$TestClass.test(long), public void Test$TestSuperClass.superTest(long), 省略Object的方法……]      ----------------------------------      [public void Test$TestClass.test(long), protected void Test$TestClass.test(int), private void Test$TestClass.test(short)]     */  }    public class TestSuperClass {    private void superTest(short i){          }        protected void superTest(int i){          }        public void superTest(long l){          }  }  public class TestClass extends TestSuperClass {    private void test(short i){          }        protected void test(int i){          }        public void test(long l){          }  }}

 

字段

  • getField(String):Field
  • getFields():Field[]
  • getDeclaredField(String):Field
  • getDeclaredFields():Field[]

与方法同理……

 

实例

  • newInstance():T
    使用该类的无参构造器创建实例。
  • isInstance(Object):boolean
    测试该对象实例是否为该类的实例。
  • cast(Object):T
    把对象实例转为该类的实例。
  • getEnumConstants():T[]
    该类为枚举类型时,可通过此方法获取其所有枚举常量。

 

资源

  • getResource(String):URL
    获取与该类所在目录下的路径资源。
  • getResourceAsStream(String):InputStream
    和上同理……

 

其它

  • desiredAssertionStatus():boolean
    测试该类的断言功能是否已打开。

示例:

test/Test.java

public class Test {  public static void main(String[] params) {    Test.class.getClassLoader().setClassAssertionStatus(TestAssert.class.getName(), true);    TestAssert testAssert2 = new TestAssert();    testAssert2.test();        /*      运行结果:      TestAssert -> 断言是否已打开=true      Exception in thread "main" java.lang.AssertionError: 断言信息!        at test.TestAssert.test(TestAssert.java:6)        at test.Test.main(Test.java:10)     */  }}

 test/TestAssert.java

public class TestAssert {  public void test(){    System.out.println("TestAssert -> 断言是否已打开=" + TestAssert.class.desiredAssertionStatus());    assert false : "断言信息!";  }}

注:打开断言功能,还可以使用“-ea”参数打开。

  • isSynthetic():boolean
    测试所修饰的成员是否由编译器编译成class文件时所增加的,否则它是由编程人员编写java源文件时所编写的。
  • getClassLoader():ClassLoader
    获取该类被加载时所用的类加载器。
  • getProtectionDomain():ProtectionDomain
    一种权限机制,制定一个代码源所拥有的权限集合,保护域就是代表一个代码源的权限集合。
  • getSigners():Object[]
    一种盖章机制,编写者编写完代码后,由签名者审核确认无误后,进行签名,同一代码可以由多个签名者审核后盖章。