浅谈 Java 中的 Class 类
来源:互联网 发布:mac看图软件推荐 编辑:程序博客网 时间:2024/05/03 01:24
最近一段时间,对于 java 的反射比较感兴趣,于是打算通过深入学习来更好的了解反射的实现机制。于是开始查阅有关反射的博文,但是在学习的过程中,发现 Class
类始终伴随着反射出现。因为多少接触过 Class
类,所以有关反射的代码还是能看懂的,不会影响我学习反射的知识,本就可以直接略过。
但是仔细一想,学习是一个主动的过程,要积极的去解决每一个小的问题,争取在求知过程中不留存疑惑,否则到最后会发现因为这些小问题的存在,使得自己的理解始终停在“知其然,不知所以然”的层面。既然接触到了 Class
类,就应该顺带消化了,这样的才能学到更多的东西。
后续我会和大家分享我在学习反射时的一些心得,在此之前,先分享一下我学习 Class
类的一些体会哈。此次分享没有太多高深的知识,但是还是觉得只要您认真的看完本文,多少会有收获的,哪怕是巩固一下也不错,嘿嘿 : )
面向对象
我们都知道,java 是一门面向对象的语言。在面向对象的世界里,万事万物皆对象,除了静态成员(因为静态成员属于某个类,而不是对象)和普通数据类型。
在面向对象的语言中,我们擅长将现实世界中的一个实际存在的事物抽象并封装成一个类,并在类中添加相应的成员变量(属性)和方法,然后我们就可以创建该类的对象,该对象持有属于自己的成员变量和方法。
既然万事万物皆对象,那么我们的类是不是对象呢?是的,我们写的每一个类都是对象,是 java.lang.Class 类的对象。也就是说,每一个类既有自己的对象,同时也是 Class
类的对象。那么,该如何表示 Class
类的对象呢,让我们接着往下看,以进一步了解 Class
类。
java.lang.Class 类
初识 Class 类
很遗憾直到现在我才认识到 Class 的意义,不敢说这次接触就彻底弄懂了 Class
类,但至少目前所理解的内容可以帮助我更好的分析其他问题了。
都说学习技术最好的方法就是查看源码和官方 API ,那么这次我也这么来,虽然我技术一般,但是格调还是要跟上的!我发现了一篇比较好的从源码角度分析 Class
类的博客,在这里推荐给大家,感兴趣的可以跟着这篇文章把 Class
类的源码过一遍,一定会有收获的。当然,您现在不看也没关系,因为推荐的博客中只有一点是我接下来要强调的,我会在后面给大家概括出来。点我跳转
先来看看 Class
类的构造方法(有删减):
/* * Private constructor. * Only the Java Virtual Machine * creates Class objects. */ private Class(ClassLoader loader) { classLoader = loader; }
根据注释可知,Class 类的构造方法是私有的,只有 Java 虚拟机可以创建该类的对象,因此我们无法在代码中显式地声明一个 Class 对象。这就是我要强调的内容,其对于后面内容的理解十分重要。
Class 类与其他类的关系
由类或类对象得到 Class 类的对象
自定义一个类 MyClass,并声明该类的对象:
class MyClass{}MyClass mClass1 = new MyClass();
在上面说过,Class
类的构造方法是私有的,只有 java 虚拟机可以调用该方法创建该类的对象。也就是说我们无法像定义普通类对象一样,通过 new 直接创建 Class
类的对象。
但是,我们依然可以通过其他方式得到 Class 类的对象
通过类的静态成员表示。每个类都有一个隐含的静态成员class,表示如下:
Class c1 = MyClass.class;
通过类对象的
getClass()
方法。由1不难理解,既然存在静态变量,那么通过对象的 getter 方法,就可以获取静态成员class:Class c2 = mClass1.getClass();
通过
Class
类的静态方法forName()
方法获取Class
的对象。区别于通过 new 创建对象(编译时静态加载),在开发时如果我们需要动态加载我们的功能模块,该方法可以帮助我们实现在程序运行时类的动态加载。try { //注意,forName()需要传入类的全路径 //如果当前类与参数类在同一包下即可省略包名 mClass = Class.forName("custom.OtherClass"); } catch (ClassNotFoundException e) { e.printStackTrace(); }
如果我们的程序中没有 OtherClass 这个类,使用 Class.forName() 动态加载时,在程序编译时刻是不会报错的,只有在运行时刻检测到没有该类才会出错。
类的动态加载和静态加载是 Java 中一个重要的知识点,但因为我们开发时通常都使用 IDE, 其帮助我们自动实现了程序的编译和运行,使得我们常常忽略了程序的编译时和运行时状态。说着说着,我发现这块我有必要再写一篇博客记录一下,今天就先不讨论了。
由 Class 类的对象得到类的对象
我们可以通过类或类对象得到 Class
类的对象,反过来,我们也可以由 Class
类的对象得到类的对象:
MyClass mClass2 = (MyClass)c2.newInstance();
需要提醒您的是:c2.newInstance()
需要调用 MyClass
类的无参构造方法!如果 MyClass
类中存在显示的有参构造方法,会覆盖默认的无参构造方法,同时又没有显示的声明无参构造方法,那么执行这段代码时会直接导致程序Crash掉。下面为大家演示一下:
示例代码,请看注释:
/** * Created by Mr Rui on 2016/5/1. */public class TestDemo { public static void main(String args[]){ //得到 Class 对象 mClass Class mClass = MyClass.class; try { // 由 mClass 实例化 MyClass 的对象, // 需要调用 MyClass 的无参构造方法 MyClass mMyClass = (MyClass) mClass.newInstance(); } catch (Exception e) { e.printStackTrace(); } }}class MyClass{ //有参构造方法,会覆盖默认的无参构造方法 public MyClass(String s){}}
程序异常:
java.lang.InstantiationException: MyClass at java.lang.Class.newInstance(Class.java:427) at TestDemo.main(TestDemo.java:12) at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) at java.lang.reflect.Method.invoke(Method.java:497) at com.intellij.rt.execution.application.AppMain.main(AppMain.java:144)Caused by: java.lang.NoSuchMethodException: MyClass.<init>() at java.lang.Class.getConstructor0(Class.java:3082) at java.lang.Class.newInstance(Class.java:412) ... 6 more
解决办法就是在 MyClass 中的显示的添加一个 无参构造方法,就不再提供示例了。
针对这一点,相信有许多人在使用第三方框架或者开源库时,遇到过因为在类中添加了带参数的构造方法而导致程序出错的情况!针对这个,我的理解是:有些框架是基于反射实现的,它根据我们传入的类对象,使用其 newInstance()
方法获取 Class
对象,进而进行后续的反射操作(不在本文的讨论范围)。可是因为我们无意覆盖了默认的无参构造方法,导致程序无法正常获取 Class
对象,所以就出错了。说到这儿,您应该能理解其中缘由了吧!
这次分享的内容比较少,归结起来就是如何获取 Class
类的对象,以及如何由 Class 对象得到类对象。至于如何使用 Class 对象进行反射操作,如何实现程序运行时动态加载类,在后面的分享中会继续向大家介绍的。
我将所理解知识梳理并整理出来,一方面供大家参考交流,另一方面因为我也处在学习的阶段,希望能得到更多人的指导。如果文中有任何错误或遗漏的地方,还望您给予指正,我会积极完善!
Java 反射基础(上)
- 浅谈 Java 中的 Class 类
- Java中Class类浅谈
- Java中的Class类
- Java中的Class类
- Java中的Class类
- Java中的Class类
- Java中的Class类
- java中的Class类
- Java中的Class类
- java中的Class类
- Java中的Class类
- java中的Class类
- Java中的Class类
- Java中的Class类和Class对象
- java中的Class类与Class对象
- java 中的Class类对象
- 浅谈java中的集合类
- 浅谈Java中的Scanner类
- 深入理解Java虚拟机(二)-对象分配、布局和访问
- 学子天地环境部署
- Android之sharepreference的使用
- Centos6.5 iptables的Filter详解
- 多用途互联网邮件扩展--MIME类型简介
- 浅谈 Java 中的 Class 类
- Yarn源码分析之MRAppMaster上MapReduce作业处理总流程(二)
- LeetCode 344 Reverse String
- zero
- 文章标题
- zmq编译找不到libsodium
- Adam学习15之Fastq在Adam中的初始存储格式AlignmentRecord
- cocos2d-x-2.x与3.x帧动画实现方式的改变
- 算法基础 - 线段树