Java反射是在运行状态中,对于任意一个类,都知道这个类的所有属性和方法;对于任意一个对象,都能调用他的任意方法和属性。这种动态获取信息及动态调用对象方法的功能称为Java语言的反射机制。换句话说,Java程序可以加载一个运行时才知道名称的class,获悉其完整构造,并生成其对象实体,或对其fields设值、或唤醒其methods。(摘自360百科)
在讲反射之前,先了解一下如下几个类:
类类(Class类):Class 类的实例表示正在运行的 Java 应用程序中的类和接口。枚举是一种类,注释是一种接口。每个数组属于被映射为 Class 对象的一个类,所有具有相同元素类型和维数的数组都共享该 Class 对象。基本的 Java 类型(boolean、byte、char、short、int、long、float 和 double)和关键字 void 也表示为 Class 对象。(摘自JDK API)
方法类(Method类):Method 提供关于类或接口上单独某个方法(以及如何访问该方法)的信息。所反映的方法可能是类方法或实例方法(包括抽象方法)。(摘自JDK API)
属性类(Field类):Field 提供有关类或接口的单个字段的信息,以及对它的动态访问权限。反射的字段可能是一个类(静态)字段或实例字段。(摘自JDK API)
构造器类(Constructor类):Constructor 提供关于类的单个构造方法的信息以及对它的访问权限。 Constructor 允许在将实参与带有底层构造方法的形参的 newInstance() 匹配时进行扩展转换,但是如果发生收缩转换,则抛出 IllegalArgumentException。(摘自JDK API)
*注意:当一个类被加载且创建对象时,和该类相关的一个类型为Class的对象就会自动创建,任何对象调用getClass()方法都可以获取和该对象相关的一个Class对象。
Class对象经常调用的方法:
String getName() //返回类的名字
Constructor[] getDeclaredConstructors() //返回类的全部构造方法
Field[] getDeclaredFields() //返回类的全部成员变量
Method[] getDeclaredMethods() //返回类的全部方法
如果说到这里都不太好理解,看看下面它们在代码中的使用方式就好了。
一、反射的作用:
1.通过反射机制发现对象的类型,发现类型的方法、属性、构造函数(在可视化编程的时候获取控件类型用的比较多)
2.可以创建对象并访问任意对象方法和属性
作用1代码示例:
package ex;
public class Test {
public static void main(String args[]) {
Class cls = "abc".getClass();
System.out.println(cls);
}
}
//输出结果:
//class java.lang.String
作用2代码示例:
package ex;
import java.util.Scanner;
public class Test {
public static void main(String args[]) throws InstantiationException, IllegalAccessException, ClassNotFoundException {
Scanner sc = new Scanner(System.in);
System.out.println("请选择创建的图形:1.圆形 2.三角形");
int choice = sc.nextInt();
Shape figure = new Shape();
if(choice == 1) {
figure = (Shape)Class.forName("ex.Circle").newInstance();
//注:newInstance(): 弱类型。低效率。只能调用无参构造
}
else {
figure = (Shape)Class.forName("ex.Triangle").newInstance();
}
figure.show();
sc.close();
}
}
class Shape{
void show() {
}
}
class Circle extends Shape{
void show() {
System.out.println("这是一个圆");
}
}
class Triangle extends Shape{
void show() {
System.out.println("这是一个三角形");
}
}
//输出结果:
/*请选择创建的图形:1.圆形 2.三角形
*1
*这是一个圆
*/
二、Reflection的简单操作示例
示例1:获得想操作类的java.lang.Class对象
eg:
Class cls = Class.forName("java.lang.String");//正常玩法
Class cls = char.class; //正常玩法2
Class cls = Integer.TYPE; //基本类型封装类的玩法
Class cls = "abc".getClass(); //正常玩法3
示例2:获取想操作类的所有方法列表
eg:
package ex;
//import java.util.Scanner;
import java.lang.reflect.*;
public class Test {
public static void main(String args[]) throws InstantiationException, IllegalAccessException, ClassNotFoundException {
Class cls = Class.forName("java.lang.String");
Method[] med = cls.getDeclaredMethods();
for(int i = 0;i<5;i++) { //先打印五个函数,太多了
System.out.println(med[i].toString());
}
}
}
//输出结果:
/*public boolean java.lang.String.equals(java.lang.Object)
*public java.lang.String java.lang.String.toString()
*public int java.lang.String.hashCode()
*public int java.lang.String.compareTo(java.lang.String)
*public int java.lang.String.compareTo(java.lang.Object)
*/
示例3:获取想操作类的构造器信息
package ex;
//import java.util.Scanner;
import java.lang.reflect.*;
public class Test {
public static void main(String args[]) throws ClassNotFoundException{
Class cls = Class.forName("java.lang.String");
Constructor[] cst = cls.getDeclaredConstructors();
for(int i = 0;i<cst.length;i++) {
System.out.println(cst[i]);
}
}
}
//输出结果:
/*public java.lang.String(java.lang.String)
*public java.lang.String(char[],int,int)
*public java.lang.String(byte[],int)
*public java.lang.String(byte[],int,int,int)
*/
示例4:获得想操作类的字段
package ex;
//import java.util.Scanner;
import java.lang.reflect.*;
public class Test {
public static void main(String args[]) throws ClassNotFoundException{
Class cls = Class.forName("java.lang.String");
Field[] fed = cls.getFields();
for(int i = 0;i<fed.length;i++) {
System.out.println(fed[i]);
}
}
}
//输出结果:
/*public static final java.util.Comparator java.lang.String.CASE_INSENSITIVE_ORDER
*/
三、一个简单的例子:找出类的方法
有的时候,程序执行到某处的时候才会知道要调用某个方法,这里我们用反射来实现通过用户输入方法名来调用方法
package ex;
import java.util.Scanner;
import java.lang.reflect.*;
public class Test {
public static void main(String args[]) throws ClassNotFoundException, NoSuchMethodException, SecurityException, IllegalAccessException, IllegalArgumentException, InvocationTargetException{
System.out.println("What is your favourite color?");
Scanner sc = new Scanner(System.in);
String color = sc.nextLine();
Class cls = Class.forName("ex.fruit");
//Class []para = new Class[2];
Method mtd = cls.getDeclaredMethod(color);//parameterTypes
mtd.invoke(null);
sc.close();
}
}
class fruit{
static void red() {
System.out.println("You like red.");
}
static void blue() {
System.out.println("You like blue.");
}
static void black() {
System.out.println("You like black.");
}
static void white() {
System.out.println("You like white.");
}
}
//运行结果
/*What is your favourite color?
*blue
*You like blue.
*/
//这里只是为了用反射而用反射,几个例子都不是很好,打开API会发现这简直是新世界的大门
//如有错误,欢迎指正