美文网首页
java反射

java反射

作者: flynnny | 来源:发表于2021-02-21 01:15 被阅读0次

定义

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

用途

在日常的第三方应用开发过程中,经常会遇到某个类的某个成员变量、方法或是属性是私有的或是只对系统应用开放,这时候就可以利用 Java 的反射机制通过反射来获取所需的私有成员或是方法。
当然,也不是所有的都适合反射,之前就遇到一个案例,通过反射得到的结果与预期不符。阅读源码发现,经过层层调用后在最终返回结果的地方对应用的权限进行了校验,对于没有权限的应用返回值是没有意义的缺省值,否则返回实际值起到保护用户的隐私目的。

反射机制的相关类
与 Java 反射相关的类如下:

1.png

Class 类
Class 代表类的实体,在运行的 Java 应用程序中表示类和接口。在这个类中提供了很多有用的方法,这里对他们简单的分类介绍。
• 获得类相关的方法

2.png

• 获得类中属性相关的方法

3.png

• 获得类中注解相关的方法

4.png

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

5.png

• 获得类中方法相关的方法

6.png

• 类中其他重要的方法

7.png

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

8.png

Method 类
Method 代表类的方法。

9.png

Constructor 类
Constructor 代表类的构造方法。

10.png

示例
为了演示反射的使用,首先构造一个与书籍相关的 model——Book.java,然后通过反射方法示例创建对象、反射私有构造方法、反射私有属性、反射私有方法,最后给出两个比较复杂的反射示例——获得当前 ZenMode 和关机 Shutdown。

• 被反射类 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("Android 进阶之光");
   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,bo
olean.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

总结
本文列举了反射机制使用过程中常用的、重要的一些类及其方法,更多信息和用法需要近一步的阅读 Google 提供的相关文档和示例。
在阅读 Class 类文档时发现一个特点,以通过反射获得 Method 对象为例,一般会提供四种方法,getMethod(parameterTypes)、getMethods()、
getDeclaredMethod(parameterTypes)和getDeclaredMethods()。

getMethod(parameterTypes)用来获取某个公有的方法的对象,getMethods()获得该类所有公有的方法,getDeclaredMethod(parameterTypes)获得该类某个方法,getDeclaredMethods()获得该类所有方法。带有 Declared 修饰的方法可以反射到私有的方法,没有 Declared 修饰的只能用来反射公有的方法。其他的 Annotation、Field、Constructor 也是如此。

在 ReflectClass 类中还提供了两种反射PowerManager.shutdown()的方法,在调用的时候会输出如下 log,提示没有相关权限。之前在项目中尝试反射其他方法的时候还遇到过有权限和没权限返回的值不一样的情况。如果源码中明确进行了权限验证,而你的应用又无法获得这个权限的话,建议就不要浪费时间反射了。

W/System.err: java.lang.reflect.InvocationTargetException
W/System.err: at java.lang.reflect.Method.invoke(Native Method)
W/System.err: at .ReflectClass.shutDown(ReflectClass.java:104)
W/System.err: at .MainActivity$1.onClick(MainActivity.java:25)
W/System.err: at android.view.View.performClick(View.java:6259)
W/System.err: at
android.view.View$PerformClick.run(View.java:24732)
W/System.err: at
android.os.Handler.handleCallback(Handler.java:789)
W/System.err: at
android.os.Handler.dispatchMessage(Handler.java:98)
W/System.err: at android.os.Looper.loop(Looper.java:164)
W/System.err: at
android.app.ActivityThread.main(ActivityThread.java:6592)
W/System.err: at java.lang.reflect.Method.invoke(Native Method)
W/System.err: at
com.android.internal.os.Zygote$MethodAndArgsCaller.run(Zygote.java:24
0)
W/System.err: at
com.android.internal.os.ZygoteInit.main(ZygoteInit.java:769)
W/System.err: Caused by: java.lang.SecurityException: Neither user
10224 nor current process has android.permission.REBOOT.
W/System.err: at
android.os.Parcel.readException(Parcel.java:1942)
W/System.err: at
android.os.Parcel.readException(Parcel.java:1888)
W/System.err: at
android.os.IPowerManager$Stub$Proxy.shutdown(IPowerManager.java:787)
W/System.err: ... 12 more

相关文章

  • 博客地址

    java注解-01、java注解-02、Git面试资源java反射-01、java反射-02、java反射-03为...

  • Java反射机制入门

    Java反射机制入门 一、什么是反射 JAVA反射机制(The JAVA reflection mechanism...

  • Java基础之反射

    Java基础之—反射(非常重要)Java中反射机制详解Java进阶之reflection(反射机制)——反射概念与...

  • 反射之一

    总结内容源自一下文章粗浅看java反射机制反射机制应用实践谈谈java反射机制Java Reflection(反射...

  • 反射之二

    总结内容源自一下文章粗浅看java反射机制反射机制应用实践谈谈java反射机制Java Reflection(反射...

  • Java基础之反射

    Java基础之反射 反射基本介绍 反射的使用通过反射调用属性和方法通过反射获取配置文件 反射基本介绍 Java反射...

  • Java 反射机制

    Java 反射机制 什么是反射 Java 反射是Java语言的一个很重要的特征,它使得Java具体了“动态性”。 ...

  • 一探究竟:Java反射效率低的原因到底在哪?

    预备知识 了解 Java 反射基本用法 看完本文可以达到什么程度 了解 Java 反射原理及 Java 反射效率低...

  • 面试官说:大家都说 Java 反射效率低,你知道原因在哪里么

    预备知识 了解 Java 反射基本用法 看完本文可以达到什么程度 了解 Java 反射原理及 Java 反射效率低...

  • Java面试题之JavaSE高级

    一、Java中的反射 1.说说你对Java中反射的理解 java中的反射首先是能够获取到Java...

网友评论

      本文标题:java反射

      本文链接:https://www.haomeiwen.com/subject/hgacfltx.html