什么是反射?
在程序运行期间,可以动态加载类,可以动态获取类的信息【属性、方法】,可以动态的调用对象的方法
java.lang.reflect.*;
所有的类型或类可以有java.lang.class类来管理
类通过对象来管理
Class 类 类型,其对象用来管理指定类或类型的相关信息
例如:要管理java.lang.String 类,则需要获取Class类的对象
获取类 类型
获取Class类 类型的对象(Class类的对象)有3种方式
1 动态加载类 Class obj = static forName(包名.类名);
Class<?> obj=Class.forName(className);
2 通过Object对象的getClass()方法
例1 “abc”.getClass();
例2 Person p1 = new Person(); Class c1=p1.getClass();
3 通过数据类型(基础+引用)的静态属性 .class
例 int.class
Class类的方法:
String getName(); 获取类名(含包名)
String getSimpleName(); 获取类名
例子 Class aa; aa.getName();
例子2-动态加载类
String className=args[0];//完整的包名.类名 如java.lang.String
Class<?> obj(obj是一个类)=Class.forName(className);
//Object o(o才是对象)=obj.newInstance();
String show = odj.getName;
println(show);
or
if(o instanceOf Integer){...}
=================
Class c
c是Class类的对象
c也是一种具体的类
Class<?> obj(obj是一个类)=Class.forName(className);
Object o(o才是对象)=obj.newInstance();
//obj.newInstance()调用默认构造器
Office oc=(Office)o;//Office是一个接口,o可以取值word、excel等实现了Office接口的类
//Office和Object有一个共同的儿子word或女儿excel或...
oc.start();
//反射和多态结合,业务更加灵活..
//即动态加载类、动态创建该类的对象..
示例代码:
public class ReflectionTest {
public static void main(String[] args) {
//通过args接收参数
try {
String className = args[0];//必须是完整路径java.*...
Class<?> class1=Class.forName(className);
Object object=class1.newInstance();
Office office=(Office) object;
office.start();
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (InstantiationException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
}
}
}
=================
常用的反射:
类类型
构造器类型
属性
方法
====
获取给定类中的所有构造器:
1加载类,并获取Class类的对象(目标:管理指定的类)
Person.class;
new Person.getClass();
Class.forName("Person");
2调用Class类提供的getConstructors()来获取所有的public权限的构造
器,获取的所有构造器会组成一个数组,由
java.lang.reflect.Constructor来管理
tem.getDeclaredConstuctors()--反射所有
3遍历
3-1 获取构造器的名称 tem.getName()
3-2 获取构造器的参数 tem.getParametertTypes()
3-3 获取形式参数 t.getSimpleName()
获取属性:
1、同上
2、java.lang.reflect.Field//字段反射类
调用Class类提供的getFields()--【只看public】方法,获取所有属性并
组成一个数组,【但getDeclaredFields()-反射所有权限的属性】
3、遍历,显示 【class】getType()属性的类型 getName()属性的名称-+
获取方法:
1、同上
2、java.lang.reflect.Method
getMethods()--含父类、public
getDeclaredMethods()--不含父类、可以private
3、遍历
[String]getName();
[Class[]]getParameterTypes()
getSimpleName
可变参数:
public int add(int ... a);
public int add(int[] b);
==========================
反射的应用:
构造器、方法、属性、数组的反射
1、构造器的反射
先搞一个对象
import java.util.Date;
public class Person {
// 属性
private String name;
private Date birthday;
// 构造器
public Person() {
}
private Person(String name) {
super();
this.name = name;
}
public Person(String name, Date birthday) {
super();
this.name = name;
this.birthday = birthday;
}
// 访问器、设定器
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Date getBirthday() {
return birthday;
}
public void setBirthday(Date birthday) {
this.birthday = birthday;
}
// 功能方法
public int add(int a, int b) {
return 9527 + a + b;
}
public void show() {
System.out.println("show方法被执行");
}
private void show(String s) {
System.out.println("show-s方法被执行");
}
public double area(double d1, double d2) {
return d1 + d2;
}
@Override
public String toString() {
return "姓名:" + name + " 生日" + birthday;
}
}
再看看简单的应用:
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
public class ReflectUSED {
public static void main(String[] args) {
// 1 默认构造器的反射
// 要求被反射的对象有正宗的默认构造器 通过newInstance()来实现
try {
Class class1 = Class.forName("jee.反射.反射的应用.Person");
Object object = class1.newInstance();
System.out.println(object.toString());
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (InstantiationException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
}
// 2 带参数的构造器
// 先【Class】getConstuctor(Class..paramTypes)来获取Constructor对象
// 后【Constructor】newInstance(Object..paramTypes)来创建对象
try {
// 加载类
Class class1 = Class.forName("jee.反射.反射的应用.Person");
// 获取带一个String类型的构造器
Constructor cst1 = class1.getDeclaredConstructor(new Class[] { String.class });
// Constructor cst2 = class1.getConstructor(new Class[]
// {String.class });
// (可选)放开权限,当构造器是private是也可以通过反射使用
cst1.setAccessible(true);// 否则报异常:权限不对
// 创建对象
Object object = cst1.newInstance(new Object[] { "刘德华" });
// 关闭权限(可选)
cst1.setAccessible(false);
// 显示
System.out.println(object);
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (NoSuchMethodException e) {
e.printStackTrace();
} catch (SecurityException e) {
e.printStackTrace();
} catch (InstantiationException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (IllegalArgumentException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
}
// 3 方法的反射,注意权限问题
try {
Class class1 = Class.forName("jee.反射.反射的应用.Person");
Object object = class1.newInstance();
// 无参
Method method = class1.getMethod("show", new Class[] {});
// 有参
Method method2 = class1.getDeclaredMethod("show", new Class[] { String.class });
// 可变参数
// Method method3 = class1.getMethod("show()", new Class[] {int[].class });
method.invoke(object, new Object[] {});
method2.setAccessible(true);
method2.invoke(object, new Object[] { "show的实参" });
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (NoSuchMethodException e) {
e.printStackTrace();
} catch (SecurityException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (IllegalArgumentException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
} catch (InstantiationException e) {
e.printStackTrace();
}
// ==============
}
}
///////////////////////////////练习题
/**
* 2016年5月24日下午12:42:41
*/
package d518Reflect;
import java.lang.reflect.Array;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
interface Office {
void start();
}
class Word implements Office {
@Override
public void start() {
System.out.println("Word start");
}
}
class Excel implements Office {
@Override
public void start() {
System.out.println("Excel start");
}
}
class PowerPoint implements Office {
@Override
public void start() {
System.out.println("PowerPoint start");
}
}
class Person {
private int id;
private String name;
public Person() {
}
public Person(String name) {
super();
this.name = name;
}
public Person(int id, String name) {
super();
this.id = id;
this.name = name;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@Override
public String toString() {
return "编号" + id + " 姓名" + name;
}
public void add(int i, int j) {
System.out.println("i+j=" + (i + j));
}
private void add2(int i, int j) {
System.out.println("i+j=" + (i + j));
}
public int add3(int i, int j) {
return i + j;
}
}
public class ReflectTest {
public static void main(String[] args)
throws ClassNotFoundException, InstantiationException, IllegalAccessException, NoSuchMethodException,
SecurityException, IllegalArgumentException, InvocationTargetException, NoSuchFieldException {
{
System.out.println("练习1:动态获取类类型的名称");
// 模拟参数args[0]为className
// 注意:完整的className包含包名
String className = "java.lang.String";
// 1 动态获取类类型对象及其名称
System.out.println("完整类名:" + Class.forName(className).getName());
System.out.println("简单类名:" + Class.forName(className).getSimpleName());
}
{
System.out.println("
练习2:动态加载类类型,动态绑定多个类对象的方法");
String className = "d518Reflect.Excel";
// 加载 类
Class<?> class1 = Class.forName(className);
// 创建 类对象
Object object = class1.newInstance();
// 对象还原
Office office = (Office) object;// Office 和 Excel间是实现关系,若没有关系,报错
// 动态绑定
office.start();
}
{
System.out.println("
练习3:遍历 构造器");
String className = "d518Reflect.Person";
Class<?> class1 = Class.forName(className);
Constructor<?>[] con = class1.getDeclaredConstructors();
for (Constructor<?> tem : con) {
System.out.print("构造器名称:" + tem.getName() + "(");
Class<?>[] types = tem.getParameterTypes();
for (Class<?> temp : types) {
System.out.print(" " + temp.getSimpleName() + " ");
}
System.out.println(")");
}
}
{
System.out.println("
练习4:遍历 属性");
String className = "d518Reflect.Person";
Class<?> class1 = Class.forName(className);
Field[] fields = class1.getDeclaredFields();
for (Field field : fields) {
System.out.println(field.getType().getSimpleName() + " " + field.getName());
}
}
{
System.out.println("
练习5:遍历 方法");
String className = "d518Reflect.Person";
Class<?> class1 = Class.forName(className);
Method[] ms = class1.getDeclaredMethods();
for (Method md : ms) {
System.out.print(md.getName() + "(");
Class<?>[] types = md.getParameterTypes();
for (Class<?> type : types) {
System.out.print(" " + type.getSimpleName() + " ");
}
System.out.println(")");
}
}
{
System.out.println("
练习6:构造器 反射");
String className = "d518Reflect.Person";
Class<?> class1 = Class.forName(className);
Object obj = class1.newInstance();// 默认构造器 直接使用
Constructor<?> con = class1.getDeclaredConstructor(String.class);// 1
// 带参
Object obj2 = con.newInstance("张三");// 2 对象
System.out.println(obj);
System.out.println(obj2);
}
{
System.out.println("
练习7:属性 反射");
String className = "d518Reflect.Person";
Class<?> class1 = Class.forName(className);
Field field = class1.getDeclaredField("id");
Object obj1 = class1.newInstance();
System.out.println("修改前" + obj1);
field.setAccessible(true);
Object value = 8;
field.set(obj1, value);
System.out.println(obj1);
}
{
System.out.println("
练习8:方法 反射");
String className = "d518Reflect.Person";
Class<?> class1 = Class.forName(className);
Object obj = class1.newInstance();
Method add = class1.getDeclaredMethod("add", int.class, int.class);
add.invoke(obj, 2, 3);// 调用方法时,指明 对象
}
{
System.out.println("
练习9:数组 反射");
// // 一维数组
// Class<?> class1 = int.class;//指定类型
// Object arr = Array.newInstance(class1, 5);//创建数组
// System.out.println("一维数组:");
// for (int i = 0; i < 5; i++) {
// int j = i * 3;
// Array.set(arr, i, j);//设置值
// System.out.print(Array.get(arr, i)+" ");//获取值
// }
// 多维数组
// 准备一个指定大小的二维数组
int size[] = new int[] { 5, 10 };
// 准备数组存放数组的类型
Class type = int.class;
Object array = Array.newInstance(type, size);
// 设置值
Array.set(Array.get(array, 0), 0, 66);
// 访问值
System.out.println(Array.get(Array.get(array, 0), 0));
}
}
}