反射
java的动态机制,用于在运行期间检查对象的类型,检查对象的类结构(属性,方法等),还可以动态加载类,动态创建对象,动态访问属性和方法等。
反射是Java 的API.
public void print(Object obj){
//动态反射API,动态检查obj引用的对象类型
Class cls=obj.getClass();
System.out.println(obj);
}
经典面试题目:Eclipse中快捷菜单用了什么技术实现的?
答案:反射技术,反射API
解耦
解除耦合性:降低/解除 两端代码(两个组件)之间的耦合关系
利用反射API,可以实现一个组件与未来的一个组件的松散耦合.甚至可以不在不知道
类名不知道方法名的情况下实现调用关系
反射的功能
1.动态加载类
2.动态创建对象
3.动态调用属性和方法
public class ReflectDemo01 {
public static void main(String[] args) {
print(1);
print("1");
print('1');
}
public static void print(Object obj){
//动态检查obj对象的类型
//getClass方法在Object类上定义,被所有对象继承,全部对象都有的方法
Class cls=obj.getClass();
/*
* Class提供了更加详尽的类型详细信息
* 检查方法:检查属性,检查方法,检查构造器.....
* 动态检查Integer等类型的属性
*/
//Declared:声明的 Field:字段,属性
System.out.println("属性:------------------------");
Field[] fields=cls.getDeclaredFields();
for(Field field:fields){
System.out.println(field);
}
System.out.println("方法:------------------------");
//获取当前类型上声明的所有方法信息
Method[] methods=cls.getDeclaredMethods();
for(Method method:methods){
System.out.println(method);
}
System.out.println(cls);
System.out.println(obj);
}
}
利用反射API动态加载类到方法区:
public static void main(String[] args) throws ClassNotFoundException, InstantiationException, IllegalAccessException {
Scanner in=new Scanner(System.in);
System.out.println("输入类名:");
String className=in.nextLine();
/*
* 动态加载类到方法区,如果类名错误则抛出“类没有找到的运行异常”
*/
Class cls=Class.forName(className);
System.out.println(cls);
//进一步检查类的详细信息....
Field[] file=cls.getDeclaredFields();
for(Field f:file){
System.out.println(f);
}
System.out.println("-----------------------");
Method[] method=cls.getMethods();
for(Method m:method){
System.out.println(m);
}
/**
* 利用反射API动态创建对象
*/
Object obj=cls.newInstance();
System.out.println(obj);
}
}
执行一个类的全部以test为开头的方法,这些方法都是非静态方法,方法没有返回值,没有参数
public static void main(String[] args) throws ClassNotFoundException, InstantiationException, IllegalAccessException, IllegalArgumentException, InvocationTargetException {
//动态加载类
Scanner in=new Scanner(System.in);
System.out.println("输入类名:");
String className=in.nextLine();
Class cls=Class.forName(className);
//动态创建对象
Object obj=cls.newInstance();
//动态检查类中的全部方法信息
Method [] methods=cls.getDeclaredMethods();
for(Method m:methods){
//System.out.println(m);
/*
* method 代表一个方法的相关信息
* method.getName() 返回方法名
*/
String name=m.getName();
//System.out.println(name);
if(name.startsWith("test")){
System.out.println("test开头:"+m);
/*
* Access 访问
* Accessble可访问
* 可以打破封装,访问不可见的方法
*/
m.setAccessible(true);
/*
* method.invoke() 方法用于在对象上调用(invoke)当前
* method对应的方法,必须传递包含方法的对象作为参数。
*/
Object val=m.invoke(obj,1);
System.out.println(val);
}
}
}
利用反射动态调用方法:
public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, SecurityException, InstantiationException, IllegalAccessException, IllegalArgumentException, InvocationTargetException {
Scanner in=new Scanner(System.in);
System.out.println("输入类名:");
String className=in.nextLine();
System.out.println("方法名:");
String methodName=in.nextLine();
System.out.println("参数类型:");
String typeName=in.nextLine();
System.out.println("参数值:");
String paramValue=in.nextLine();
//动态加载类
Class cls=Class.forName(className);
//参数类型转换
Class type=null; //方法的参数类型
Object param=null;//调用方法时的实际参数
if(typeName.equals("int")){
//java中int的类型表示为:int.class
type=int.class;
param=Integer.parseInt(paramValue);
}else if(typeName.equals("double")){
type=double.class;
param=Double.parseDouble(paramValue);
}else if(typeName.equals("String")){
type=String.class;
param=paramValue;
}
//找到一个被执行的方法信息
Method method=cls.getDeclaredMethod(methodName,type);
//method.setAccessible(true);
System.out.println(method);
//动态创建对象
Object obj=cls.newInstance();
/*
* 执行方法
* obj代表包含方法的对象
* param代表执行方法的时候的实际参数
* param的数据类型要与type一致
*/
Object value=method.invoke(obj, param);
System.out.print(value);
}
利用反射获取属性的值:
public static void main(String[] args) throws ClassNotFoundException, InstantiationException, IllegalAccessException, NoSuchFieldException, SecurityException {
Scanner in=new Scanner(System.in);
System.out.println("类名:");
String className=in.nextLine();
System.out.println("属性名:");
String name=in.nextLine();
Class cls=Class.forName(className);
//动态创建对象
Object obj=cls.newInstance();
//在类上查找指定的类信息
Field fld=cls.getDeclaredField(name);
//获取对象obj上的fld属性信息
Object value=fld.get(obj);
//输出属性的值
System.out.println(value);
}
获取字符串的char[] value属性
因为属性value是私有的,所以采用反射API访问:
public static void main(String[] args) throws NoSuchFieldException, SecurityException, IllegalArgumentException, IllegalAccessException {
String s="落霞与孤鹜齐飞,秋水共长天一色。";
//找到属性信息
Class cls=String.class;
Field fld=cls.getDeclaredField("value");
fld.setAccessible(true);
char [] chs=(char[])fld.get(s);
for(char c:chs){
System.out.println(c);
}
// chs[1]='好';
// System.out.println(s);
}
运行结果:
利用反射API动态设置对象的属性:
public static void main(String[] args) throws ClassNotFoundException, NoSuchFieldException, SecurityException, InstantiationException, IllegalAccessException {
Scanner in=new Scanner(System.in);
System.out.println("类名:");
String className=in.nextLine();
System.out.println("属性:");
String name=in.nextLine();
System.out.println("值:");
String value=in.nextLine();
Class cls=Class.forName(className);
Field fld=cls.getDeclaredField(name);
Object obj=cls.newInstance();
//设置obj对象的fld属性值为value
fld.set(obj,value);
System.out.println(obj);
}
demo:
public class TestCase { public void testHello(){ System.out.println("hello world!"); } private void testKitty(){ System.out.println("hello kitty!"); } public void demo(){ System.out.println("demo"); } }
public class Foo { public int age=3; private String name; private int salary; private String gender; public Foo(){ } @Override public String toString() { return "Foo [age=" + age + ", name=" + name + ", salary=" + salary + ", gender=" + gender + "]"; } public Foo(int age, String name, int salary, String gender) { super(); this.age = age; this.name = name; this.salary = salary; this.gender = gender; } @Override public int hashCode() { final int prime = 31; int result = 1; result = prime * result + age; result = prime * result + ((gender == null) ? 0 : gender.hashCode()); result = prime * result + ((name == null) ? 0 : name.hashCode()); result = prime * result + salary; return result; } @Override public boolean equals(Object obj) { if (this == obj) return true; if (obj == null) return false; if (getClass() != obj.getClass()) return false; Foo other = (Foo) obj; if (age != other.age) return false; if (gender == null) { if (other.gender != null) return false; } else if (!gender.equals(other.gender)) return false; if (name == null) { if (other.name != null) return false; } else if (!name.equals(other.name)) return false; if (salary != other.salary) return false; return true; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } public String getName() { return name; } public void setName(String name) { this.name = name; } public int getSalary() { return salary; } public void setSalary(int salary) { this.salary = salary; } public String getGender() { return gender; } public void setGender(String gender) { this.gender = gender; } }
public class Goo { private int test(int a){ return a+1; } public String demo(String s){ return s+""; } public double demo(double d){ return d+1; } }
public class Person { String name; String sex; @Override public String toString() { return "Person [name=" + name + ", sex=" + sex + "]"; } }