反射
只需知道被使用来扩展功能的类的类名
没看懂没关系,现在你只需要知道除了使用new关键字来创建对象外,下面的方法也可以实现对象的创建:(也就是我们要讲的java反射)
//1、获取Class对象
String className = "com.bean.Person";
Class<?> c = Class.forName(className);
//2、使用Class对象创建该类对 象:
Object obj = c.newInstance();
我们关键字new类创建对象其实内部在进行:
1、查找并加载Person.class文件进内存,并将该文件封装成Class字节码文件;
2、根据Class字节码文件进行类的创建;
3、调用构造函数来初始化对象。
而这些步骤便是使用下面两个步骤来完成的:
首先使用Class类的forName()来获取Class字节码文件,
然后使用Class字节码文件实例化该类,即调用Instance()方法,
而调用该方法后会自动调用构造函数进行初始化,完成对象的创建。
总结来说就是Person p = new Person();等价于Class.forName("bean.Person").newInstance();
一些细节问题:
1、forName()方法中传入的是类的名字:Person,但是我们需要在类名前写上包名,com.bean.Person。因为不同包中可能有相同的类名,我们需要指明包才能找到类。
2、 如果指定的类中没有空参数函数或者该类需要指定的构造函数进行初始化时,即我们需要使用到带有参数的构造函数时,就不能再使用Class对象的newInstance()来创建对象了:我们需要通过构造器来创建对象:
1 Class c = Class.getName("com.bean.Person");
2 //1、获取这个带有参数的构造器
3 Constructor<?> con = c.getConstructor(String.class,int.class);
4 //2、使用构造器来创建:
5 Object obj = con.newInsatnce("LiSi",20);
这样等价于Person p = new Person(“LiSi”,20);
Java"反射包"
通过Class对象来获取类的成员,类中的方法等等.
Person类中的字段:name和age
1.获取:用Class对象中的getField()方法getDeclaredField()
区别:getField()方法返回的是公有的字段和分类中的字段.
getDeclaredField()方法返回的是私有化的字段.
2.使用:先使用forName() 创建一个对象
如果使用的字段无访问权限.公有则可以直接使用,若是私有,则需要使用setAccessible(true)来取消权限设置,才能进行访问.
package reflect;
import java.lang.reflect.Field;
public class demo1 {
public static void main(String[] args) throws Exception {
String className="reflect.Person";
Class <?> c=Class.forName(className);
//用Class对象创建对象Object object=c.newInstance();
//System.out.println(object);
/*Constructor<?> con=c.getConstructor(String.class,int.class,String.class);
Object object=con.newInstance("lisi",20,"男");
System.out.println(object);
*/
Field nameField=c.getDeclaredField("name");
Field ageField=c.getDeclaredField("age");
Field sexField=c.getField("sex");
nameField.setAccessible(true);
ageField.setAccessible(true);
Object obj=c.newInstance();
nameField.set(obj, "Lisa");
ageField.set(obj, 20);
sexField.set(obj, "男");
System.out.println("name:"+nameField);
System.out.println("age:"+ageField);
System.out.println("sex:"+sexField);
System.out.println("字段的设置:name:"+nameField.get(obj)+",age:"+ageField.get(obj)+",sex:"+sexField.get(obj));
}
}
获取类中的4个方法, 我们首先要明确该方法的访问权限和是否有参数。
1、获取
我们使用getMethods()和getDeclaredMethods()来返回的是Method[]:前者获取公有及父类中的方法,后者获取私有方法。
而获取一个方法则使用getMethod(String name,Class<?>... parameterTypes)和 getDeclaredMethod(String name,Class<?>... parameterTypes)来获取。
2、调用
使用Method类中的invoke(object obj,object args...)方法来调用有参数的方法的底层方法。
听课
反射的用途:运行时可以动态的探测类 成员变量,成员方法 调用 构造方法,方法,给成员变量设值
Java执行的过程
step1:将字节码加入内存
step2:进行检查
step3:为每个字节码实例化一个对象(Class类)
step4:初始化静态变量,静态代码块----同级别的按顺序执行
step5:入口main方法
静态
main方法执行之前
2017.11.19-09.56.33 12.45
String str="abc";
Class clazz=Class.forName();
Class clazz2=String.class; //所有的类都有class属性
Class clazz3=int.class; //基本类型也有class
Class clazz4=Integer.class;
Class clazz5=Integer.TYPE; //基本类型对于的包装类有一个TYPE成员等价于基本类型.Class
Class clazz6=str.getClass();//任何一个对象都有getClass()方法
Constructor
可变长形参
emails(23,new String[]("wwww","ssss"));
public static void emails(int age ,String ... email)
{
for (String e:email)
{
syso(e)
}
}
Constructor con=clazz.getDeclaredConstryctor(new Class[]{String.class,int.class});
Stu stu=(Stu)con.newInstance("lisi",20);
stu.display();
成员变量.set(obj,"");
Object value =name.get(s1);
11.19 下午
反射代理:
静态代理:
Email接口 send()
静态代理:
public class ProxyEmail {
Email email;
public ProxyEmail(Email email)
{
this.email=email;
}
public void send()
{
email.send();
System.out.println("--------------------");
System.out.println("前日志");
System.out.println("小小的发个邮件");
System.out.println("后日志");
}
}
动态代理:
需要一个实现InvocationHandler的类
public class MyInvocation implements InvocationHandler {
private Object org;//原始对象
public MyInvocation(Object org) {
this.org=org;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
Object result=null;
System.out.println("^_^......");
method.invoke(org, args);//调用原始对象的功能
System.out.println(">_<......");
return result;
}
}
代理工厂类
public class ProxyFactory {
public static Object getProxy(Object org)
{
MyInvocation myInvocation=new MyInvocation(org);
//动态生成代理对象
return Proxy.newProxyInstance(org.getClass().getClassLoader(), org.getClass().getInterfaces(), myInvocation);
}
}
main()
Email ep=(Email) ProxyFactory.getProxy(email);
ep.send();