Java反射 Class类常用方法详解

Java反射 Class类常用方法详解1.返回Class类对应的实体类的相关的Class类的方法:如果我们已经有了一个类的Class类,可以使用下面的一些方法来获得它相关的类:(1)返回当前Class类对应的实体类的父类的Class类:publicClass<?superT>getSuperclass()例如:publicstaticvoidmain(String[]args)throwsClassN…

大家好,又见面了,我是你们的朋友全栈君。

获取一个类对应的Class类的方法

1.使用Object.getClass ()方法—-引用类型的对象的获取方式

如果我们已经拿到了一个对象,可以使用这个对象的 getClass 方法获得一个 Class 对象(不过这仅限于引用类型的对象):

String string=new String();
//使用已经存在的对象的getClass()方法获取Class对象
Class  class1=string.getClass();

2.使用类的class成员属性

如果我们当前没有某个类的对象,无法使用 getClass() 方法来获取Class对象,那还可以使用 类名.class 来获取 Class对象:

//使用 类名.class来获取Class对象
Class class2=String.class;

其实这种方式不仅能用于引用类型,基本类型也可以。数组也是可以的:

Class class3=int.class;
Class class4=int[][].class

3.使用Class类的forName(“类完整路径”)方法获取:

如果我们有一个类的完整路径,就可以使用 Class.forName(“类完整的路径”) 来得到相应的 Class,这个方法只能用于引用类型,所谓类的完整路径是:包名.类名 例如:java.lang.String。

Class<?> strClass=Class.forName("java.lang.String");

4.使用包装类的TYPE属性来获取包装类对应的Class类:

public static final Class<Integer>  TYPE = (Class<Integer>) Class.getPrimitiveClass("int");

返回Class类对应的实体类的相关的Class类的方法:

如果我们已经有了一个类的 Class类,可以使用下面的一些方法来获得它相关的类:

1.返回当前Class类对应的实体类的父类的Class类:

public Class<? super T> getSuperclass()

例如:

public static void main(String[] args) throws ClassNotFoundException
{
    Class<String> strClass = (Class<String>) Class.forName("java.lang.String");
    // 返回调用类的父类
    Class<?> superClass = strClass.getSuperclass();
    System.out.println("当前实体类的Class类    :"+strClass);
    System.out.println("实体类的父类的Class类:"+superClass);
}

结果:

当前实体类的Class类    :class java.lang.String
实体类的父类的Class类:class java.lang.Object

2.返回类定义的公共的内部类,以及从父类、父接口那里继承来的内部类

public Class<?>[] getClasses()

3.返回类中定义的公共、私有、保护的内部类

public Class<?>[] getDeclaredClasses()

实例:

Person类:

public class Person
{
	public class PA{};
	private class PB{};
	public interface PIA{};
	private interface PIB{};
}

Student类:

public class Student extends Person
{
	//公共的内部类
	public class A{}
	//保护内部类
	protected class B{}
	//默认内部类
	class C{}
	//私有内部类:
	private class D{}
	//共有静态内部类
	public static class E{}
	//共有内部接口
	public interface IA{}
	//保护内部接口
	protected interface IB{}
	//默认内部接口
	interface IC{}
	//私有内部接口
	private interface ID{}
}

main方法:

public static void main(String[] args) throws ClassNotFoundException
{
	Class<String> stuClass = (Class<String>) Class.forName("reflect.Student");
	//获取调用类的所有公共的内部类和接口,包括继承的共有的内部类和接口的Class
	System.out.println(stuClass.getName()+"的公有内部类和接口(包括继承):");
	Class[]   strClasses=stuClass.getClasses();
	for (Class class1 : strClasses)
	{
		System.out.println(class1.getName());
	}
	System.out.println("-------------------------");
	System.out.println(stuClass.getName()+"的所有内部类和接口(包括继承):");
	Class[]   stuAllClasses=stuClass.getDeclaredClasses();
	for (Class class1 : stuAllClasses)
	{
		System.out.println(class1.getName());
	}
	
}

运行结果:

reflect.Student的公有内部类和接口(包括继承):
reflect.Student$A
reflect.Student$E
reflect.Student$IA
reflect.Person$PA
reflect.Person$PIA
-------------------------
reflect.Student的所有内部类和接口(包括继承):
reflect.Student$A
reflect.Student$B
reflect.Student$C
reflect.Student$D
reflect.Student$E
reflect.Student$IA
reflect.Student$IB
reflect.Student$IC
reflect.Student$ID

4. 返回一个成员内部类/属性/方法/构造器所在的类的Class,这些方法是上面那两个方法的逆操作

java.lang.reflect.Class.getDeclaringClass()    ;//返回一个成员内部类所在的类的Class
java.lang.reflect.Field.getDeclaringClass()      ;//返回一个字段所在的类的Class
java.lang.reflect.Method.getDeclaringClass()    ;//返回一个方法所在的类的Class
java.lang.reflect.Constructor.getDeclaringClass() ;//返回一个构造器所在的类的Class

(1) Class.getDeclaringClass()实例:–获取该成员内部类所在声明类的Class,所谓声明类,就是声明该内部类的外部类

测试类:

public class A
{
	String name;
	class C{}
}

在这里,内部类C的声明类就是A,在类A里面声明了内部类C和成员属性name.对于成员属性name和成员内部类C而言,它们的声明类都是A.这样说可以理解了吧。

main方法:

public static void main(String[] args) throws ClassNotFoundException
{
	Class stuClass =  Class.forName("reflect.A$C");//获取一个成员内部类的Class对象
	//获取成员内部类的声明类,也就是他的外部类
	Class stuclass2=stuClass.getDeclaringClass();
	System.out.println(stuClass);
	System.out.println(stuclass2);
}

运行结果:

class reflect.A$C
class reflect.A

(2)获取声明该字段,方法,构造器的类的Class后面再补上。

5.获取Class对应类(或者接口)的修饰符:Class.getModifiers()

public int getModifiers();//返回此类或接口以整数编码的 Java 语言修饰符。
修饰符由 Java 虚拟机的 public、protected、private、final、static、abstract 和 interface 对应的常量组成;
它们应当使用 Modifier 类的方法来解码。

一个 类(或接口)可以被以下修饰符的一种或者多种修饰:

  • 访问权限控制符:public, protected, private
  • 抽象的、需要实现的:abstract
  • 限制只能有一个实例的:static
  • 不允许修改的:final
  • 线程同步锁:synchronized
  • 原生函数:native
  • 采用严格的浮点精度:strictfp
  • 接口
  • 注解

当然上面的修饰符不是所有类(或接口)都可以修饰,比如:

  • Interface 不能是 final
  • enum 不能是 abstract

java.lang.reflect.Modifier 可以用来解码 Class 修饰符。我们可以使用 Class.getModifiers() 获得调用类的修饰符的二进制值,然后使用 Modifier.toString(int modifiers) 将获取到的二进制值转换为字符串。

实例:

测试类:

public class A
{
	String name;
	public class B{};
	protected class C{};
	private class D{};
	public static class E{};
	abstract class F{};
	interface G{};
}

测试类:

public class ModifierTest 
{
	public static void printModifier(String ClassPath) throws ClassNotFoundException
	{
		Class aClass=Class.forName(ClassPath);
		int modifier=aClass.getModifiers();
		System.out.println(ClassPath+"的修饰符为:"+Modifier.toString(modifier));
	}
	public static void main(String[] args) throws ClassNotFoundException
	{
		printModifier("reflect.A");
		printModifier("reflect.A$B");
		printModifier("reflect.A$C");
		printModifier("reflect.A$D");
		printModifier("reflect.A$E");
		printModifier("reflect.A$F");
		printModifier("reflect.A$G");
	}
	
}

运行结果:

reflect.A的修饰符为:public
reflect.A$B的修饰符为:public
reflect.A$C的修饰符为:protected
reflect.A$D的修饰符为:private
reflect.A$E的修饰符为:public static
reflect.A$F的修饰符为:abstract
reflect.A$G的修饰符为:abstract static interface

下面给上Modifier.toString(int modifiers)JDK的源码:

 public static String toString(int mod) {
        StringBuilder sb = new StringBuilder();
        int len;

        if ((mod & PUBLIC) != 0)        sb.append("public ");
        if ((mod & PROTECTED) != 0)     sb.append("protected ");
        if ((mod & PRIVATE) != 0)       sb.append("private ");

        /* Canonical order */
        if ((mod & ABSTRACT) != 0)      sb.append("abstract ");
        if ((mod & STATIC) != 0)        sb.append("static ");
        if ((mod & FINAL) != 0)         sb.append("final ");
        if ((mod & TRANSIENT) != 0)     sb.append("transient ");
        if ((mod & VOLATILE) != 0)      sb.append("volatile ");
        if ((mod & SYNCHRONIZED) != 0)  sb.append("synchronized ");
        if ((mod & NATIVE) != 0)        sb.append("native ");
        if ((mod & STRICT) != 0)        sb.append("strictfp ");
        if ((mod & INTERFACE) != 0)     sb.append("interface ");

        if ((len = sb.length()) > 0)    /* trim trailing space */
            return sb.toString().substring(0, len-1);
        return "";
    }

总结:

Class.getModifiers():获取当前Class类的修饰符编码(int 类型),

Modifier.toString(int modifiers):把上面获取到的修饰符编码,转换成字符串形式。

注意:

  • Interface 默认是 abstract 的,虽然我们没有添加,编译器会在编译器为每个 Interface 添加这个修饰符。
  • 只有被 @Retention(RetentionPolicy.RUNTIME) 修饰的注解才可以在运行时被发射获取
  • Java 中预定义的注解 @Deprecated,@Override, 和 @SuppressWarnings 中只有 @Deprecated 可以在运行时被访问到

6. 获取Class对应的类或者接口的成员Member(成员有:属性,方法,构造方法)

java.lang.reflect.Member 是一个接口,代表 Class 的成员,每个成员都有类型,分为是否从父类继承,还有是否可以直接访问。

Member 有三个实现类:

  • java.lang.reflect.Constructor:表示该 Class 的构造函数
  • java.lang.reflect.Field:表示该 Class 的成员变量
  • java.lang.reflect.Method:表示该 Class 的成员方法

(1)获取构造函数

java.lang.Class 提供了以下方法用于获取该类的构造函数:

a.返回构造器数组:

 Constructor<?>[] getDeclaredConstructors();//返回所有的构造方法的Constructor对象的数组的Constructor对象的数组
 Constructor<?>[] getConstructors();        //返回所有共有的构造方法的Constructor对象的数组

b.返回指定的一个构造器:

Constructor<T> getConstructor(Class<?>... parameterTypes) 
          返回一个 Constructor 对象,它反映此 Class 对象所表示的类的指定公共构造方法。 
Constructor<T> getDeclaredConstructor(Class<?>... parameterTypes) 
          返回一个 Constructor 对象,该对象反映此 Class 对象所表示的类或接口的指定构造方法。 

(2)获取成员变量

java.lang.Class 提供了以下方法用于获取该类的成员变量:

a.返回字段对象数组:

Field[] getFields() 
          返回此 Class 对象所表示的类或接口的所有公有字段数组(Field 对象数组)
Field[] getDeclaredFields() 
          返回此 Class 对象所表示的类或接口中所有声明的字段数组(Field对象数组)。 

b.返回单个字段对象:

Field getField(String name) 
          返回此 Class 对象所表示的类或接口的指定的公有成员字段对象(Field对象)。 
 Field getDeclaredField(String name) 
          返回一个此 Class 对象所表示的类或接口的指定已声明字段(Field 对象)

7.获取成员方法

java.lang.Class 提供了以下方法用于获取该类的成员方法:

a.获取方法对象数组:第一个只能获取public修饰的方法数组,第二个可以获取除继承外的所有方法

 Method[] getMethods() 
          返回一个包含某些 Method 对象的数组,这些对象反映此 Class 对象所表示的类或接口
          (包括那些由该类或接口声明的以及从超类和超接口继承的那些的类或接口)的公共 member 方法 
 Method[] getDeclaredMethods() 
          返回 Method 对象的一个数组,这些对象反映此 Class 对象表示的类或接口声明的所有方法,
           包括公共、保护、默认(包)访问和私有方法,但不包括继承的方法。 

b.获取单个方法:第一个只能获取到public修饰的方法,第二个能获取除继承外的方法所有方法(公有,保护,默认,私有)

Method getMethod(String name, Class<?>... parameterTypes) 
          返回一个 Method 对象,它反映此 Class 对象所表示的类或接口的指定的public成员方法。 
Method getDeclaredMethod(String name, Class<?>... parameterTypes) 
          返回一个 Method 对象,该对象反映此 Class 对象所表示的类或接口的指定已声明方法。

8.创建对象的方法:

 T newInstance() 
          创建此 Class 对象所表示的类的一个新实例。

9.返回字符串(String)的方法:

 String getCanonicalName() 
          返回 Java Language Specification 中所定义的底层类的规范化名称。 
 String getName() 
          以 String 的形式返回此 Class 对象所表示的实体(类、接口、数组类、基本类型或 void)名称(全限定名:包名.类名)。
 String getSimpleName() 
          返回源代码中给出的底层类的简称。 
 String toString() 
          将对象转换为字符串。 

解释:

(1)获取当前Class表示的类的完整名字:(包名.类名):

public String getName();
//以 String 的形式返回此 Class 对象所表示的实体(类、接口、数组类、基本类型或 void)名称。 

(2)获取当前Class表示的实体的简称(类名):

public String getSimpleName();
//返回源代码中给出的底层类的简称。如果底层类是匿名的则返回一个空字符串。 

(3)把对象转换成String:这个方法太常见了,不举例了。

 String toString() 
          将对象转换为字符串。

(4)返回底层类的规范化名称:

 String getCanonicalName() 
          返回 Java Language Specification 中所定义的底层类的规范化名称。 

例如:

public static void main(String[] args) throws ClassNotFoundException
{
	Class<String> strClass = (Class<String>) Class.forName("java.lang.String");
	System.out.println("当前Class表示的实体的      规范化名字:"+strClass.getCanonicalName());
	System.out.println("当前Class表示的实体的          完整名字:"+strClass.getName());
	System.out.println("当前Class表示的实体的                  简称:"+strClass.getSimpleName());
	System.out.println("当前Class表示的实体的toString():"+strClass.toString());
}

结果:

当前Class表示的实体的      规范化名字:java.lang.String
当前Class表示的实体的          完整名字:java.lang.String
当前Class表示的实体的                  简称:String
当前Class表示的实体的toString():class java.lang.String

10.返回boolean的方法:

(1)判断当前类是什么类

boolean isLocalClass()     ;//判断是不是局部类,也就是方法里面的类 
boolean isMemberClass()    ;//判断是不是成员内部类,也就是一个类里面定义的类
boolean isAnonymousClass() ;//判断当前类是不是匿名类,匿名类一般用于实例化接口

实例:

public class ClassTest{  
    public static void main(String[] args) {  
        ClassTest son = new ClassTest();  
 
        //测试匿名类  
        son.testAnonymous(new AnonymousClass() {  
            @Override  
            public void test() {  
                System.out.println("AnonymousClass是成员类:-> " + this.getClass().isMemberClass());  
                System.out.println("AnonymousClass是匿名类: -> " + this.getClass().isAnonymousClass());  
                System.out.println("AnonymousClass是局部类:-> " + this.getClass().isLocalClass());  
                System.out.println("---------------------------------------");  
            }  
        });  
        //测试成员类  
        son.testMember();  
        //测试静态成员类  
        new StaticMemberClass();  
        //测试局部类  
        class LocalClass{  
            public LocalClass(){  
                System.out.println("LocalClass是成员类:-> " + this.getClass().isMemberClass());  
                System.out.println("LocalClass是匿名类: -> " + this.getClass().isAnonymousClass());  
                System.out.println("LocalClass是局部类:-> " + this.getClass().isLocalClass());  
                System.out.println("---------------------------------------");  
            }  
        }  
        new LocalClass();  
    }  
    //测试匿名内部类
    private void testAnonymous(AnonymousClass inner) {  
        inner.test();  
    }  
    //测试成员内部类:
    private void testMember() {  
        new MemberClass();  
    }  
      
    /** 
     * 接口,用于测试匿名类
     */  
    interface AnonymousClass{  
        public void test();  
    }  
      
    /** 
     * 静态成员类 
     */  
    static class StaticMemberClass{  
        public StaticMemberClass() {  
            System.out.println("StaticMemberClass是成员类:-> " + this.getClass().isMemberClass());  
            System.out.println("StaticMemberClass是匿名类: -> " + this.getClass().isAnonymousClass());  
            System.out.println("StaticMemberClass是局部类:-> " + this.getClass().isLocalClass()); 
            System.out.println("---------------------------------------");  
        }  
    }  
    /** 
     * 成员类 
     */  
    class MemberClass{  
        public MemberClass() {  
        	 System.out.println("MemberClass是成员类:-> " + this.getClass().isMemberClass());  
             System.out.println("MemberClass是匿名类: -> " + this.getClass().isAnonymousClass());  
             System.out.println("MemberClass是局部类:-> " + this.getClass().isLocalClass());  
            System.out.println("---------------------------------------");  
        }  
    }  
}  

运行结果:

AnonymousClass是成员类:-> false
AnonymousClass是匿名类: -> true
AnonymousClass是局部类:-> false
---------------------------------------
MemberClass是成员类:-> true
MemberClass是匿名类: -> false
MemberClass是局部类:-> false
---------------------------------------
StaticMemberClass是成员类:-> true
StaticMemberClass是匿名类: -> false
StaticMemberClass是局部类:-> false
---------------------------------------
LocalClass是成员类:-> false
LocalClass是匿名类: -> false
LocalClass是局部类:-> true
---------------------------------------

(2)其他返回boolean的方法:—》以后再给例子

 boolean isAnnotation() ;//判断当前Class对象是否是注释类型
 boolean isAnnotationPresent(Class<? extends Annotation> annotationClass) 
          如果指定类型的注释存在于此元素上,则返回 true,否则返回 false。
 boolean isAssignableFrom(Class<?> cls) 
          判定此 Class 对象所表示的类或接口与指定的 Class 参数所表示的类或接口是否相同,或是否是其超类或超接口。 
 boolean isEnum() 
          当且仅当该类声明为源代码中的枚举时返回 true。 
 boolean isInstance(Object obj) 
          判定指定的 Object 是否与此 Class 所表示的对象赋值兼容。 
 boolean isInterface() 
          判定指定的 Class 对象是否表示一个接口类型。 
 boolean isPrimitive() 
          判定指定的 Class 对象是否表示一个基本类型。 
 boolean isSynthetic() 
          如果此类是复合类,则返回 true,否则 false。

参考:

张拭心的博客 shixinzhang 的:深入理解 Java 反射:Class (反射的入口)

张兴华的技术博客 的:匿名内部类、成员类与局部类

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

发布者:全栈程序员-用户IM,转载请注明出处:https://javaforall.cn/140731.html原文链接:https://javaforall.cn

【正版授权,激活自己账号】: Jetbrains全家桶Ide使用,1年售后保障,每天仅需1毛

【官方授权 正版激活】: 官方授权 正版激活 支持Jetbrains家族下所有IDE 使用个人JB账号...

(0)


相关推荐

发表回复

您的电子邮箱地址不会被公开。

关注全栈程序员社区公众号