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 (反射的入口)

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

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

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

(0)
全栈程序员-站长的头像全栈程序员-站长


相关推荐

  • jvm面试题2021_jvm运行原理及调优面试题

    jvm面试题2021_jvm运行原理及调优面试题2022最新JVM面试题1.JDK、JRE、JVM关系?2.启动程序如何查看加载了哪些类,以及加载顺序?3.class字节码文件10个主要组成部分?4.画一下jvm内存结构图?5.程序计数器6.Java虚拟机栈7.本地方法栈8.Java堆9.方法区10.运行时常量池?11.什么时候抛出StackOverflowError?12.Java7和Java8在内存模型上有什么区别?13.程序员最关注的两个内存区域?14.直接内存是什么?15.除了哪个区域外,虚拟机内存其他运行时区域都会发生OutOfMemo

    2022年8月27日
    6
  • AT命令集详解_at命令详解

    AT命令集详解_at命令详解1.AT的历史与应用   1.1AT的历史AT命令集是由拨号调制解调器(MODEM)的发明者贺氏公司(Hayes)为了控制Modem发明的控制协议.AT是Attention的缩写,协议本身采用文本.每个命令均以AT打头,因此得名.这段历史参见http://en.wikipedia.org/wiki/Hayes_command_set 随着网络升级为宽带,速度很低拨号MODEM

    2025年7月25日
    6
  • bgp多线是什么宽带_双线制

    bgp多线是什么宽带_双线制众所周知,南方带宽主要是以电信为主,北方带宽主要以联通为主,要想实现南北互联互通,就要选择双线服务器托管,目前双线服务器托管一般有两种,即双线双ip服务器托管和bgp双线服务器托管,这两者有什么区别呢?    双IP双线路实现方式是指在一台服务器上安装两块网卡,分别接入电信网线与网通网线并设置一个网通IP与一个电信IP,这样一台服务器上就有了两个IP地址,需要在服务器上添加网通或

    2025年6月9日
    4
  • python中merge函数「建议收藏」

    python中merge函数「建议收藏」merge函数用来合并下面我们看看长什么样子merge(left,right,how=’inner’,on=None,left_on=None,right_on=None,left_index=False,right_index=False,sort=False,suffixes=(‘_x’,’_y’),copy=True,indicator=False,valida…

    2022年6月1日
    61
  • OpenGL中glPushMatrix和glPopMatrix的原理「建议收藏」

    转自:http://www.bubuko.com/infodetail-435954.htmlglPushMatrix、glPopMatrix操作事实上就相当于栈里的入栈和出栈。  很多人不明确的可能是入的是什么,出的又是什么。比如你当前的坐标系原点在你电脑屏幕的左上方。如今你调用glPushMatrix,然后再调用一堆平移、旋转代码等等,然后再绘图。那些平移和旋转都是基于左上角为

    2022年4月8日
    60
  • 相机标定(Camera calibration)

    相机标定(Camera calibration)简介摄像机标定(Cameracalibration)简单来说是从世界坐标系换到图像坐标系的过程,也就是求最终的投影矩阵PP的过程,下面相关的部分主要参考UIUC的计算机视觉的课件(网址Spring2016CS543/ECE549 Computervision)。基本的坐标系:世界坐标系(worldcoordinatesystem);相机坐标系(cameracoordina

    2022年5月28日
    40

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

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