什么是Java的反射机制
- 对于一个给定的(Class)对象,可以获得这个类(Class)对象的所有属性和方法;
- 对于给定的一个对象,都能够调用他的任意一个属性和方法;
这种动态获取类的内容以及动态调用对象的方法和获取属性的机制,就叫做java的反射机制
Class类
- 在java程序运行的时候jvm会为每一个类创建一个对应的Class类的Class对象,以保存该类相关的类型信息。(可以理解为创建了一个该类的模板,每一个类都会有一个自己的Class对象,但是多个同类型的对象只会存在一个Class对象)
- Class类是类的一种与class关键字是不一样的
- 手动编写的类在程序运行被编译后会产生一个Class对象,该对象表示该类的类型信息,且会被保存在同名.class的文件中
- Class类只存私有构造函数 Class类的对象作用是运行时提供或获得某个对象的类型信息(反射机制的关键所在)
反射机制的作用
反射机制的主要功能主要有:
①得到一个对象所属的类,
②获取一个类的所有成员变量和方法,
③在运行时创建对象,调用对象的方法。
如何实现反射机制
- 通过类名获取 类名.calss
- 通过对象获取 对象.getClass
- 通过全类名获取 Class.forName(“类路径.类名”)
//通过类名获取
Class sclass1 = Stu.class;
//通过对象获取
Stu stu = new Stu();
Class sclass2 = stu.getClass();
//通过全类名获取
Class sclass3 = Class.forName("com.ssmp.entity.Stu");
栗子
假设我有三个女友,我每天看心情挑一个带出去约会。
但是,如果我想要再交第四个女朋友的话,就要再创建一个四号女友,然后还要再约会类中把四号女友给加进去,这样非常的麻烦,而且还不安全,容易被发现。
package com.ssmp.entity;
public class day1026 {
public static void main(String[] args) throws ClassNotFoundException {
BeautifullGirl beautifullGirl = Meeting.love("Girl1");
}
}
//约会类
class Meeting{
public static BeautifullGirl love(String name){
if ("Girl1".equals(name)){
return new Girl1();
}
if ("Girl2".equals(name)){
return new Girl2();
}
if ("Girl3".equals(name)){
return new Girl3();
}
return null;
}
}
//女友类
class BeautifullGirl{
public String age;
public BeautifullGirl(){
}
}
//一号女友
class Girl1 extends BeautifullGirl{
public Girl1(){
System.out.println("今天宠幸一号女友");
}
}
//二号女友
class Girl2 extends BeautifullGirl{
public Girl2(){
System.out.println("今天宠幸二号女友");
}
}
//三号女友
class Girl3 extends BeautifullGirl{
public Girl3(){
System.out.println("今天宠幸三号女友");
}
}
修改过后,如果想要再找女朋友的话就直接,创建一个新的对象就可以了,不用频繁的去修改约会类,这样就比较安全
package com.ssmp.entity;
public class day1026 {
public static void main(String[] args) throws Exception {
BeautifullGirl love = Meeting.love("com.ssmp.entity.Girl3");
}
}
//约会类
class Meeting{
public static BeautifullGirl love(String name) throws Exception {
Class clazz = Class.forName(name);
BeautifullGirl bet = (BeautifullGirl) clazz.newInstance();
return bet;
}
}
//女友类
class BeautifullGirl{
public String age;
public BeautifullGirl(){
}
}
//一号女友
class Girl1 extends BeautifullGirl{
public Girl1(){
System.out.println("今天宠幸一号女友");
}
}
//二号女友
class Girl2 extends BeautifullGirl{
public Girl2(){
System.out.println("今天宠幸二号女友");
}
}
//三号女友
class Girl3 extends BeautifullGirl{
public Girl3(){
System.out.println("今天宠幸三号女友");
}
}
long time = System.currentTimeMillis();
for (int i = 0; i < 1000000; i++) {
//
BeautifullGirl love1 = Meeting1.love("com.ssmp.entity.Girl1");
}
System.out.println("反射创建");
System.out.println(System.currentTimeMillis()-time);// 598
time = System.currentTimeMillis();
for (int i = 0; i <1000000 ; i++) {
BeautifullGirl love2 = Meeting2.love("Girl1");
}
System.out.println("普通创建");
System.out.println(System.currentTimeMillis()-time);// 5
优缺点
优势
- 增加程序的灵活性,避免将固有的逻辑程序写死到代码里
- 代码简洁,可读性强,可提高代码的复用率
缺点
- 相较直接调用在量大的情景下反射性能下降(差距还是非常大的)
- 存在一些内部暴露和安全隐患
long time = System.currentTimeMillis();
for (int i = 0; i < 1000000; i++) {
//
BeautifullGirl love1 = Meeting1.love("com.ssmp.entity.Girl1");
}
System.out.println("反射创建");
System.out.println(System.currentTimeMillis()-time);// 598
time = System.currentTimeMillis();
for (int i = 0; i <1000000 ; i++) {
BeautifullGirl love2 = Meeting2.love("Girl1");
}
System.out.println("普通创建");
System.out.println(System.currentTimeMillis()-time);// 5