关于Java.lang.Class的一些疑问

请问大家一些问题,今天看到一个这样的代码:

图片描述

后来我根据自己对java.lang.Class对象的了解,改写成这样,但是编译器提醒我要转换类型。

图片描述

我产生了 几个问题:

  • Class对象是一个集合吗? 为什么要用Class<User>这样的泛型约束?
  • 为什么通过User.class获取的类型不需要转换成Class<User>,而其它两种则需要?
  • 这个参数传入BeanListHandler一般起什么作用?他和new User() ,User.this有什么区别
  • 对这个知识比较疑惑,大家有没有好的文章分享一下。一般有哪些比较常用的场景?
阅读 2.2k
2 个回答
  • Class是一个对象,用来描述java中一个类的结构。实际上可以不用泛型约束,只是泛型的好处就在于可以将运行时错误提前到编译时错误。
  • User.class可以在编译时就确定下来Class的泛型,而new User().getClass()实际上是运行时才能确定下来实际是什么泛型。举个例子:

    public class User{
    }
    public class Student extends User{
        public static void main(String[] args) {
            User user1 = new User();
            User user2 = new Student();
            //输出User
            System.out.println(user1.getClass());
            //输出Student
            System.out.println(user2.getClass());
        }
    }

    由此可见,Object.getClass()方法返回的Class泛型是运行时才能确定的,所以返回的类型是Class<?>,顺带贴下jdk源码上的注释

    /**
         * Returns the runtime class of this {@code Object}. The returned
         * {@code Class} object is the object that is locked by {@code
         * static synchronized} methods of the represented class.
         *
         * <p><b>The actual result type is {@code Class<? extends |X|>}
         * where {@code |X|} is the erasure of the static type of the
         * expression on which {@code getClass} is called.</b> For
         * example, no cast is required in this code fragment:</p>
         *
         * <p>
         * {@code Number n = 0;                             }<br>
         * {@code Class<? extends Number> c = n.getClass(); }
         * </p>
         *
         * @return The {@code Class} object that represents the runtime
         *         class of this object.
         * @see    Class Literals, section 15.8.2 of
         *         <cite>The Java&trade; Language Specification</cite>.
         */
        public final native Class<?> getClass();
  • Class对象当参数传入方法中,因为需要一个Class对象的实例来操作反射进行类的创建,还是直接看代码:

    public static <T> T getT(Class<T> clazz) throws Exception{
        return clazz.newInstance();
    }

    注意这里T和clazz不是同一个概念,一个是类型一个是实例。即如果不传Class<T>的实例的话,用T是完成不了对象的创建的。

    //对照上面,T泛型表示Studen,而clazz则是Class<Student>的实例
    Class<Studen> clazz = Studen.class;
  • 建议查阅下泛型、Class和运行时类型、编译时类型相关的知识,运用场景很多了比如Spring的getBean()方法,hibernate的get()方法等等,都是配合反射来动态生成相应的对象。

谢邀,:))

手机上作答。这些是关于反射的技术,我大概答一答。

类的确是一个容器,但是这个容器包含了什么信息呢?它包含了关于类的信息,比如这个类的父类是什么,实现了什么接口,有什么构造方法,有什么方法,有什么成员变量,每个成员变量的类型是什么等等。

每个类都有各自的类容器,每个类的所有实例都会关连到同一个相应的类容器,所以每个实例才会知道怎样调用方法,怎样使用成员变量等。

同时,每个类容器本身又是一个对象(Class 类的实例),也就是每个类容器对应唯一一个 Class 的实例,但是每个类容器可以对应无数的类实例。那么,怎样获取这个类容器(也就是这个 Class 的实例)呢?正如你所说,有三种方法:

  1. User.class
  2. user.getClass()
  3. Class.forName()

这三种方法得到的都是同一个类容器!至于为什么后面两种方法要转型,是因为 getClassObject 上的方法,而 Class.forName() 接收的参数是字符串,根本没有足够类型信息可以推断,当然需要你手动转型。

一旦拥有了类容器,就相当于拥有了这个类的源码一样,可以通过它查看有哪些成员变量,变量名分别是什么,类型是什么,从而可以利用这些信息建表,又可以查看它有什么构造方法,从而可以创建新的实例并返回给你。

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题