关于Java的Class类概念:isLocalClass,isMemberClass,isAnonymousClass,isPrimitive,isSynthetic()

作者:weishu
链接:https://www.zhihu.com/question/67270393/answer/251059300
来源:知乎
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

第一个问题,「本地类,成员类,合成类具体是什么概念?」 其实这些名词本身已经说明了他们自己的意思了,写个例子来说明一下到底何种情况对应这些概念:

public class ClassTest {

    static class StaticMemberClass {
        int a = print(getClass());
    }

    public class MemberClass {
        int a = print(getClass());
    }

    public static void main(String[] args) {

        // 匿名类
        new Cloneable() {
            int a = print(getClass());
        };

        // 成员类
        new ClassTest().new MemberClass();

        // 静态成员类
        new StaticMemberClass();

        // 局部类
        class LocalClass {
            int a = print(getClass());
        }

        new LocalClass();

        final Object proxyInstance = Proxy.newProxyInstance(ClassLoader.getSystemClassLoader(), new Class[]{Cloneable.class}, new InvocationHandler() {
            @Override
            public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                return null;
            }
        });
        print(proxyInstance.getClass());

        for (Field field : MemberClass.class.getDeclaredFields()) {
            System.out.println(String.format("%s isSynthetic: %s", field.getName(), field.isSynthetic()));
        }
    }

    private static int print(Class<?> clazz) {
        System.out.println(String.format("%s isMemberClass : %s", clazz.getName(), clazz.isMemberClass()));
        System.out.println(String.format("%s isLocalClass : %s", clazz.getName(), clazz.isLocalClass()));
        System.out.println(String.format("%s isAnonymousClass : %s", clazz.getName(), clazz.isAnonymousClass()));
        System.out.println(String.format("%s isSynthetic: %s", clazz.getName(), clazz.isSynthetic()));
        System.out.println("-----------------------------");
        return 0; // 返回值没有用,就为了在成员创建的时候可以调用此函数
    }
}

上面代码的输出如下:

me.weishu.epic.test.ClassTest$1 isMemberClass : false
me.weishu.epic.test.ClassTest$1 isLocalClass : false
me.weishu.epic.test.ClassTest$1 isAnonymousClass : true
me.weishu.epic.test.ClassTest$1 isSynthetic: false-----------------------------me.weishu.epic.test.ClassTest$MemberClass isMemberClass : true
me.weishu.epic.test.ClassTest$MemberClass isLocalClass : false
me.weishu.epic.test.ClassTest$MemberClass isAnonymousClass : false
me.weishu.epic.test.ClassTest$MemberClass isSynthetic: false-----------------------------me.weishu.epic.test.ClassTest$StaticMemberClass isMemberClass : true
me.weishu.epic.test.ClassTest$StaticMemberClass isLocalClass : false
me.weishu.epic.test.ClassTest$StaticMemberClass isAnonymousClass : false
me.weishu.epic.test.ClassTest$StaticMemberClass isSynthetic: false--------------------------
me.weishu.epic.test.ClassTest$1LocalClass isMemberClass : false
me.weishu.epic.test.ClassTest$1LocalClass isLocalClass : true
me.weishu.epic.test.ClassTest$1LocalClass isAnonymousClass : false
me.weishu.epic.test.ClassTest$1LocalClass isSynthetic: false---------------------------com.sun.proxy.$Proxy0 isMemberClass : falsecom.sun.proxy.$Proxy0 isLocalClass : false
com.sun.proxy.$Proxy0 isAnonymousClass : falsecom.sun.proxy.$Proxy0 isSynthetic: false-------a isSynthetic: falsethis$0 isSynthetic: true

上面的例子很清楚了,成员类是内部类的子集。
内部类包含四种:静态内部类,成员内部类(非静态内部类),局部内部类,匿名内部类。
合成类没怎么见过,合成方法倒是有很多,比如非静态成员类里面,为了访问外部类的成员,编译器会给它生成一个额外的成员,这个Field就是 “Synthetic”。
第二个问题,“Class应该是JVM预先加载好的对象“ 这句话不对。
Class本质上也是一个对象,对象什么时候可以创建?当然是Runtime启动之后的任何时候。Class对象确实是在运行时动态创建的(除了某些虚拟机内部使用的类型会预先创建)。具体是什么东西创建的呢?ClassLoader。ClassLoader可以通过各种姿势创建Class对象,从本地的jar包中创建,从内存中直接创建,从网络中下载class文件创建。。。除了从文件,内存,网络中通过加载class文件来创建Class对象,Class还可以在运行时动态产生。比如Java的动态代理机制,可以在运行时直接创建出一个全新的Class对象。还有一些第三方的库,比如asm,cglib等,都可以动态创建Class。
回到问题:
1。 那么数组的Class对象到底是什么样的存在? 跟普通的类对象一样,代表对象元数据的存在。
2。 每个类都可以通过数组维度的增加产生无数个不同的Class对象?事实如此。
3。 那JVM怎么预先加载Class对象,还是说Class对象其实是用的时候才产生的?有一些Bootstrap的Class对象是预先加载的,这并非本题的讨论范围之内;其余大部分的Class对象是在用的时候产生的。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Java 中,`Class` 是用于表示一个或接口的元数据信息。`Class` 提供了一些常用方法来获取的信息以及进行反射操作。下面是一些常用的 `Class` 方法及其作用: 1. `getName()`:获取的全限定名(包括包名)。 2. `getSimpleName()`:获取的简单名称(不包括包名)。 3. `getPackage()`:获取所在的包。 4. `getSuperclass()`:获取的父。 5. `getInterfaces()`:获取实现的接口列表。 6. `isInterface()`:判断当前是否是接口。 7. `isEnum()`:判断当前是否是枚举型。 8. `isAnnotation()`:判断当前是否是注解型。 9. `isArray()`:判断当前是否是数组型。 10. `isPrimitive()`:判断当前是否是基本数据型。 11. `getDeclaredFields()`:获取的所有字段(包括私有字段)。 12. `getDeclaredMethods()`:获取的所有方法(包括私有方法)。 13. `getDeclaredConstructors()`:获取的所有构造方法(包括私有构造方法)。 14. `newInstance()`:创建的实例对象(需要无参构造方法)。 15. `getDeclaredField(String name)`:获取指定名称的字段。 16. `getDeclaredMethod(String name, Class<?>... parameterTypes)`:获取指定名称和参数型的方法。 这只是一小部分 `Class` 的方法,还有其他一些方法可以用于获取的注解、泛型信息等。通过 `Class` ,我们可以在运行时获取和操作的信息,实现动态性和灵活性。 需要注意的是,`Class` 的方法在 Java 9 中进行了一些调整和新增,具体使用时请查阅相关文档以及适用你使用的 Java 版本。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值