Java 反射
1、什么是反射?
官方:在程序的运行状态中,可以构造任意一个类的对象,可以了解任意一个对象所属的类,可以了解任意一个类的成员变量和方法,可以调用任意一个对象的属性和方法。这种动态获取程序信息以及动态调用对象的功能称为Java语言的反射机制。
仅仅从概念上我们还无法真正了解反射,通过下面的学习,我相信你会突然对反射机制恍然大悟。那么就让我们一起去瞧瞧吧!
2、Class 类的使用
(1)首先大家都知道在Java中,万物皆对象。好,那么成员变量、成员方法、静态成员变量等等这些都是不是对象呢?
答案:是的。
(2)那么类是对象吗?,是的话又是谁的对象呢?
答案:类是对象,类是 java.lang.Class类的实例对象。
例如:
public class Main {
}
我们就可以认为 Main这个类是 java.lang.Class 类的实例对象。
(3)相信大家都知道,如何获取某个类的对象
通过这段代码,我们就轻松的获得了 Foo 这个类的实例对象 f1
public class ClassDemo1 {
public static void main(String[] args) {
Foo f1 = new Foo();
}
}
class Foo{}
(4)我们说过,类是对象同时它是java.lang.Class类的实例对象。那如何表示Class的实例对象呢?
有三种表示方式
这里我们拿 Foo这个类来举例,当然也可以拿任意其他类,因为所有的类都是Class类的实例对象。
- 方式一
Class c1 = Foo.class;
从方式一中,可以得到一个结论:
任何一个类都有一个隐含的静态成员变量。
- 方式二
Foo f1 = new Foo();
Class c2 = f1.getClass();
- 方式三
Class.forName(“类的全称”)
try {
Class c3 = Class.forName("com.wangrui.reflect.Foo");
} catch (ClassNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
(5)c1、c2 对象,我们称之为该类的类类型。
如果拿Foo 来说,c1、c2就是Foo 的类类型。那么我就敢说 c1、c2、c3都是同一个对象。如果不了解 == 和equals比较的同学建议看我的这篇博客《Java ==和equals有什么区别?》。
System.out.println(c1==c2);
System.out.println(c2 == c3);
运行结果:
true
true
(6)通过该类的类类型创建该类的对象实例,并且调用该类的某个方法
public class ClassDemo1 {
public static void main(String[] args) {
Class c1 = Foo.class;
try {
Foo foo = (Foo) c1.newInstance();
foo.start();
} catch (InstantiationException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IllegalAccessException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
class Foo{
public void start() {
System.out.println("未来的你会感谢此刻的自己");
}
}
运行结果:
未来的你会感谢此刻的自己
3、动态加载类
(1)静态加载类、动态加载类
静态加载类:编译时可加载的类
动态加载类:运行时刻加载的类
我们之前提到的 Class.forName(“类的全称”),不仅表示类的类类型,同时还代表了动态加载类。
(2)为什么要有动态加载类
假如现在有一个场景:要求运行 Word里的start()方法
源代码项目结构
word.java
public class Word {
public static void start() {
System.out.println("word");
}
}
Office.java
可以看到 Excel处报错,无法执行程序,很明显是因为 Excel 类不存在。那么现在我的要求是,Word 存在,程序就能执行Word。那么按照这种写法很显然就会有问题,因为:
new 创建对象 是静态加载类,在编译时刻就需要加载所有的可能使用到的类
所以 Excel不存在,自然就通过不了编译。如果以后我们有一百个功能,只要1个功能有问题,其他99个就都用不了了。
(3)通过动态加载类就能解决上面的问题
新建:OfficeBetter.java
public class OfficeBetter {
public static void main(String[] args) {
try {
//动态加载类,在运行时刻加载
Class c = Class.forName("com.wangrui.reflect.Word");
} catch (Exception e) {
e.printStackTrace();
}
}
}
我们都知道,通过类的类类型就可以创建该类的对象,但是我们不能如下这么写:
Word w = (Word) c.newInstance(); //c加载Excel就会报错
Excel e = (Excel) c.newInstance(); //c加载Word就会报错
这种时候我们就需要给他们制定统一标准
我们可以让 Word 和 Excel都属于 OfficeAble这个标准,如下
OfficeAble oa = (OfficeAble) c.newInstance();
详细步骤:
新增:OfficeAble.java 接口
public interface OfficeAble {
public void start();
}
让Word 遵循这个标准,Word.java
public class Word implements OfficeAble{
public void start() {
System.out.println("word");
}
}
回到 OfficeBetter.java
public class OfficeBetter {
public static void main(String[] args) {
try {
//动态加载类,在运行时刻加载
Class c = Class.forName("com.wangrui.reflect.Word");
OfficeAble oa = (OfficeAble) c.newInstance();
oa.start();
} catch (Exception e) {
e.printStackTrace();
}
}
}
运行结果:
这样就就解决了当 Excel不存在的时候,我们也能使用 Word这个功能。
如果将来我们增加 Excel功能,就可以
public class Excel implements OfficeAble{
@Override
public void start() {
System.out.println("excel 启动啦");
}
}
OfficeBetter.java
Class c = Class.forName("com.wangrui.reflect.Excel");
运行结果:
如果将来还需要增加 PPT功能,也是一个同上一个道理,这样就避免了传统写法的错误,一个功能用不了就都用不了。
4、获取方法信息
(1)回顾一下前面
- 表示:double这个类型 的类类型
Class c1 = double.class;
- 表示:Double这个类 的类类型
Class c2 = Double.class;
- 拓展1:void关键字也有它的类类型
Class c3 = void.class;
- 拓展2:String 类的类类型,也表示String 类的字节码
Class c4 = String.class;
(2)获取类的名称、方法对象、
5、获取成员变量构造函数信息
6、方法反射的基本操作
7、通过反射了解集合泛型的本质
相关文章
- java字符串的拆分_Java中的字符串分割 .
- java map 二维数组_Java二维数组实现简单Map
- java分布式框架_5个强大的Java分布式缓存框架推荐
- java和c语言哪个简单_Java编程和C语言哪个好学
- 【说站】java内存屏障有哪些类型
- Deep Java Library_java atomicinteger
- mysql和oracle的sql区别有什么_java和oracle的关系
- java中遍历数组的方法_java遍历object数组
- 【错误记录】生成 Java 文档错误 ( Xxx.java:xx: 错误: 编码GBK的不可映射字符 )
- 八皇后问题-Java
- Java中英文字母汉字混合字符长度值计算详解编程语言
- Java学习笔记之六java三种循环(for,while,do……while)的使用方法及区别详解编程语言
- 实现Linux上的Java环境:从安装到配置(linux安装java环境)
- Java中/r和/n的区别详解编程语言
- Java基础-IO流详解编程语言
- 实现Java实现Redis集合的技术研究(redis集合java)
- 构建Java应用程序中Redis集群的方法(java连redis集群)
- java使用Weka、Linux和Java构建强大的数据分析系统(weka linux)
- java使用swt显示图片示例分享
- java获取当前路径下的所有xml文档的方法