@w460461339
2016-11-15T23:10:32.000000Z
字数 5088
阅读 1109
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 stubClass 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方法的对象,注意最后的参数类型是ObjectMethod me=c.getDeclaredMethod("add", Object.class);//利用该add方法写入Hellome.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{@Overridepublic 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;}@Overridepublic 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"){@Overridepublic void show() {System.out.println("前");}},BEHIND("B"){@Overridepublic void show() {System.out.println("后");}},LEFT("L"){@Overridepublic void show() {System.out.println("左");}},RIGHT("R"){@Overridepublic 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();}}