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

------<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()

[java] view
plain
copy

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

2.Constructor

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

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

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

[java] view
plain
copy

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

3.Field

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

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

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

[java] view
plain
copy

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

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
plain
copy

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

内省

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
plain
copy

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

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

三、线程池

线程池的作用:

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

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

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

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

比较重要的几个类:

ExecutorService

真正的线程池接口。

ScheduledExecutorService

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

ThreadPoolExecutor

ExecutorService的默认实现。

ScheduledThreadPoolExecutor

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

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

[java] view
plain
copy

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

2.newFixedThreadPool

[java] view
plain
copy

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

3 newCachedThreadPool

[java] view
plain
copy

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

4ScheduledThreadPool

[java] view
plain
copy

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

时间: 2024-11-05 07:45:13

黑马程序员__反射_内省_动态代理的相关文章

黑马程序员__反射

------<a href="http://www.itheima.com" target="blank">Java培训.Android培训.iOS培训..Net培训</a>.期待与您交流! ------- <反射> 1.Class .class文件加载到内存中就是一个Class对象 获取Class对象的方式有3种: Class.forName(); 类名.class 对象.getClass() 例如: [java] view p

黑马程序员__反射总结

------Java培训期待与您交流! ------- 简而言之反射 就是Java类中的各种成分映射成相应的java类. 反射是加载类的class文件并解析里面的数据.利用反射技术可以对一个类进行解剖把各个组成部分映射成一个个对象. 1.Class类 Class: 根据所有类的class文件所抽象出的类型如何得到某个class文件对应的class对象.Class.forName("类名") 用全类名. 1.1Class类的常用方法 Field getField(String name)

黑马程序员——高新技术---反射

黑马程序员——高新技术---反射 ------Java培训.Android培训.iOS培训..Net培训.期待与您交流! ------ 一.概述 JAVA反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法:对于任意一个对象,都能够调用它的任意一个方法和属性:这种动态获取的信息以及动态调用对象的方法的功能称为java语言的反射机制. 反射把Java类中的各种成分映射成相应的Java类,例如一个Java类中用一个Class类的对象表示,一个类中的组成部分:成员变量,方法,构造方

黑马程序员_Java反射机制

一切的操作都将使用Object完成,类,数组的引用都可以使用Object来接收 1,认识Class类 以前要是想知道一个类中的属性,成员变量,方法等等的信息的话,需要通过new这个类的对象才能得到这些信息,但是在Java中,也允许一个实例化对象找到一个类的完整的信息,这个类就是Class类,Class类是继承Object类的. 正常方式:  引入需要的"包.类"名称 >取得实例化对象 反射方式:  实例化对象>得到完整的"包.类"名称 getClass(

黑马程序员—张老师基础加强7-动态代理

代理: 要为已经存在的多个具有相同接口的目标类的各个方法增加一些系统功能. 例如:异常处理,日志和计算方法的运行时间,事物管理等,怎么做 如 在运行前后增加计算时间的方法.show(){ sop(); } 编写一个与目标类具有相同接口的代理类,代理类的每个方法调用目标类的相同方法,并在调用方法时加上系统功能的代码. 动态代理: 要为系统中的各种接口的类增加代理功能,那需要太多代理类. jvm可以在运行期间动态生成出类的字节码,这种动态生成的类往往被调用作代理类, 即动态代理类. jvm生成动态类

黑马程序员------Java反射学习总结(一)

-------------------------Java培训.Android培训,期待与您交流!----------------------------- 一.反射的概念 1) Java反射机制是在运行状态中,对于任意一个类,都能够知道这个类中的所有属性和方法:对于任意一个对象,都能够调用它的任意一个方法和属性:这种动态获取的信息以及动态调用对象的方法的功能称为java语言的反射机制. 2)一句话来讲,反射就是将Java类中的各个成分映射成相应的Java类. 3)即在Java中,描述事物的各种

黑马程序员__多线程

------<a href="http://www.itheima.com" target="blank">Java培训.Android培训.iOS培训..Net培训</a>.期待与您交流! ------- 1.线程是程序执行的一条路径, 一个进程中可以包含多条线程,多线程并发执行可以提高程序的效率, 可以同时完成多项工作. 2.开启新线程的两种方式 1).继承Thread [java] view plaincopy public stati

黑马程序员__集合框架总结

------Java培训期待与您交流! ------- 前言: 本文是对Java集合框架做了一个概括性的解说,目的是对Java集合框架体系有个总体认识,如果你想学习具体的接口和类的使用方法,请参看Java API文档. 一.概述 数据结构对程序设计有着深远的影响,在面向过程的C语言中,数据库结构用struct来描述,而在面向对象的编程中,数据结构是用类来描述的,并且包含有对该数据结构操作的方法. 在Java语言中,Java语言的设计者对常用的数据结构和算法做了一些规范(接口)和实现(具体实现接口

黑马程序员___java反射机制

 ----------- android培训.java培训.java学习型技术博客.期待与您交流! --------- Java的反射机制的实现要借助于4个类:class,Constructor,Field,Method:其中class代表的时类对 象,Constructor-类的构造器对象,Field-类的属性对象,Method-类的方法对象.通过这四个对象我们可以粗略的看到一个类的各个组 成部分.Class:程序运行时,java运行时系统会对所有的对象进行运行时类型的处理.这项信息记录了每个