一、 反射格式:
修饰符 返回值类型 方法名(数据类型... 变量)'
{
函数体;
}
注意:这里的变量其本质是一个数组。如果你写程序的时候,想用可变参数,最好把可变参数定义在末尾。
二、反射方法
//public Constructor<?>[] getConstructors()
Constructor[] cons = c.getConstructors();
// 所有构造方法
//public Constructor<?>[] getDeclaredConstructors()
Constructor[] cons = c.getDeclaredConstructors();
Class c = Class.forName("cn.itcast_01.Person");
// 创建对象
Constructor con = c.getConstructor();
Object obj = con.newInstance();
Method[] methods = c.getMethods();// 所有公共方法,包括父类的
Method[] methods = c.getDeclaredMethods();// 本类的所有方法
//第一种:无参数无返回值
Method m1 = c.getMethod("show", null);
m1.invoke(obj, null);
System.out.println("---------------");
//第二种:带参数无返回值
Method m2 = c.getMethod("function", String.class);
m2.invoke(obj, "林青霞");
System.out.println("---------------");
//第三种:带多个参数有返回值
Method m3 = c.getMethod("reutrnValue", String.class,int.class);
Object ooo = m3.invoke(obj, "林青霞",26);
System.out.println(ooo);
System.out.println("---------------");
//第四种:私有方法的调用
Method m4 = c.getDeclaredMethod("hello", null);
m4.setAccessible(true);
m4.invoke(obj, null)
三、反射概述和获取字节码文件的方式
- 可变参数:
JDK5新特性举例:
public static void main(String[] args) {
//我也不知道别人要传递几个参数。
// 只有在别人调用的时候,别人才明确。
int a = 10;
int b = 20;
int result = sum(a, b);
System.out.println(result);
int c = 30;
result = sum(a, b, c);
System.out.println(result)
int d = 40;
result = sum(a, b, c, d);
System.out.println(result);
int e = 50;
result = sum(a, b, c, d, e);
System.out.println(result);
//将参数定义为可变参数,
public static int sum(int... x) {
int result = 0;
for (int i : x) {
result += i;
}
return result; }
- 概念
反射:在运行状态下,通过class文件对象(Class的对象),去使用构造方法,成员变量,成员方法 - 获取到class文件对象(字节码文件对象)
a:Object类的getClass()方法。
Class c = 对象.getClass();
b:数据类型的静态的class属性
Class c =类名.class;
c:通过Class类的静态方法forName(String className)
Class c = Class.forName("cn.itcast_01.Person")(包名.类名)
四、通过反射获取构造方法并使用
- 获取字节码文件对像
Class c=Class.forName( "cn.itcasn_01.Person"); - 获取构造器对象
a 所有公共构造方法
b 获取无参构造方法
Constructor con = c.getConstructor( );// 表示我使用的是无参数构造方法
通过构造器对象创建对象
// public T newInstance(Object... initargs);
Object obj = con.newInstance();
c 获取有参构造方法
//public Constructor<T> getConstructor(Class<?>... parameterTypes)
Class[] classes = new Class[2];
classes[0] = String.class;
classes[1] = int.class;
Constructor con = c.getConstructor(classes);
// 改进版
Constructor con = c.getConstructor(new Class[] { String.class, int.class });
//最终版
Constructor con = c.getConstructor(String.class, int.class);
// 创建对象
public T newInstance(Object... initargs)
Object obj = con.newInstance("林青霞", 26);
五、通过反射获取成员变量并使用
- 获取成员变量并使用
// 获取字节码文件对象
Class c = Class.forName("cn.itcast_01.Person");
// 获取成员变量对象
Field[] fields = c.getFields();// 获取所有公共的成员变量
Field[] fields = c.getDeclaredFields();// 获取所有的成员变量
//获取构造器对象
Constructor con = c.getConstructor();
Object obj = con.newInstance();
// 获取单个的成员变量
Field field = c.getField("age");
// obj.field = 20;
//public void set(Object obj,Object value)
field.set(obj, 20);//给obj对象的field字段赋值为20
- 获取私有成员变量并使用
// 获取字节码文件对象
Class c = Class.forName("cn.itcast_01.Person");
// 创建对象
Constructor con = c.getConstructor();
Object obj = con.newInstance();
// 获取年龄并赋值
Field ageField = c.getField("age");
ageField.set(obj, 26);
// 获取姓名并赋值
// NoSuchFieldException
// Field nameField = c.getField("name");
Field nameField = c.getDeclaredField("name");
//public void setAccessible(boolean flag)
//在访问私有成员变量时,暴力访问,不然会出现 IllegalAccessException 错误
nameField.setAccessible(true);//你就不要限制我了。
nameField.set(obj, "林青霞");
六、面试题
在ArrayList<Integer>的集合中添加一个String类型的对象,如何实现呢?
*通过反射实现
* 反射可以越过泛型检查。
public class ArrayListTest {
public static void main(String[] args) throws Exception {
ArrayList<Integer> array = new ArrayList<Integer>();
array.add(10);
// 获取字节码文件对象
Class c = array.getClass();
Method m = c.getMethod("add", Object.class);
m.invoke(array, "hello");
m.invoke(array, "world");
m.invoke(array, "java");
System.out.println(array);
}
}
网友评论