反射的核心就是Class对象,每一个类被jvm加载都会有一个对应的class对象,这个class对象包含了这个类的结构信息,反射就是会通过反射api反复操作这个class对象(属性,方法,注解,构造器,泛型),但是反射会降低程序的运行效率,比普通方法要慢30倍,通过setAccessble(true) 跳过安全检查(可以读取private 的属性),提高4倍的程序运行效率
反射将普遍运用到各个类型的框架。
效率:
1,运行效率:使用反射 减低程序的运行效率。
2,开发效率:由于反射运用到各个java框架中,大大加快了开发的效率。
下面就是一些简单的例子来具体阐述反射的一些特点:
package com.mk;
public class Test{
public static void main(String [] args){
Foo foo = new Foo();//foo 表示foo的实例对象
//任何一个类都是class的实例对象,有3钟表达方式
//1,任何一个类都有一个隐含的成员变量Class
Class c1 = Foo.class;
//2,通过getClass方法获得
Class c2 = foo.getClass();
//不管是c1还是c2都代表Foo类的类类型,一个类只能是Class的实例对象
System.out.println(c1==c2);//true
//3,第三种表达方式
Class c3 = null;
try {
c3 = Class.forName("com.mk.Foo");//类的全称
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
System.out.println(c2==c3);//true
//可以通过类的类类型创建该类的对象实例
try {
Foo f1 = (Foo) c1.newInstance();//需要无参数的构造方法
f1.print();
} catch (InstantiationException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
}
}
}
class Foo{
void print(){
System.out.println("print parent");
}
}
动态加载类
new 创建对象 是静态的加载类,在编译的时刻就需要加载 所有可能使用到的类
通过动态的加载类可以解决这个问题
运行时刻加载 就是想用哪个就加载哪个,不用就不加载。
通过反射api 操作类的方法
method.invoke(对象,参数列表)
package com.mk;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
public class Test1 {
public static void main(String[]args) throws
NoSuchMethodException,
InvocationTargetException,
IllegalAccessException {
A a1 = new A();
Class c = a1.getClass();//得到类类型
Method m = c.getMethod("print",int.class,int.class);
//方法的反射操作
//a1.print(10,20);方法的反射操作是用m对象进行方法的调用,和a1.print()的调用效果相同
//方法如果没有返回值返回null,如果有返回值就返回具体的值
//Object obj = m.invoke(a1,new Object[]{10,20});
//或者有几个参数传几个参数
Object ob = m.invoke(a1,10,20);
}
}
class A{
public void print(int a,int b){
System.out.println(a+b);
}
}
通过class,method来认识泛型的本质
package com.mk;
java.lang.reflect.Method;
java.util.ArrayList;
class test2 {
public static void main(String[] arg){
ArrayList list = new ArrayList();
ArrayList<String> ls = new ArrayList<String>();
ls.add("hello");
//ls.add(20);//泛型检查错误,20是加不进去的
Class c1 = list.getClass();
Class c2 = ls.getClass();
System.out.println(c1==c2);//反射的操作都是编译之后的操作
/**
* c1==c2 结果返回true说明编译之后的集合的泛型是去泛型化的,java中
* 集合的泛型,是防止错误输入的,只有在编译阶段是有效的,在其他的阶段都是
* 无效的
* 可以通过方法的反射来操作 绕过编译
*/
try {
Method m = c2.getMethod("add",Object.class);
m.invoke(ls,100);
System.out.println(ls.size());
System.out.println(ls);//[hello, 100] 结果int 是可以加进去的
} catch (Exception e) {
e.printStackTrace();
}
}
}
如何通过反射api 操作属性,构造器
public class User {
private int id;
private String name;
//javabean 无参构造器,用于java的反射机制的初始化
public User() {
}
public User(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;
}
}
Class clazz
= Class.forName("com.test.reflection.Bean.User");
//获取名字
System.out.println(clazz.getName());//包名+类名
System.out.println(clazz.getSimpleName());
//获取属性方法(重载,根据参数找方法)
Field [] fs = clazz.getDeclaredFields();
System.out.println(fs.length);//获取所有的fields,不论public还是private
Field [] field = clazz.getFields();//获取公共属性
for(Field fields:fs){
System.out.println("属性:"+fields);
}
//获取方法信息
Method [] method
= clazz.getDeclaredMethods();//获取所有的方法
Method m1 =
clazz.getDeclaredMethod("getName",null);
for(Method m:method){
System.out.println("方法:"+m);
}
//获取构造器
Constructor c1 = clazz.getConstructor(null);
System.out.println("无参构造器:"+c1);
Constructor c2 = clazz.getConstructor(int.class,String.class);
System.out.println("有参构造器:"+c2);
Constructor [] constructors
= clazz.getDeclaredConstructors();
for(Constructor c:constructors){
System.out.println("构造器:"+c);
}
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
//动态操作构造器
try {
//通过反射api调用构造方法
User user = (User) clazz.newInstance();//其实是调用了user的无参构造方法
System.out.println(user);
//调用有参构造器
Constructor constructor
= clazz.getDeclaredConstructor(int.class,String.class);
User u
= (User) constructor.newInstance(12,"michael");
System.out.println(u.getName());
//通过反射api调用普通的方法
User u1
= (User)clazz.newInstance();
Method method
= clazz.getDeclaredMethod("setName", String.class);
method.invoke(u1, "mike");//setName("mike");
System.out.println(u1.getName());
//通过反射操作属性
User u2 = (User) clazz.newInstance();
Field f
= clazz.getDeclaredField("name");//属性必须是public的
f.setAccessible(true);//不需要安全检查,直接访问
f.set(u2, "mike2");
System.out.println(u2.getName());//通过反射直接读动态值
System.out.println(f.get(u2));
} catch (Exception e) {
e.printStackTrace();
}
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。