码迷,mamicode.com
首页 > 其他好文 > 详细

黑马程序员__反射_内省_动态代理

时间:2015-05-12 09:26:04      阅读:130      评论:0      收藏:0      [点我收藏+]

标签:黑马程序员   java   编程   语言   

------<a href="http://www.itheima.com" target="blank">Java培训、Android培训、iOS培训、.Net培训</a>、期待与您交流! -------

1.Class

       .class文件加载到内存中就是一个Class对象

       获取Class对象的方式有3种:

       Scanner sc = newScanner("xxx.txt");

           Class.forName(sc.nextLine());

           类名.class

           对象.getClass()

  1. import cn.itcast.bean.Person;  
  2.   
  3. public class Demo1_Reflect {  
  4.   
  5.     /** 
  6.      * @param args 
  7.      * @throws ClassNotFoundException  
  8.      */  
  9.     public static void main(String[] args) throws ClassNotFoundException {  
  10.         Class<?> clazz1 = Class.forName("cn.itcast.bean.Person");  
  11.         Class<?> clazz2 = Person.class;  
  12.           
  13.         Person p = new Person();  
  14.         Class<?> clazz3 = p.getClass();  
  15.           
  16.         System.out.println(clazz1 == clazz2);  
  17.         System.out.println(clazz2 == clazz3);  
  18.     }  
  19.   
  20. }  

2.Constructor

       Class类的newInstance()方法是使用该类无参的构造函数创建对象, 如果一个类没有无参的构造函数, 就不能这样创建了

       可以调用Class类的getConstructor(String.class,int.class)方法获取一个指定的构造函数

       然后再调用Constructor类的newInstance("张三",20)方法创建对象

[java] view plaincopy
  1. import java.lang.reflect.Constructor;  
  2.   
  3. import cn.itcast.bean.Person;  
  4.   
  5. public class Demo3_Constructor {  
  6.   
  7.     /* 
  8.       @throws Exception  
  9.      */  
  10.     public static void main(String[] args) throws Exception {  
  11.         Class<?> clazz = Class.forName("cn.itcast.bean.Person");  
  12.         /*Person p = (Person) clazz.newInstance(); 
  13.         System.out.println(p);*/  
  14.         Constructor con = clazz.getConstructor(String.class,int.class);//获取有参的构造函数  
  15.         Person p = (Person) con.newInstance("张三",23);                   //创建对象  
  16.         System.out.println(p);                                          //打印对象  
  17.     }  
  18.   
  19. }  

3.Field

       Class.getField(String)方法可以获取类中的指定字段(可见的), 如果是私有的可以用getDeclaedField("name")方法获取

       通过set(obj, "李四")方法可以设置指定对象上该字段的值, 如果是私有的需要先调用setAccessible(true)设置访问权限

       用获取的指定的字段调用get(obj)可以获取指定对象中该字段的值

[java] view plaincopy
  1. import java.lang.reflect.Constructor;  
  2. import java.lang.reflect.Field;  
  3.   
  4. import cn.itcast.bean.Person;  
  5.   
  6. public class Demo4_Field {  
  7.   
  8.       
  9.       
  10.     public static void main(String[] args) throws Exception {  
  11.         Class<?> clazz = Class.forName("cn.itcast.bean.Person");  
  12.         Constructor con = clazz.getConstructor(String.class,int.class);//获取有参的构造函数  
  13.         Person p = (Person) con.newInstance("张三",23);                   //创建对象  
  14.           
  15.         /*Field f = clazz.getField("name"); 
  16.         System.out.println(f);*/  
  17.         Field f = clazz.getDeclaredField("name");                       //暴力反射  
  18.         f.setAccessible(true);                                          //去除权限  
  19.         f.set(p, "李四");  
  20.         System.out.println(p);  
  21.     }  

4.Method

       Class.getMethod(String, Class...) 和 Class.getDeclaredMethod(String, Class...)方法可以获取类中的指定方法

       调用invoke(Object,Object...)可以调用该方法

       Class.getMethod("eat")invoke(obj) Class.getMethod("eat",int.class) invoke(obj,10)

[java] view plaincopy
  1. import java.lang.reflect.Constructor;  
  2. import java.lang.reflect.Method;  
  3.   
  4. import cn.itcast.bean.Person;  
  5.   
  6. public class Demo5_Method {  
  7.   
  8.     /** 
  9.      *4.Method 
  10.         Class.getMethod(String, Class...) 和 Class.getDeclaredMethod(String, Class...)方法可以获取类中的指定方法 
  11.         调用invoke(Object, Object...)可以调用该方法 
  12.         Class.getMethod("eat") invoke(obj) Class.getMethod("eat",int.class) invoke(obj,10) 
  13.      * @throws Exception  
  14.      */  
  15.     public static void main(String[] args) throws Exception {  
  16.         Class<?> clazz = Class.forName("cn.itcast.bean.Person");  
  17.         Constructor con = clazz.getConstructor(String.class,int.class);//获取有参的构造函数  
  18.         Person p = (Person) con.newInstance("张三",23);                   //创建对象  
  19.           
  20.         Method m = clazz.getMethod("eat");  
  21.         m.invoke(p);  
  22.           
  23.         Method m2 = clazz.getMethod("eat"int.class);  
  24.         m2.invoke(p, 10);  
  25.     }  
  26.   
  27. }  



内省

1什么是内省?

内省(Introspector)是Java语言对bean类属性,事件的一种缺省处理方法。例如类A中有属性name,那我们可以通过getName,setname来得到其值或设置新的值。通过getName/setName来访问name 属性,这就是默认的规则。Java中提供了一套API用某个属来访问getter/setter方法,这些API存放于包java.beans中。

2直接通过属性的描述器java.beans.PropertyDescriptor类,来访问属性的getter/setter 方法;

[java] view plaincopy
  1. <span style="font-size:18px;">importjava.beans.PropertyDescriptor;  
  2. importjava.lang.reflect.Method;  
  3.    
  4. public class Reflect{  
  5.    
  6. public static voidmain(String[] args)throws Exception{  
  7.     Point point=new Point(1,2);  
  8.     String proName="x";  
  9.     getProperty(point,proName);  
  10.     setProperty(point,proName);  
  11. }  
  12. private static voidsetProperty(Point point,String proName)throws Exception{  
  13.      
  14.     PropertyDescriptor proDescriptor=new  
  15. PropertyDescriptor(proName,Point.class);  
  16.     MethodmethodSetX=proDescriptor.getWriteMethod();  
  17.     methodSetX.invoke(point,8);  
  18.     System.out.println(point.getX());  
  19. }  
  20. private static voidgetProperty(Point point,String proName)throws Exception{  
  21.      
  22.     PropertyDescriptor proDescriptor=new  
  23. PropertyDescriptor(proName,Point.class);  
  24.     MethodmethodGetX=proDescriptor.getReadMethod();  
  25.    System.out.println(methodGetX.invoke(point));  
  26.    
  27. }  
  28. }  
  29. public class Point {  
  30.    
  31. private Integer x;  
  32. private Integer y;  
  33. public Point(Integerx,Integer y){  
  34.     super();  
  35.     this.x=x;  
  36.     this.y=y;  
  37. }  
  38. public IntegergetX(){  
  39.     return x;  
  40. }  
  41. public voidsetX(Integer x){  
  42.     this.x=x;  
  43. }  
  44. public IntegergetY(){  
  45.     return y;  
  46. }  
  47. public voidsetY(Integer y){  
  48.     this.y=y;  
  49. }</span>  

二.动态代理

一、什么是动态代理?

动态代理是为对象提供一种代理以控制对这个对象的访问。

二、什么时候使用动态代理?

 当不允许直接访问某些类时或对访问的对象要做特殊处理时。

三、Java动态代理类位于Java.lang.reflect包下,一般主要涉及到以下两个类:

(1). InterfaceInvocationHandler:该接口中仅定义了一个方法Object:invoke(Object obj,Method method, Object[] args)。在实际使用时,第一个参数obj一般是指代理类,method是被代理的方法,如上例中的request(),args为该方法的参数数组。这个抽象方法在代理类中动态实现。

 

(2).Proxy:该类即为动态代理类,作用类似于上例中的ProxySubject,其中主要包含以下内容:

ProtectedProxy(InvocationHandler h):构造函数,估计用于给内部的h赋值。

Static ClassgetProxyClass (ClassLoader loader, Class[] interfaces):获得一个代理类,其中loader是类装载器,interfaces是真实类所拥有的全部接口的数组。

Static ObjectnewProxyInstance(ClassLoader loader,

Class[] interfaces,InvocationHandler h);

 

返回代理类的一个实例,返回后的代理类可以当作被代理类使用(可使用被代理类的在Subject接口中声明过的方法)。

 

动态代理实例:


[java] view plaincopy
  1. import java.lang.reflect.*;  
  2. class  ProxyDemo  
  3. {  
  4.     public static void main(String[] args) throws Exception  
  5.       
  6.     {  
  7.       
  8.           
  9.       
  10.         UserServiceBean ub=new UserServiceBean();  
  11.       
  12.         UserViceProxy up=new UserViceProxy(ub);  
  13.       
  14.         UserService us=(UserService)Proxy.newProxyInstance(ub.getClass().  
  15.       
  16.         getClassLoader();  
  17.       
  18.         ub.getClass().getInterfaces(),up);  
  19.       
  20.         us.say();  
  21.     }  
  22. }  
  23. interface UserService //定义一个接口  
  24. {  
  25.     public void say();  
  26. }  
  27. class UserServiceBean implements UserService //实现UserService接口  
  28. {  
  29.     public void say();  
  30.     {  
  31.       
  32.         System.out.println("Hello!");  
  33.       
  34.     }  
  35. }  
  36. class UserViceProxy implements InvocationHandler  
  37. {  
  38.     private Object obj;  
  39.       
  40.     UserViceProxy(Object obj)  
  41.       
  42.     {  
  43.       
  44.         this.obj=obj;  
  45.       
  46.     }  
  47.     public Object invoke(Object proxy,Method method,Object[] args)throws Throwable  
  48.       
  49.     {  
  50.       
  51.         return method.invoke(obj,args);  
  52.       
  53.     }  
  54. }  

三、线程池

线程池的作用:

线程池作用就是限制系统中执行线程的数量。

 

 

1.减少了创建和销毁线程的次数,每个工作线程都可以被重复利用,可执行多个任务。

2.可以根据系统的承受能力,调整线程池中工作线线程的数目,防止因为消耗过多的内存,而把服务器累趴下(每个线程需要大约1MB内存,线程开的越多,消耗的内存也就越大,最后死机)。

Java里面线程池的顶级接口是Executor,但是严格意义上讲Executor并不是一个线程池,而只是一个执行线程的工具。真正的线程池接口是ExecutorService。

比较重要的几个类:

ExecutorService

真正的线程池接口。

ScheduledExecutorService

能和Timer/TimerTask类似,解决那些需要任务重复执行的问题。

ThreadPoolExecutor

ExecutorService的默认实现。

ScheduledThreadPoolExecutor

继承ThreadPoolExecutor的ScheduledExecutorService接口实现,周期性任务调度的类实现。

要配置一个线程池是比较复杂的,尤其是对于线程池的原理不是很清楚的情况下,很有可能配置的线程池不是较优的,因此在Executors类里面提供了一些静态工厂,生成一些常用的线程池。

[java] view plaincopy
  1. import java.util.concurrent.ExecutorService;  
  2. import java.util.concurrent.Executors;  
  3.    
  4. public class NewSingleThreadExecutor {  
  5.    
  6. public static void main(String[] args) {  
  7.     // TODO Auto-generated method stub  
  8.       
  9.      //创建一个可重用固定线程数的线程池  
  10.    
  11.     ExecutorService pool=Executors.newSingleThreadExecutor();  
  12.      //创建实现了Runnable接口对象  
  13.     Thread t1=new Thread(){  
  14.         public void run(){  
  15.             System.out.println(Thread.currentThread().getName()+"正在执行线程1");  
  16.         }  
  17.     };  
  18.       
  19.     Thread t2=new Thread(){  
  20.         public void run(){  
  21.             System.out.println(Thread.currentThread().getName()+"正在执行线程2");  
  22.         }  
  23.     };  
  24.       
  25.     Thread t3=new Thread(){  
  26.         public void run(){  
  27.             System.out.println(Thread.currentThread().getName()+"正在执行线程3");  
  28.         }  
  29.     };  
  30.       
  31.     Thread t4=new Thread(){  
  32.         public void run(){  
  33.             System.out.println(Thread.currentThread().getName()+"正在执行线程4");  
  34.         }  
  35.     };  
  36.       
  37.     Thread t5=new Thread(){  
  38.         public void run(){  
  39.             System.out.println(Thread.currentThread().getName()+"正在执行线程5");  
  40.         }  
  41.     };  
  42.       
  43.     //将线程放入池中进行执行  
  44.     pool.execute(t1);  
  45.     pool.execute(t2);  
  46.     pool.execute(t3);  
  47.     pool.execute(t4);  
  48.     pool.execute(t5);  
  49.     //关闭线程  
  50.     pool.shutdown();  
  51.     }  
  52. }  
  53.    
  54. 输出结果  
  55. pool-1-thread-1正在执行线程1  
  56. pool-1-thread-1正在执行线程2  
  57. pool-1-thread-1正在执行线程3  
  58. pool-1-thread-1正在执行线程4  
  59. pool-1-thread-1正在执行线程5  

2.newFixedThreadPool


[java] view plaincopy
  1. <span style="font-size:18px;">package threadPool;  
  2.    
  3. import java.util.concurrent.ExecutorService;  
  4. import java.util.concurrent.Executors;  
  5.    
  6. public class NexFixedThreadPool {  
  7.    
  8. public static void main(String[] args) {  
  9.     // TODO Auto-generated method stub  
  10.    
  11.       
  12.      //创建一个可重用固定线程数的线程池  
  13.    
  14.     ExecutorService pool=Executors.newFixedThreadPool(3);  
  15.      //创建实现了Runnable接口对象  
  16.     Thread t1=new Thread(){  
  17.         public void run(){  
  18.             System.out.println(Thread.currentThread().getName()+"正在执行线程1");  
  19.         }  
  20.     };  
  21.       
  22.     Thread t2=new Thread(){  
  23.         public void run(){  
  24.             System.out.println(Thread.currentThread().getName()+"正在执行线程2");  
  25.         }  
  26.     };  
  27.       
  28.     Thread t3=new Thread(){  
  29.         public void run(){  
  30.             System.out.println(Thread.currentThread().getName()+"正在执行线程3");  
  31.         }  
  32.     };  
  33.       
  34.     Thread t4=new Thread(){  
  35.         public void run(){  
  36.             System.out.println(Thread.currentThread().getName()+"正在执行线程4");  
  37.         }  
  38.     };  
  39.       
  40.     Thread t5=new Thread(){  
  41.         public void run(){  
  42.             System.out.println(Thread.currentThread().getName()+"正在执行线程5");  
  43.         }  
  44.     };  
  45.       
  46.     //将线程放入池中进行执行  
  47.     pool.execute(t1);  
  48.     pool.execute(t2);  
  49.     pool.execute(t3);  
  50.     pool.execute(t4);  
  51.     pool.execute(t5);  
  52.     //关闭线程  
  53.     pool.shutdown();  
  54.     }  
  55. }  
  56.    
  57. 输出结果  
  58. pool-1-thread-3正在执行线程3  
  59. pool-1-thread-1正在执行线程1  
  60. pool-1-thread-2正在执行线程2  
  61. pool-1-thread-1正在执行线程5  
  62. pool-1-thread-3正在执行线程4  
  63. </span>  

3 newCachedThreadPool

[java] view plaincopy
  1. import java.util.concurrent.Executors;  
  2.    
  3. public class NewCachedThreadPool {  
  4.    
  5. public static void main(String[] args) {  
  6.     // TODO Auto-generated method stub  
  7.    
  8.      //创建一个可重用固定线程数的线程池  
  9.    
  10.     ExecutorService pool=Executors.newCachedThreadPool();  
  11.      //创建实现了Runnable接口对象  
  12.     Thread t1=new Thread(){  
  13.         public void run(){  
  14.             System.out.println(Thread.currentThread().getName()+"正在执行线程1");  
  15.         }  
  16.     };  
  17.       
  18.     Thread t2=new Thread(){  
  19.         public void run(){  
  20.             System.out.println(Thread.currentThread().getName()+"正在执行线程2");  
  21.         }  
  22.     };        
  23.     Thread t3=new Thread(){  
  24.         public void run(){  
  25.             System.out.println(Thread.currentThread().getName()+"正在执行线程3");  
  26.         }  
  27.     };        
  28.     Thread t4=new Thread(){  
  29.         public void run(){  
  30.             System.out.println(Thread.currentThread().getName()+"正在执行线程4");  
  31.         }  
  32.     };        
  33.     Thread t5=new Thread(){  
  34.         public void run(){  
  35.             System.out.println(Thread.currentThread().getName()+"正在执行线程5");  
  36.         }  
  37.     };        
  38.     //将线程放入池中进行执行  
  39.     pool.execute(t1);  
  40.     pool.execute(t2);  
  41.     pool.execute(t3);  
  42.     pool.execute(t4);  
  43.     pool.execute(t5);  
  44.     //关闭线程  
  45.     pool.shutdown();  
  46.     }  
  47. }  
  48.    
  49. 输出结果:  
  50. pool-1-thread-1正在执行线程1  
  51. pool-1-thread-4正在执行线程4  
  52. pool-1-thread-5正在执行线程5  
  53. pool-1-thread-3正在执行线程3  
  54.       pool-1-thread-2正在执行线程2  

4ScheduledThreadPool

[java] view plaincopy
  1. pool-1-thread-4boombing  
  2. pool-1-thread-4boombing package threadPool;  
  3.    
  4. import java.util.concurrent.TimeUnit;  
  5. import java.util.concurrent.ScheduledThreadPoolExecutor;  
  6. public class ScheduledThreadPoolExecutorTest {  
  7.    
  8. public static void main(String[] args) {  
  9.     // TODO Auto-generated method stub  
  10.    
  11.     ScheduledThreadPoolExecutor stpe=new ScheduledThreadPoolExecutor(5);  
  12.     stpe.scheduleAtFixedRate(new Runnable(){  
  13.         public void run(){  
  14.             System.out.println(Thread.currentThread().getName()+"boombing");  
  15.         }  
  16.     },1000,1000,  TimeUnit.MILLISECONDS);//1s后执行1个线程,然后以1+1=2s执行1个线程,然后1+2*1=3s执行1个线程  
  17.       
  18.     stpe.scheduleAtFixedRate(new Runnable(){  
  19.         public void run(){  
  20.             System.out.println(System.nanoTime());// 返回最准确的可用系统计时器的当前值  
  21.         }  
  22.     },1000,2000, TimeUnit.MILLISECONDS);  
  23.     }  
  24. }  
  25.    
  26.    
  27. 输出结果  
  28. pool-1-thread-1boombing  
  29. 35676046677778  
  30. pool-1-thread-2boombing  
  31. pool-1-thread-1boombing  
  32. 35678045981107  
  33. pool-1-thread-1boombing  
  34. pool-1-thread-1boombing  
  35. 35680046431459  
  36.   
  37. 35682046069371  



四、类加载器

1、什么是类加载器?

 加载类的工具。

2、为什么要创建类加载器?

既然Java虚拟金已经有了类加载器,我们还要自己创建其他的呢?

默认的类加载器只知道如何从本地系统加载类。当你的程序完全在本机编译的话,默认的类加载器一般都工作的很好。但是Java很容易的从网络上而不只是本地加载类。举个例子,浏览器可以通过自定义的类加载器加载类。还有很多加载类的方式。除了简单的从本地或者网络外,还可以通过自定义Java中的地方之一:

执行非信任代码前自动验证数字签名

根据用户提供的密码解密代码

根据用户的需要动态的创建类

3、java类加载器

Java虚拟机中可以安装多个类加载器,系统默认三个主要类加载器,每个类负责加载特定位置的类:BootStrap,ExtClassLoader,AppClassLoader

类加载--------------------------------------------管辖范围

BootStrap--------------------------------JRE/lip/rt.jar

ExtClassLoader--------------------------JRE/lib/ext/*jar

AppClassCoader---------------------------ClassPath指定的所有jar目录下

MyClassLoader ItcassLoader--------------------------程序指定的特殊目录

的原因。

4、怎么定义一个类加载器?

1.自定义的类加载器继承ClassLoader

2.覆盖findClass方法

3.调用defineClass方法把得到的class文件转换成字节码。


黑马程序员__反射_内省_动态代理

标签:黑马程序员   java   编程   语言   

原文地址:http://blog.csdn.net/haojude/article/details/45653393

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!