JAVA高阶(类加载器、反射、动态代理、设计模式)

一、类加载器

类的加载:当程序使用某个类时,若该类未被加载到内存中,则系统会通过 加载、连接、初始化三步来实现类的初始化。

1.类加载的三个步骤

1.1加载(通过类加载器实现):

  • 将class文件读入内存,并为它创建一个Class对象(任何类在使用时,系统都会为它创建一个Class对象)

1.2链接:

  • 验证:内部结构是否正确。
  • 准备:复制为类的静态变量分配内存,并设置默认值。
  • 解析:将类的二进制数据中的符号引用替换为直接引用

1.3初始化:

  • 类的初始化:类加载最后阶段,若该类具有超类,则对其进行初始化,执行静态初始化器和静态初始化成员变量(如前面只初始化了默认值的static变量将会在这个阶段赋值,成员变量也将被初始化)。

2.类加载的时机:

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

3.类加载器分类:

  • 根类加载器:加载java核心类(jdk/jre/rt.jar 中的class文件)
  • 扩展类加载器:加载jre中扩展目录中的jar包中的类(jdk/jre/lib/ext目录中的class文件)
  • 系统类加载器:加载来自java命令的class文件以及classpath环境变量所指定的jar包和类路径下的class文件

二、反射

1.定义:

  • 通过class文件对象,即Class类的对象(不是通过该类的对像),去使用该类的成员变量,构造方法,成员方法

2.Class类:

  • 对应的成员变量,构造方法,成员方法都是类。(反射就是先得到Class类对象,再通过该对象获得它的成员变量/构造方法/成员方法,最后分别通过成员变量/构造方法/成员方法的对象调用对应的方法)
  • 获取Class类的对象的方法
    • 法一

      Person p=new Person();
      Class c=p.getClass();
      
    • 法二

      Class c=Person.class;
      
    • 法三

      Class c=Class.forName(类的地址);
      
    • 方法选择

    • 法二相对简单,但一般开发选择法三,因为法三参数时字符串,比较灵活,可通过配置文件加载,便于维护。

3.通过反射获取构造方法

Class c=Class.forName(Person类地址);//以Person类为例子

//获取所有构造方法,返回的cons 是类对象的集合
	//获取所有公共构造方法
	Constructor[] cons=c.getConstructors();
	//获取所有构造方法(包括私有)
	Constructor[] cons=c.getDeclaredConstructors();
	//遍历构造方法
	for(Constructor con:cons)System.out.println(con)
//获取单个构造方法
	//获取有参构造方法(无参就不填参数即可)
	Constructor con=c.getConstructor(String.class,int.class,String.class);//获取有参构造方法(无参就不填参数即可)
	//获取任意单个构造方法(包括私有)
		Constructor con=c.getDeclaredConstructor(String.class);
		//取消java语言访问检测
		con.setAccessible(true);

//通过构造方法创建类对象
Object obj=con.newInstance(“林青霞”,12,“重庆”);


4.通过反射获取成员变量并赋值

//先利用反射创建对象
Class c=Class.forName(person类地址)
Constructor con =c.getConstructor();
Object obj=con.newInstance();

//获取所有成员变量
	//获取所有共有的成员变量
	Field[] fields=c.getFields();
	//获取所有的成员变量(包括私有)
	Field[] fields=c.getDeclaredFields();
//获取单个成员变量
	//获取共有的单个成员变量(名称记得打引号)
	Field field=c.getField(“变量名称”);
	//获取任意一个成员变量(包括私有)
		Field field=c.getDeclaredField("变量名称“);
		//取消java语言访问检测
		field.setAccessible(true);
//给成员变量赋值
field.set(obj,变量值)//多个变量用逗号隔开

5.通过反射获取成员方法

//先利用反射创建对象
Class c=Class.forName(person类地址)
Constructor con =c.getConstructor();
Object obj=con.newInstance();

//获取所有成员方法
	//获取所有共有的成员方法
	Method[] methods=c.getMethods();
	//获取所有的成员方法(包括私有)
	Method[] methods=c.getDeclaredMethods();
//获取单个成员方法
	//获取共有的单个成员方法(名称记得打引号)
	Method method=c.getMethod(“方法名称”);
	//获取任意一个成员方法(包括私有)
		Method method=c.getDeclaredMethod("方法名称“,参数的class类型);//多个参数用空格隔开,参数的class类型如:String.class
		//取消java语言访问检测
		method.setAccessible(true);
//调用成员方法
method.invoke(obj,参数)//多个参数用逗号隔开

三、动态代理

1.含义:

  • 在运行过程中产生某个对象,可以在运行的时候才切入改变类的方法,而不需要预先定义它。
  • 在java的动态代理机制中,有两个重要的类和接口:Proxy(Class),InvocationHandler(Interface)通过这个类和接口就能生成一个动态代理对象(注意JDK提供的代理只能针对接口做代理,要对类做代理可以用cglib)。
  • 每一个动态代理类都必须要实现InvocationHandler这个接口,并且每个代理类的实例都关联到了一个handler,当我们通过代理对象调用一个方法的时候,这个方法的调用就会被转发为由InvocationHandler这个接口的 invoke 方法来进行调用。

2.创建步骤

  1. 创建一个需要代理的接口

    public interface StudentDao {
    	abstract void  identify(int s);
    	abstract void  dream();
    }
    
  2. 实现代理接口

    package proxy;
    public class StudentImpl implements StudentDao{
    	@Override
    	public void identify(int s) {
    		System.out.println("我是"+s+"年纪的"+"学生");
    	}
    	@Override
    	public void dream() {
    		System.out.println("成绩高");
    	}
    }
    
  3. 实现InvocationHandler 接口

    public class InvocationHandlerImpl implements InvocationHandler{
    	public Object target;
    	InvocationHandlerImpl(Object target){
    		this.target=target;
    	}
    	@Override
    	public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
    		//System.out.println(proxy);
    		System.out.println("动态执行一些方法");
    		Object result=method.invoke(target, args);
    		return result;
    	}
    }
    
  4. 生成接口代理并测试

    public class TestProxy {
    	public static void main(String[] args) {
    		StudentDao sd=new StudentImpl();
    		System.out.println("代理前:"+"\n"+"------------------------------------");
    		sd.dream();
    		sd.identify(5);
    		System.out.println("------------------------------------");
    		
    		//生成接口代理
    		InvocationHandlerImpl h=new InvocationHandlerImpl(sd);
    		StudentDao sdProxy=(StudentDao)Proxy.newProxyInstance(sd.getClass().getClassLoader(), sd.getClass().getInterfaces(), h);
    		
    		System.out.println("代理后:"+"\n"+"------------------------------------");
    		sdProxy.dream();
    		sdProxy.identify(5);
    		System.out.println("------------------------------------");
    	}
    }
    

测试结果

代理前:
------------------------------------
成绩高
我是5年纪的学生
------------------------------------
代理后:
------------------------------------
动态执行一些方法
成绩高
动态执行一些方法
我是5年纪的学生
------------------------------------

四、设计模式

1.设计思想:

1.1单一职责思想设计原则:

  • 每个类实现一种功能,引起改变的原因也只有一个。

1.2开闭原则

  • 对类改动通过增加代码,而不是修改代码(对类的改动通过增加代码进行,而不是修改代码)多借助抽象和多态。

1.3里氏替换原则

  • 任何父类出现的地方都应该可以用其子类替换。(同一个继承体系拥有共同的特征)

1.4依赖注入原则

  • 要依赖于抽象类,不要依赖于具体实现类

1.5接口分离原则

  • 一个接口提供一种功能(如将对某个类的增删改查分离为四个接口,每个接口实现一个功能)

1.6迪米特原则

  • 一个类应尽可能少的了解其他类(降低各个类之间的耦合)

2.设计模式

2.1设计模式的几个要素:

  • 名字 必须有一个简单,有意义的名字
  • 问题 描述在何时使用模式
  • 解决方案 描述设计的组成部分以及如何解决问题
  • 效果 描述模式的效果以及优缺点

2.2设计模式的分类

  • 创建型模式 对象的创建
    • 简单工厂模式

      例子:

      //父类:Animal (eat方法)
      //子类:Cat  Dog   (都覆盖eat方法)
      传统创建:
      Cat cat =new Cat();
      cat.eat();
      Dog dog=new Dog();
      dog.eat();
      //简单工厂模式:创建一个动物工厂(class   : AnimalFactory)
      public static  Animal createAnimal  (String type){
      	if("dog".equals(type)){
      		return new Dog();
      	}else if("cat".equals(type)){
      		return new Cat();
      	}else{
      		return null;
      	}
      }
      //利用工厂创建:
      Animal a=AnimalFactory.createAnimal("dog");//通过字符串方式传递给工厂进行创建,便于代码维护。
      a.eat();
      
    • 工厂方法模式
      例子:

      //在简单工厂模式上改进了,简单工厂模式每次增加一个动物都需要该原有的代码。
      //父类:Animal (eat方法)
      //子类:Cat  Dog   (都覆盖eat方法)
      //父工厂:Factory接口(abstract  createAnimal());
      //子工厂:DogFactory,CatFactory(实现Factory接口,覆盖createAnimal()方法)
      //测试:
      Factory f=new DagFactory();
      Animal a=f.createAnimal();
      a.eat();
      
      
    • 抽象工厂模式

    • 建造者模式

    • 原型模式

    • 单例模式。

  • 结构型模式 对象的组成(结构)
    • 外观模式
    • 适配器模式
    • 代理模式
    • 装饰模式
    • 桥接模式
    • 组合模式
    • 享元模式
  • 行为型模式 对象的行为
    • 模版方法模式
    • 观察者模式
    • 状态模式
    • 职责链模式
    • 命令模式
    • 访问者模式
    • 策略模式
    • 备忘录模式
    • 迭代器模式
    • 解释器模式
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值