一.简介
反射机制是Java动态性之一。
所谓动态语言:是指程序在运行时可以改变其结构:新的函数可以引进,已有的函数可以被删除等结构上的变化。比如常见的JavaScript就是动态语言,除此之外Ruby,Python等也属于动态语言,而C、C++则不属于动态语言。
从动态语言能在运行时改变程序结构结构或则变量类型上看,Java和C、C++一样都不属于动态语言。 但是JAVA却有一个非常突出的与动态相关的机制:反射机制。Java通过反射机制,可以在程序运行时加载,探知和使用编译期间完全未知的类,并且可以生成相关类对象实例,从而可以调用其方法或则改变某个属性值。所以JAVA也可以算得上是一个半动态的语言。
二.反射
1.反射机制概念
在Java中的反射机制是指在运行状态中,对于任意一个类都能够知道这个类所有的属性和方法;并且对于任意一个对象,都能够调用它的任意一个方法;这种动态获取信息以及动态调用对象方法的功能成为Java语言的反射机制。
2.反射的应用场合
在Java程序中许多对象在运行时都会出现两种类型:编译时类型和运行时类型。 编译时的类型由声明对象时实用的类型来决定,运行时的类型由实际赋值给对象的类型决定。
如:Person p=new Student();
其中编译时类型为Person,运行时类型为Student。
除此之外,程序在运行时还可能接收到外部传入的对象,该对象的编译时类型为Object,但是程序有需要调用该对象的运行时类型的方法。为了解决这些问题,程序需要在运行时发现对象和类的真实信息。然而,如果编译时根本无法预知该对象和类属于哪些类,程序只能依靠运行时信息来发现该对象和类的真实信息,此时就必须使用到反射了。
3.反射涉及类
<1> 类:Class
作用:反射的核心类,可以获取类的属性,方法等信息。
<2> 类:Field
作用:Java.lang.reflec包中的类,表示类的成员变量,可以用来获取和设置类之中的属性值。
<3> 类:Method
作用:Java.lang.reflec包中的类,表示类的方法,它可以用来获取类中的方法信息或者执行方法。
<4> 类:Constructor
作用:Java.lang.reflec包中的类,表示类的构造方法。
三.代码实现
1.利用反射机制获取类信息
Java Bean
package com.wjn.sqlitedemo.bean;
public class Student implements Cloneable {
private String name;
private String sex;
private String age;
public Student(){
}
public Student(String name,String sex,String age){
this.name=name;
this.sex=sex;
this.age=age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getSex() {
return sex;
}
public void setSex(String sex) {
this.sex = sex;
}
public String getAge() {
return age;
}
public void setAge(String age) {
this.age = age;
}
@Override
public Object clone() throws CloneNotSupportedException {
return super.clone();
}
public String toString(){
return "姓名:"+name+" 性别:"+sex+" 年龄:"+age;
}
}
测试方法
public void reflectionMethod(){
try {
//1.利用Class.forName("类的全路径")方法获取Class对象
Class myclass=Class.forName("com.wjn.sqlitedemo.bean.Student");
//2.利用Method获取Student类的所有方法信息
Method[] method=myclass.getDeclaredMethods();
for(Method m:method){
Log.d("TAG","类的所有方法信息:"+m.toString());
}
Log.d("TAG","********************************************************************");
//3.利用Field获取Student类的所有成员属性信息
Field[] field=myclass.getDeclaredFields();
for(Field f:field){
Log.d("TAG","类的所有成员属性信息:"+f.toString());
System.out.println(f.toString());
}
Log.d("TAG","********************************************************************");
//4.利用Constructor获取Student类的所有构造方法信息
Constructor[] constructor=myclass.getDeclaredConstructors();
for(Constructor c:constructor){
Log.d("TAG","类的所有构造方法信息:"+c.toString());
System.out.println(c.toString());
}
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
结果
类的所有方法信息:public static java.lang.Object com.wjn.sqlitedemo.bean.Student.access$super(com.wjn.sqlitedemo.bean.Student,java.lang.String,java.lang.Object[])
类的所有方法信息:public java.lang.Object com.wjn.sqlitedemo.bean.Student.clone() throws java.lang.CloneNotSupportedException
类的所有方法信息:public java.lang.String com.wjn.sqlitedemo.bean.Student.getAge()
类的所有方法信息:public java.lang.String com.wjn.sqlitedemo.bean.Student.getName()
类的所有方法信息:public java.lang.String com.wjn.sqlitedemo.bean.Student.getSex()
类的所有方法信息:public void com.wjn.sqlitedemo.bean.Student.setAge(java.lang.String)
类的所有方法信息:public void com.wjn.sqlitedemo.bean.Student.setName(java.lang.String)
类的所有方法信息:public void com.wjn.sqlitedemo.bean.Student.setSex(java.lang.String)
类的所有方法信息:public java.lang.String com.wjn.sqlitedemo.bean.Student.toString()
********************************************************************
类的所有成员属性信息:private java.lang.String com.wjn.sqlitedemo.bean.Student.age
类的所有成员属性信息:private java.lang.String com.wjn.sqlitedemo.bean.Student.name
类的所有成员属性信息:private java.lang.String com.wjn.sqlitedemo.bean.Student.sex
类的所有成员属性信息:public static transient volatile com.android.tools.ir.runtime.IncrementalChange com.wjn.sqlitedemo.bean.Student.$change
类的所有成员属性信息:public static final long com.wjn.sqlitedemo.bean.Student.serialVersionUID
********************************************************************
类的所有构造方法信息:public com.wjn.sqlitedemo.bean.Student()
类的所有构造方法信息:public com.wjn.sqlitedemo.bean.Student(java.lang.String,java.lang.String,java.lang.String)
类的所有构造方法信息:com.wjn.sqlitedemo.bean.Student(java.lang.Object[],com.android.tools.ir.runtime.InstantReloadException)
2.利用反射机制创建类对象
Java Bean
package com.wjn.sqlitedemo.bean;
public class Student implements Cloneable {
private String name;
private String sex;
private String age;
public Student(){
}
public Student(String name,String sex,String age){
this.name=name;
this.sex=sex;
this.age=age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getSex() {
return sex;
}
public void setSex(String sex) {
this.sex = sex;
}
public String getAge() {
return age;
}
public void setAge(String age) {
this.age = age;
}
@Override
public Object clone() throws CloneNotSupportedException {
return super.clone();
}
public String toString(){
return "姓名:"+name+" 性别:"+sex+" 年龄:"+age;
}
}
测试方法
public void reflectionMethods(){
//1.利用Class.forName("类的全路径")方法获取Class对象
Class myclass= null;
try {
myclass = Class.forName("com.wjn.sqlitedemo.bean.Student");
//2.利用get set方法创建对象
Student student= null;
try {
student = (Student) myclass.newInstance();
} catch (InstantiationException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
}
student.setName("张三");
student.setSex("男");
student.setAge("27");
Log.d("TAG","利用get set方法创建对象获取类信息:"+student.toString());
Log.d("TAG","********************************************************************");
//3.利用构造方法创建对象
Constructor cc = myclass.getDeclaredConstructor(String.class,String.class,String.class);
Student student1= (Student) cc.newInstance("李四","男","29");
Log.d("TAG","利用构造方法创建对象取类信息:"+student1.toString());
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (NoSuchMethodException e) {
e.printStackTrace();
} catch (InstantiationException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
}
}
结果
利用get set方法创建对象获取类信息:姓名:张三 性别:男 年龄:27
********************************************************************
利用构造方法创建对象取类信息:姓名:李四 性别:男 年龄:29
图解
3.Android中使用反射机制
工具类
public static int getIdByName(Context context, String className, String resName) {
String packageName = context.getPackageName();
int id = 0;
try {
Class r = Class.forName(packageName + ".R");
Class[] classes = r.getClasses();
Class desireClass = null;
for (Class cls : classes) {
if (cls.getName().split("\\$")[1].equals(className)) {
desireClass = cls;
break;
}
}
if (desireClass != null) {
id = desireClass.getField(resName).getInt(desireClass);
}
} catch (Exception e) {
e.printStackTrace();
}
return id;
}
使用
setContentView(MResource.getIdByName(this, "layout", "activity_connectdevice"));
datalayout= (LinearLayout) findViewById(MResource.getIdByName(this, "id", "activity_connectdevice_datalayout"));
pdflayout= (LinearLayout) findViewById(MResource.getIdByName(this, "id", "activity_connectdevice_pdflayout"));
Android的反射机制是在本人打包Android原生代码封装成Cordova插件时用到的。
Cordova 知识讲解:https://blog.csdn.net/weixin_37730482/article/category/7007517