@w460461339
2016-11-16T07:10:32.000000Z
字数 5088
阅读 829
Java基础
今天学习的是Java基础的最后一课,内容是有关于反射的。呃,虽然不是很明白为什么要用反射这个词,但反射的大意就是用类的class文件强行调用该类的方法,不管它的访问属性。
通过字节码文件对象,去使用成员变量,构造方法,成员方法
package reflect_01;
public class ReflectDemoTest {
/**
* @param args
* @throws ClassNotFoundException
*/
public static void main(String[] args) throws ClassNotFoundException {
// 获取.class文件方法一
//创建对应的实例对象,利用实例对象获取
ReflectDemo rd1=new ReflectDemo(10);
Class c1=rd1.getClass();
//获取.class文件方法二
//直接利用类名来获取
Class c2=ReflectDemo.class;
//获取.class文件方法三
//通过Class类中的forname方法来获取
Class c3=Class.forName("reflect_01.ReflectDemo");
System.out.println((c1==c2) &&(c2==c3));
}
}
自己玩的时候用第二种,因为方便;但是开发的时候用第三种,因为易更改
package reflect_01;
import java.lang.reflect.Constructor;
public class ConstructionDemo {
/**
* @param args
*/
public static void main(String[] args) throws Exception{
Class c=Class.forName("reflect_01.ReflectDemo");
//只能拿所有public訪問屬性的構造方法
Constructor[] con0=c.getConstructors();
for(Constructor cor:con0){
System.out.println(cor);
}
//只能拿一個public訪問屬性的構造方法
Constructor con=c.getConstructor(int.class);
Object obj= con.newInstance(10);
System.out.println(obj);
//能拿private或者default修飾的構造方法,并使用
Constructor con1=c.getDeclaredConstructor();
con1.setAccessible(true);
Object obj2=con1.newInstance();
System.out.println(obj2);
}
}
package reflect_01;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
public class FieldDemo {
/**
* @param args
*/
public static void main(String[] args) throws Exception{
// TODO Auto-generated method stub
Class c=Class.forName("reflect_01.ReflectDemo");
//创建构造方法,并构造实例
Constructor con=c.getConstructor(int.class);
Object obj=con.newInstance(16);
//利用反射得到对应的成员变量,并将上述obj中的对应成员变量赋值
Field f1=c.getField("age");
f1.set(obj, 20);
//输出
System.out.println(obj);
//获取私有成员变量
Field f2=c.getDeclaredField("address");
f2.setAccessible(true);
f2.set(obj, "haven");
//输出
System.out.println(obj);
}
}
package reflect_01;
import java.lang.reflect.Constructor;
import java.lang.reflect.Method;
public class MehtodDemo {
/**
* @param args
*/
public static void main(String[] args) throws Exception{
// TODO Auto-generated method stub
//获得字节码文件对象
Class c=Class.forName("reflect_01.ReflectDemo");
//利用反射创建实例对象
Constructor con=c.getConstructor(int.class);
Object obj= con.newInstance(22);
//利用反射调用包括private在内的所有方法
Method me=c.getDeclaredMethod("require");
me.setAccessible(true);
me.invoke(obj);
}
}
package reflect_02;
import java.lang.reflect.Method;
import java.util.ArrayList;
public class ReflectArrayDemo {
public static void main(String[] args) throws Exception{
//创建ArrayList对象并测试
ArrayList<Integer> array=new ArrayList<Integer>();
array.add(10);
//获得Array的.class文件对象
Class c=array.getClass();
//获得add方法的对象,注意最后的参数类型是Object
Method me=c.getDeclaredMethod("add", Object.class);
//利用该add方法写入Hello
me.invoke(array, "Hello");
//输出
System.out.println(array);
}
}
动态代理
代理:本来应该自己做的事情,却请了别人来做,被请的人就是代理对象。
举例:春季回家买票让人代买
动态代理:在程序运行过程中产生的这个对象
而程序运行过程中产生对象其实就是我们刚才反射讲解的内容,所以,动态代理其实就是通过反射来生成一个代理
在Java中java.lang.reflect包下提供了一个Proxy类和一个InvocationHandler接口,通过使用这个类和接口就可以生成动态代理对象。JDK提供的代理只能针对接口做代理。我们有更强大的代理cglib
Proxy类中的方法创建动态代理类对象
public static Object newProxyInstance(ClassLoader loader,Class[] interfaces,InvocationHandler h)
最终会调用InvocationHandler的方法
InvocationHandler
Object invoke(Object proxy,Method method,Object[] args)
简而言之,就是不对原本类中的方法进行修改的情况下,在该方法的前后增添内容。
另外需要注意,动态代理只能代理接口对象!
接口
package reflect_03;
public interface Tool {
public abstract void print();
}
接口实现
package reflect_03;
public class ToolImpl implements Tool{
@Override
public void print() {
System.out.println("Right");
}
}
动态代理类
package reflect_03;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
public class MyInvocationHandler implements InvocationHandler{
//创建目标对象对应的成员变量
private Object target;
//获取目标对象
public MyInvocationHandler(Object target){
this.target=target;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args)
throws Throwable {
// TODO Auto-generated method stub
//目标对象前面要加的语句(是在该类所有的方法前加上下列语句)
System.out.println("Test One");
//获取代理对象
Object result=method.invoke(target, args);
//目标对象后面要加的语句(是在该类所有的方法后加上下列语句)
System.out.println("Test Two");
//返回代理对象
return result;
}
}
测试类
package reflect_03;
import java.lang.reflect.Proxy;
public class TestDemo {
public static void main(String[] args) {
//获取接口对象
Tool t=new ToolImpl();
//将接口对象传入动态代理类
MyInvocationHandler mih=new MyInvocationHandler(t);
//获取动态代理对象
Tool proxyt=(Tool) Proxy.newProxyInstance(
t.getClass().getClassLoader(),
t.getClass().getInterfaces(), mih);
//运行接口中方法
proxyt.print();
}
}
枚举概述
是指将变量的值一一列出来,变量的值只限于列举出来的值的范围内。举例:一周只有7天,一年只有12个月等。
回想单例设计模式:单例类是一个类只有一个实例
那么多例类就是一个类有多个实例,但不是无限个数的实例,而是有限个数的实例。这才能是枚举类。
注意事项
定义枚举类要用关键字enum
所有枚举类都是Enum的子类
枚举类的第一行上必须是枚举项,最后一个枚举项后的分号是可以省略的,但是如果枚举类有其他的东西,这个分号就不能省略。建议不要省略
枚举类可以有构造器,但必须是private的,它默认的也是private的。枚举项的用法比较特殊:枚举(“”);
枚举类也可以有抽象方法,但是枚举项必须重写该方法
枚举在switch语句中的使用
枚举类
package emumDemo;
public enum EmumTest {
FRONT("F"){
@Override
public void show() {
System.out.println("前");
}
},BEHIND("B"){
@Override
public void show() {
System.out.println("后");
}
},LEFT("L"){
@Override
public void show() {
System.out.println("左");
}
},RIGHT("R"){
@Override
public void show() {
System.out.println("右");
}
};
private String direction;
private EmumTest(String dir){
direction=dir;
}
public abstract void show();
}
枚举类使用
package emumDemo;
public class MyEmum {
public static void main(String[] args) {
EmumTest.BEHIND.show();
}
}