day27-Java反射/设计模式

27.01_类的加载概述和加载时机

  • 当程序要使用某个类时,如果该类还未被加载到内存中,则系统会通过加载连接初始化三步来实现对这个类进行初始化。

  • 加载

    • 就是指将class文件读入内存,并为之创建一个Class对象。任何类被使用时系统都会建立一个Class对象。
  • 连接

    • 1.验证 是否有正确的内部结构,并和其他类协调一致
    • 2.准备 负责为类的静态成员分配内存,并设置默认初始化值
    • 3.解析 将类的二进制数据中的符号引用替换为直接引用
  • 初始化 就是我们以前讲过的初始化步骤

  • B:加载时机

* 创建类的实例
* 访问类的静态变量,或者为静态变量赋值
* 调用类的静态方法
* 使用反射方式来强制创建某个类或接口对应的java.lang.Class对象
* 初始化某个类的子类
* 直接使用java.exe命令来运行某个主类

27.02_类加载器的概述和分类

  • A:类加载器的概述 : 负责将.class文件加载到内存中,并为之生成对应的Class对象。虽然我们不需要关心类加载机制,但是了解这个机制我们就能更好的理解程序的运行。
  • B:类加载器的分类
    • Bootstrap ClassLoader根类加载器
    • Extension ClassLoader扩展类加载器
    • Sysetm ClassLoader 系统类加载器
  • C:类加载器的作用
- Bootstrap ClassLoader 根类加载器
    - 也被称为引导类加载器,负责Java核心类的加载
    - 比如System,String等。在JDK中JRE的lib目录下rt.jar文件中
- Extension ClassLoader 扩展类加载器
    - 负责JRE的扩展目录中jar包的加载。
    - 在JDK中JRE的lib目录下ext目录
- Sysetm ClassLoader 系统类加载器
    - 负责在JVM启动时加载来自java命令的class文件,以及classpath环境变量所指定的jar包和类路径

27.03_反射概述

  • 1.1JAVA反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;
  • 1.2对于任意一个对象,都能够调用它的任意一个方法和属性;
  • 1.3这种动态获取的信息以及动态调用对象的方法的功能称为java语言的反射机制
  • 1.4要想解剖一个类,必须先要获取到该类的字节码文件对象。
  • 1.5而解剖使用的就是Class类中的方法,所以先要获取到每一个字节码文件对应的Class类型的对象。
  • 推荐2篇详细讲解Java反射的优秀文章:
    Java基础与提高干货系列——Java反射机制
    Java反射详解
Class clazz1 = Class.forName("com.bean.Person");
Class<?> clazz2 = Person.class;
Class<?> clazz3 = new Person().getClass();   //加不加<?>都一样,

System.out.println(clazz1 == clazz2);

Class<?> 相当于 Class<? extends Object>
?是个通配符,可以用任何由Object派生的类型代替
反射的三个阶段.png

27.04_反射(Class.forName()读取配置文件举例)

// 反射和配置文件
BufferedReader br = new BufferedReader(new FileReader("config.plist"));
Class<?> clazz = Class.forName(br.readLine());  //从文件中读取了类名(全类名)
br.close();

Juicer j = new Juicer();
j.run( (Apple)clazz.newInstance() ); //使用 Class 创建了对象

--------------------分割线-----------------------------
class Juicer {
    public void run(Apple a) {  a.squeeze();  }
}
class Apple {
    public void squeeze() { System.out.println("炸出一杯苹果汁"); }
}

27.05_通过反射获取带参构造方法并使用

  • 关键类:Constructor构造方法类
    Class类的newInstance()方法是使用该类无参的构造函数创建对象, 如果一个类没有无参的构造函数, 就不能这样创建了,可以调用Class类的getConstructor(String.class,int.class)方法获取一个指定的构造函数然后再调用Constructor类的newInstance("张三",20)方法创建对象
Class<?> clazz = Class.forName("com.bean.Person");
Constructor<?> c = clazz.getConstructor(String.class,int.class); //获取class的构造(有参)方法类
Person p = (Person) c.newInstance("张六",23); //使用有参构造方法类创建对象
System.out.println(p);
System.out.println(clazz.getConstructors());  //获取所有构造方法

27.06_通过反射获取成员变量并使用

  • 关键类: Field成员变量类
    Class.getField(String)方法可以获取类中的指定字段(可见的), 如果是私有的可以用getDeclaedField("name")方法获取,通过set(obj, "李四")方法可以设置指定对象上该字段的值, 如果是私有的需要先调用setAccessible(true)设置访问权限,用获取的指定的字段调用get(obj)可以获取指定对象中该字段的值
// 通过反射,获取 成员变量
Class<?> clazz = Class.forName("com.bean.Person");
Constructor<?> c = clazz.getConstructor(String.class,int.class); //获取class的构造(有参)方法类
Person p = (Person) c.newInstance("张六",23); //使用有参构造方法类创建对象

//Field f = clazz.getField("name");  //获取name成员属性  只能获取public的成员属性

Field f = clazz.getDeclaredField("name"); //暴力反射,获取私有字段(成员属性/变量)
f.setAccessible(true);  //去除私有权限,必须这样只会,才能修改值
f.set(p, "我日,这也可以");  //修改字段的值
System.out.println(p);

27.07_通过反射获取方法并使用

  • 关键类: 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)
Class<?> clazz = Class.forName("com.bean.Person");
Constructor<?> c = clazz.getConstructor(String.class , int.class);
Person p = (Person) c.newInstance("大叔",40);

Method m = clazz.getMethod("eat");  //获取eat方法,没有参数
m.invoke(p); //运行获取的eat方法,没有参数

Method m3 = clazz.getMethod("eat", int.class); //获取eat方法,带参数的
m3.invoke(p, 12); //运行获取的eat方法。带参数。

Method m2 = clazz.getDeclaredMethod("sleep"); //获取私有方法,没有参数
m2.setAccessible(true);  //想要运行私有方法,必须先让方法可见
m2.invoke(p); //运行获取的私有方法,没有参数

27.08_通过反射越过泛型检查)

  • ArrayList<Integer>的一个对象,在这个集合中添加一个字符串数据,如何实现呢?
// 1.不通过反射的办法, 泛型擦除,泛型只是在编译期做语法检查的,运行期泛型会被擦除掉
ArrayList list = null;
ArrayList<Integer> intList = new ArrayList<>();
intList.add(100);
list = intList;  //改变list的内存指向
list.add("XXOO...我是字符串...");   //实际此时已经把字符串 添加到  ArrayList<Integer> 里面了
System.out.println(intList);


// 2.通过 反射 
ArrayList<Integer> intList = new ArrayList<>();
intList.add(100);

Class<?> clazz = Class.forName("java.util.ArrayList");
Method m = clazz.getMethod("add", Object.class);  //获取add方法
m.invoke(intList, "我是字符串,我进入int泛型集合了!");
System.out.println(intList);

27.09_通过反射写一个通用的设置某个对象的某个属性为指定的值

/**
 * 把某个对象的属性,改成自己想要的值
 * @param obj 对象
 * @param k 对象的属性名称,字符串
 * @param v 要改成的值
 */
public static void setPropertyByName(Object obj, String k, Object v) throws Exception {
    Class<?> clazz = obj.getClass();
    Field f = clazz.getDeclaredField(k); //不管私有方法还是public的,都能获取 暴力反射
    f.setAccessible(true);  //去除权限
    f.set(obj, v);
}

27.11_动态代理的概述和实现

  • 动态代理:在程序运行过程中产生的这个对象,而程序运行过程中产生对象其实就是我们刚才反射讲解的内容,所以,动态代理其实就是通过反射来生成一个代理。
  • 在Java中java.lang.reflect包下提供了一个Proxy类和一个InvocationHandler接口,通过使用这个类和接口就可以生成动态代理对象。JDK提供的代理只能针对接口做代理。我们有更强大的代理cglib(JavaEE讲),Proxy类中的方法创建动态代理类对象.
interface Animal {  void eat();  }

class Dog implements Animal {
    public void eat() {
        System.out.println("狗改不了吃屎!");
    }
}

---------------分割线---------------
class MyInvocationHandler implements InvocationHandler { //自定义代理功能类
    private Object target;
    public MyInvocationHandler(Object target) {
        this.target = target;
    }
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        System.out.println("先做一些事情...");
        method.invoke(target, args);  //执行被代理target对象的方法,多个参数本的本质是数组
        System.out.println("后做一些事情...");
        return null;
    }
}
---------------分割线---------------
Dog dog = new Dog();

MyInvocationHandler delegate = new MyInvocationHandler(dog);
ClassLoader l = dog.getClass().getClassLoader();  //固定写法
Class<?>[] inter = dog.getClass().getInterfaces(); //固定写法

Animal animal = (Animal) Proxy.newProxyInstance(l, inter, delegate);
animal.eat();  //等于是让代理类,在方法运行时 多处理了一些事情。

27.12_设计模式(模版(Template)设计模式概述和使用)

模版方法模式就是定义一个算法的骨架,而将具体的算法延迟到子类中来实现

  • a:优点 : 使用模版方法模式,在定义算法骨架的同时,可以很灵活的实现具体的算法,满足用户灵活多变的需求
  • b:缺点 : 如果算法骨架有修改的话,则需要修改抽象类
// 一个抽象类,目的是计算一段代码运行的耗时
// 但是运行什么代码,是不知道的,需要子类去实现具体的代码
abstract class GetTime {
    public final void getTime() {  // final目的是不让子类重写
        long s = System.currentTimeMillis();
        code();
        long e = System.currentTimeMillis();
        System.out.println(e - s);
    }

    public abstract void code() ; // abstract必须让子类重写 
}

27.14_设计模式

  • 目前已学已讲的设计模式:
1,装饰 : 在不必改变原类文件和使用继承的情况下,动态地扩展一个对象的功能。典型就是JavaIO框架。
2,单例 : 一个类有且仅有一个实例,并且自行实例化向整个系统提供。
3,简单工厂 : 专门生产势力的类,把类的实例过程抽取到一个专门的类里。
4,工厂方法 : 创建一个工厂接口和创建多个工厂实现类,这样一旦需要增加新的功能,直接增加新的工厂类就可以了
5,适配器 : 将一个类的接口转换成客户希望的另外一个接口。典型就是GUI里各种事件的处理。
6,模版 : 定义一个操作中的算法的骨架,而将步骤延迟到子类中。
7,动态代理 : 在实现阶段不用关心代理类,而在运行阶段才指定哪一个对象。
  • 总体来说设计模式分为三大类:
  • 创建型模式,共五种:工厂方法模式、抽象工厂模式、单例模式、建造者模式、原型模式。
  • 结构型模式,共七种:适配器模式、装饰器模式、代理模式、外观模式、桥接模式、组合模式、享元模式。
  • 行为型模式,共十一种:策略模式、模板方法模式、观察者模式、迭代子模式、责任链模式、命令模式、备忘录模式、状态模式、访问者模式、中介者模式、解释器模式。
    其实还有两类:并发型模式和线程池模式。用一个图片来整体描述一下:
设计模式1.png
设计模式2.png

END。
我是小侯爷。
在魔都艰苦奋斗,白天是上班族,晚上是知识服务工作者。
如果读完觉得有收获的话,记得关注和点赞哦。
非要打赏的话,我也是不会拒绝的。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 204,732评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 87,496评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,264评论 0 338
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,807评论 1 277
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,806评论 5 368
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,675评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,029评论 3 399
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,683评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 41,704评论 1 299
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,666评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,773评论 1 332
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,413评论 4 321
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,016评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,978评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,204评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,083评论 2 350
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,503评论 2 343

推荐阅读更多精彩内容

  • Spring Cloud为开发人员提供了快速构建分布式系统中一些常见模式的工具(例如配置管理,服务发现,断路器,智...
    卡卡罗2017阅读 134,596评论 18 139
  • Android 自定义View的各种姿势1 Activity的显示之ViewRootImpl详解 Activity...
    passiontim阅读 171,448评论 25 707
  • 积极主动;以终为始;要事第一 思想决定行动,行动决定习惯,习惯决定品德,品德决定命运 承认自己的无知往往是求知的第...
    huangming003阅读 182评论 0 1
  • 年龄二十好几的人,突然想写我这一辈子这样一个话题,真不知道是受到了什么挫折还是生活让你如此不堪,他刚看到她发的动态...
    涵辰阅读 260评论 0 0
  • 孔老师要去生宝宝了,接下来的时间不能再每天和她朝夕相对,我很舍不得,会很想她吧! 他其实是很自我的一个人,这个假期...
    刘piano阅读 117评论 0 0