您的位置:首页 > 编程语言 > Java开发

Java反射机制

2019-09-21 17:09 218 查看
版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。 本文链接:https://blog.csdn.net/weixin_41924879/article/details/101109772

Java反射机制

Java反射机制是在运行状态中,对于任意一个实体类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意方法和属性;这种动态获取信息以及动态调用对象方法的功能称为Java语言的反射机制。

Java的反射机制允许编程人员在对类未知的情况下,获取类相关信息的方式变得更加多样灵活,调用类中相应方法,是Java增加其灵活性与动态性的一种机制。

反射机制(Reflection)是Java提供的一项较为高级的功能,它提供了一种动态功能,而此功能的体现在于通过反射机制相关的API就可以获取任何Java类的包括属性、方法、构造器、修饰符等信息。元素不必在JⅧ运行时进行确定,反射可以使得它们在运行时动态地进行创建或调用。反射技术在中间件领域应用得较多。

功能

1、获得某个对象的属性
通过getClass()方法获得某个对象的类,然后实例化一个Field对象,接收类声明的属性,最后通过get()方法获得该属性的实例,注意,这里的属性必须为公有的,否则将会报illegalAeeessException的异常。

2、获得某个类的静态属性
首先根据类名获得该类,同获得某个对象的属性一样,通过实例化一个Field对象,接收该类声明的属性,不同的是,由于属性是静态的,所以直接从类中获取。

3、执行某对象的方法
同样要先获得对象的类,然后配置类的数组,并把它作搜索方法的条件。通过getMethod()方法,得到要执行的方法。执行该invoke方法,该方法中执行的是owner对象中带有参数args的方法。返回值是一个对象。

4、执行某个类的静态方法
基本的原理和“执行某个类的方法”相同,不同点在于method.invoke(null,args),这里的第一个参数是null,因为调用的是静态方法,所以不需要借助owner就能运行。

5、新建类的实例
我们利用执行带参数的构造函数的方法来新建一个实例。如果不需要参数,可以直接使用newoneClass.newlnstaneeO来实现嘲。同样要先得到要构造的实例的类,然后构造参数的类数组,构造器是通过getConstructor(argsClass)得到的,最后使用newlnstanee(args)方法新建一个实例。

反射是框架的灵魂

框架:半成品软件,可以在框架的基础上进行软件开发,简化代码。
反射:将类的各个组成部分封装为其他对象,反射机制。

反射的原理就是通过类的字节码文件(class文件)反向获取该类或者对象中的属性,因为是通过字节码获取,则需要JVM的操作。

动静态编译

静态编译:在编译期就确定类或者方法的属性,有点一次到位的意思。
动态编译:在运行期确定类或者方法的属性,好比什么时候用就什么时候编译。

静态编译是一次性编译,对于确定的代码是不能更改的,除非下线,更改,测试,再重新上线,显然这是不妥的。因此就需要动态编译,即在程序运行期间也可以进行相应的操作,一切操作方式都是灵活的,所以说反射对于程序是很重要的。

反射优缺点

优点:

  • 可以在程序运行的过程中,操作这些对象。
  • 可以解耦,提高程序的可扩展性。

缺点:

  • 因为是JVM操作,所以对于性能来说会有所下降。
  • 容易对程序源码造成一定的混乱。

反射图解


同一个字节码文件(*.class)在程序运行过程中,只会被加载一次。

反射获取方式

获取Class对象的方式:

  • Class.forName(“全类名”):将字节码文件加载进内存,返回class对象,多用于配置文件中,将类名定义在配置文件中,读取文件并加载类。
  • 类名.class:通过类名的属性class获取,多用于参数的构造。
  • 对象.getClass():该方法定义在Object中,多用于对象的字节码获取。
public class ReflectDemo {
public static void main(String[] args) throws ClassNotFoundException {
// Class.forName("");
Class c1 = Class.forName("com.api.reflect.User");
System.out.println(c1);
// 类名.class
Class<User> c2 = User.class;
System.out.println(c2);
// .getClass
User user = new User();
Class c3 = user.getClass();
System.out.println(c3);

System.out.println(c1 == c2);
System.out.println(c1 == c3);
System.out.println(c2 == c3);
}
}

运行结果

分析:通过以上三种反射方式都可以获得实例对象,同样也证明三个对象是相同的,也就是对象只会被创建一次。

反射机制的相关类


Class类

  • Class 类的实例对象表示正在运行的 Java 应用程序中的类和接口。也就是jvm中有很多的实例,每个类都有唯一的Class对象。
  • Class 类没有公共构造方法。Class 对象是在加载类时由 Java 虚拟机自动构造的。也就是说我们不需要创建,JVM已经帮我们创建了。
  • Class 对象用于提供类本身的信息,比如有几种构造方法, 有多少属性,有哪些普通方法。

获得类相关的方法

获得类中属性相关的方法

获得类中注解相关的方法

获得类中构造器相关的方法

获得类中方法相关的方法

类中其他重要的方法

Field类
Field代表类的成员变量(成员变量也称为类的属性)

Method类
Method代表类的方法

Constructor类
Constructor代表类的构造方法

Demo

被反射类Book.java

public class Book{
private final static String TAG = "BookTag";

private String name;
private String author;

@Override
public String toString() {
return "Book{" +
"name='" + name + '\'' +
", author='" + author + '\'' +
'}';
}

public Book() {
}

private Book(String name, String author) {
this.name = name;
this.author = author;
}

public String getName() {
return name;
}

public void setName(String name) {
this.name = name;
}

public String getAuthor() {
return author;
}

public void setAuthor(String author) {
this.author = author;
}

private String declaredMethod(int index) {
String string = null;
switch (index) {
case 0:
string = "I am declaredMethod 1 !";
break;
case 1:
string = "I am declaredMethod 2 !";
break;
default:
string = "I am declaredMethod 1 !";
}

return string;
}
}

反射逻辑封装在ReflectClass.java

public class ReflectClass {
private final static String TAG = "peter.log.ReflectClass";

// 创建对象
public static void reflectNewInstance() {
try {
Class<?> classBook = Class.forName("com.android.peter.reflectdemo.Book");
Object objectBook = classBook.newInstance();
Book book = (Book) objectBook;
book.setName("挪威的森林");
book.setAuthor("村上春树");
Log.d(TAG,"reflectNewInstance book = " + book.toString());
} catch (Exception ex) {
ex.printStackTrace();
}
}

// 反射私有的构造方法
public static void reflectPrivateConstructor() {
try {
Class<?> classBook = Class.forName("com.android.peter.reflectdemo.Book");
Constructor<?> declaredConstructorBook = classBook.getDeclaredConstructor(String.class,String.class);
declaredConstructorBook.setAccessible(true);
Object objectBook = declaredConstructorBook.newInstance("Android开发艺术探索","任玉刚");
Book book = (Book) objectBook;
Log.d(TAG,"reflectPrivateConstructor book = " + book.toString());
} catch (Exception ex) {
ex.printStackTrace();
}
}

// 反射私有属性
public static void reflectPrivateField() {
try {
Class<?> classBook = Class.forName("com.android.peter.reflectdemo.Book");
Object objectBook = classBook.newInstance();
Field fieldTag = classBook.getDeclaredField("TAG");
fieldTag.setAccessible(true);
String tag = (String) fieldTag.get(objectBook);
Log.d(TAG,"reflectPrivateField tag = " + tag);
} catch (Exception ex) {
ex.printStackTrace();
}
}

// 反射私有方法
public static void reflectPrivateMethod() {
try {
Class<?> classBook = Class.forName("com.android.peter.reflectdemo.Book");
Method methodBook = classBook.getDeclaredMethod("declaredMethod",int.class);
methodBook.setAccessible(true);
Object objectBook = classBook.newInstance();
String string = (String) methodBook.invoke(objectBook,0);

Log.d(TAG,"reflectPrivateMethod string = " + string);
} catch (Exception ex) {
ex.printStackTrace();
}
}

// 获得系统Zenmode值
public static int getZenMode() {
int zenMode = -1;
try {
Class<?> cServiceManager = Class.forName("android.os.ServiceManager");
Method mGetService = cServiceManager.getMethod("getService", String.class);
Object oNotificationManagerService = mGetService.invoke(null, Context.NOTIFICATION_SERVICE);
Class<?> cINotificationManagerStub = Class.forName("android.app.INotificationManager$Stub");
Method mAsInterface = cINotificationManagerStub.getMethod("asInterface",IBinder.class);
Object oINotificationManager = mAsInterface.invoke(null,oNotificationManagerService);
Method mGetZenMode = cINotificationManagerStub.getMethod("getZenMode");
zenMode = (int) mGetZenMode.invoke(oINotificationManager);
} catch (Exception ex) {
ex.printStackTrace();
}

return zenMode;
}

// 关闭手机
public static void shutDown() {
try {
Class<?> cServiceManager = Class.forName("android.os.ServiceManager");
Method mGetService = cServiceManager.getMethod("getService",String.class);
Object oPowerManagerService = mGetService.invoke(null,Context.POWER_SERVICE);
Class<?> cIPowerManagerStub = Class.forName("android.os.IPowerManager$Stub");
Method mShutdown = cIPowerManagerStub.getMethod("shutdown",boolean.class,String.class,boolean.class);
Method mAsInterface = cIPowerManagerStub.getMethod("asInterface",IBinder.class);
Object oIPowerManager = mAsInterface.invoke(null,oPowerManagerService);
mShutdown.invoke(oIPowerManager,true,null,true);

} catch (Exception ex) {
ex.printStackTrace();
}
}

public static void shutdownOrReboot(final boolean shutdown, final boolean confirm) {
try {
Class<?> ServiceManager = Class.forName("android.os.ServiceManager");
// 获得ServiceManager的getService方法
Method getService = ServiceManager.getMethod("getService", java.lang.String.class);
// 调用getService获取RemoteService
Object oRemoteService = getService.invoke(null, Context.POWER_SERVICE);
// 获得IPowerManager.Stub类
Class<?> cStub = Class.forName("android.os.IPowerManager$Stub");
// 获得asInterface方法
Method asInterface = cStub.getMethod("asInterface", android.os.IBinder.class);
// 调用asInterface方法获取IPowerManager对象
Object oIPowerManager = asInterface.invoke(null, oRemoteService);
if (shutdown) {
// 获得shutdown()方法
Method shutdownMethod = oIPowerManager.getClass().getMethod(
"shutdown", boolean.class, String.class, boolean.class);
// 调用shutdown()方法
shutdownMethod.invoke(oIPowerManager, confirm, null, false);
} else {
// 获得reboot()方法
Method rebootMethod = oIPowerManager.getClass().getMethod("reboot",
boolean.class, String.class, boolean.class);
// 调用reboot()方法
rebootMethod.invoke(oIPowerManager, confirm, null, false);
}
} catch (Exception e) {
e.printStackTrace();
}
}
}

调用相应反射逻辑方法

try {
// 创建对象
ReflectClass.reflectNewInstance();

// 反射私有的构造方法
ReflectClass.reflectPrivateConstructor();

// 反射私有属性
ReflectClass.reflectPrivateField();

// 反射私有方法
ReflectClass.reflectPrivateMethod();
} catch (Exception ex) {
ex.printStackTrace();
}

Log.d(TAG," zenmode = " + ReflectClass.getZenMode());

Log输出结果如下:

08-27 15:11:37.999 11987-11987/com.android.peter.reflectdemo D/peter.log.ReflectClass: reflectNewInstance book = Book{name='Android进阶之光', author='刘望舒'}
08-27 15:11:38.000 11987-11987/com.android.peter.reflectdemo D/peter.log.ReflectClass: reflectPrivateConstructor book = Book{name='Android开发艺术探索', author='任玉刚'}
08-27 15:11:38.000 11987-11987/com.android.peter.reflectdemo D/peter.log.ReflectClass: reflectPrivateField tag = BookTag
08-27 15:11:38.000 11987-11987/com.android.peter.reflectdemo D/peter.log.ReflectClass: reflectPrivateMethod string = I am declaredMethod 1 !
08-27 15:11:38.004 11987-11987/com.android.peter.reflectdemo D/peter.log.ReflectDemo:  zenmode = 0

参考文章:
https://baike.baidu.com/item/JAVA%E5%8F%8D%E5%B0%84%E6%9C%BA%E5%88%B6/6015990?fr=aladdin
https://www.jianshu.com/p/9be58ee20dee
https://www.cnblogs.com/fenjyang/p/11512045.html

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: