java基础第二十一天 JDK新特性 反射

1、jdk新特性

java新特性,一般是指java1.5之后的新特性,是因为1.4.2这个版本非常重要。

1.1. 自动装箱拆箱

1、自动装箱拆箱
2、泛型
3、可变参数
4、增强for循环
5、枚举
6、静态导入

1.2. 可变参数

可变参数,类型都是相同的。

public static int add(int ...a){
    int sum = 0;
    //从可变参数里面获取各个参数
    for (int i : a) {
        sum = sum + i;
    }
    return sum;
}

1.3. 增强for循环

强for循环,也叫foreach循环

主要用于遍历容器

    int[] array = {1,2,3,4,5,6};
    //增强for循环
    for (int i : array) {
        System.out.println(i);
    }

1.4. 静态导入(了解)

能够导入静态的方法,直接使用

import static java.lang.Math.sqrt;

1.5. 枚举(了解)

一般用来处理静态变量
//定义枚举
enum Color{
RED, ORANGE, YELLOW, GREEN, BLUE
}

    //使用枚举类型
    Color color = Color.RED;
    switch (color) {
    case RED:
        System.out.println("红色");
        break;
    case ORANGE:
        System.out.println("橙色");
        break;
    case YELLOW:
        System.out.println("黄色");
        break;
    case GREEN:
        System.out.println("绿色");
        break;
    case BLUE:
        System.out.println("蓝色");
        break;
    default:
        break;
    }       

1.6. 泛型

主要用途:

解决元素存储的安全性问题
解决获取数据元素时,需要类型强转的问题

1、在容器中使用泛型

List<String> list = new ArrayList<String>();

2、泛型类

class Person<T>{

    T person;

    public T getPerson() {
        return person;
    }

    public void setPerson(T person) {
        this.person = person;
    }
}

3、泛型方法

泛型方法的格式:

[访问权限]  <泛型>  返回类型  方法名([泛型标识 参数名称])  抛出的异常

代码示例:

public static <T> T getDAO(T t){

    //这里可以对传入的实例做统一处理,例如设置数据库连接...

    return t;
}

4、泛型通配符与限制

    //?表示任意类型
    List<?> list = new ArrayList<String>();


    //extends表示只能是Person05或者他的子类(子类的子类...无穷小)
    List<? extends Person05> p1 = new ArrayList<Person05>();
    //super表示只能是Person05或者他的父类(父类的父类...无穷大,一直到Object)
    List<? super Person05> p2 = new ArrayList<Person05>();

代码示例:

/**
 * 定义的方法里面,容量里需要传入的类型是Aminal及其子类
 * 
 * 
 * @param list
 */
public static void showInfo(List<? extends Animal> list){
    for (Animal animal : list) {
        System.out.println(animal);
    }
}

2、设计模式

2.1. 简单工厂模式

/**
 * 简单工程模式:
 * 
 * 让对象的调用和对象的创建分离开,当对象调用者需要对象时,直接想工厂请求即可。
 * 避免了对象的调用着与对象的实现类或者子类以硬编码的方式耦合在一起。当以后产品需要改变时,我们仅仅需要修改工厂即可。
 * 
 * 前提:有继承或者是实现
 * 
 * 
 * 
 * @author Administrator
 *
 */
public class SimpleFactory {

    public static void main(String[] args) throws Exception {

//      //造一辆宝马
//      Car bmw = new BMW();
//      //造一辆奔驰
//      Car benz = new BenZ();
//      //早一辆兰博基尼
//      Car lamborghini = new Lamborghini();


        Car bmw = Driver.driveCar("bmw");
        bmw.run();

        Car benz = Driver.driveCar("benz");
        benz.run();

        Car lamborghini = Driver.driveCar("lamborghini");
        lamborghini.run();

        Car xiali = Driver.driveCar("xiali");
        xiali.run();

    }
}

2.2. 单例模式

2.2.1.饿汉模式

/**
 * 单例模式:
 *      就是内存中只有一个实例,这样设计的好处是:
 *          1、当类创建比较频繁的时候,对于一些较大的对象,对于内存来说开始很大
 *          2、省去new操作符,降低了jvm的使用频率,减轻gc压力
 * 
 *      使用场景:
 *          比如说一些查询特别多,变更少的数据,我们建议放在缓存当中而且只能有一份儿
 *          例如:企业用户信息
 *  
 *  
 *      编写特点:
 *          对象是static
 *          构造方法是私有的
 *  
 * 模式一:饿汉模式
 *      系统加载时就产生实例,如果没有使用也会占用内存
 * 
 * 模式二:懒汉模式
 *      第一次使用时,才会产生实例,因为是同步的,性能会比较差
 * 
 * 
 * @author Administrator
 *
 */
public class Singleton01 {

    //类加载的时候就会初始化instance,从这以后,static的instance会一直在内存中存在,永远不会被回收,除非jvm退出
    private static Singleton01 instance = new Singleton01();

    //私有的构造方法,避免直接使用new Singleton01
    private Singleton01(){

    }

    /**
     * 
     * 因为是单例,所以我们要使用static方法来获取实例,因此
     * 
     * 
     * @return
     */
    public static Singleton01 getInstance(){
        return instance;
    }
} 

2.2.3.懒汉模式

/**
 * 懒汉模式:
 * 
 *  需要使用synchronized修饰获取实例的方法
 * 
 *  第一次使用的时候才实例话,因此会减少内存的使用
 *  但是是同步的,性能会差差一点
 * 
 * @author Administrator
 *
 */
public class Singleton02 {

    //因为是懒汉模式,初始时不需要实例化
    private static Singleton02 instance= null;

    private Singleton02(){

    }

    public static synchronized Singleton02 getInstance(){
        if(instance == null){
            instance = new Singleton02();
        }
        return instance;
    }
}

3、反射

3.1. 反射是什么:就是通过反射api获取类的所有成员方法,变量,构造方法的机制

实例化类对象的4种方式

    //1、已知具体的类,通过类的class属性获取
    Class s1 = Student.class;

    //2、已知某个类的实例,调用该实例的getClass()方法获取Class对象
    Student student =new Student();
    Class s2 = student.getClass();

    //3、已知某个类的类名,通过类的全限定名(带包路径的类名)来实例化
    try {
        Class s3 = Class.forName("day21.reflect.Student");
    } catch (ClassNotFoundException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }

    //4、通过类加载器
    ClassLoader cl = Thread.currentThread().getContextClassLoader();
    try {
        Class s4 = cl.loadClass("day21.reflect.Student");
    } catch (ClassNotFoundException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }

3.2. 类加载器:

  • 系统类加载器AppClassLoader CLASSPATH环境变量, 由-classpath或-cp选项定义
  • 扩展类加载器ExtClassLoader JRE/lib/ext或者java.ext.dirs指向的目录
  • 引导类加载器BootStrapClassLoader 负责加载rt.jar中的JDK类文件,无法直接获取,返回为null

3.3. class类常用的反射方法

  • 通过能得到类的所有属性:

    • Field、Method、Constructor、Superclass、Interface、Annotation
  • 实现的全部接口
  • 所继承的父类
  • 全部的构造器
  • 全部的方法
  • 全部的Field

4、动态代理

4.1. 动态代理概述:

通过动态代理,我们可以实现在某个类的方法前后,执行一些我们自己的方法,比如执行方法前,验证用户是否用权限,执行方法之后,记录日志等

4.2. 通过java实现动态代理

在Java中java.lang.reflect包下提供了一个Proxy类和一个InvocationHandler接口,通过使用这个类和接口就可以生成动态代理对象

1.定义接口

public interface HelloService {

    public void sayHello();
}

2.定义实现类

public class HelloServiceImpl implements HelloService{

    @Override
    public void sayHello() {
        System.out.println("hello proxy...");
    }

}

3.定义代理类

public class ProxyHandler implements InvocationHandler{

    Object proxy;

    public ProxyHandler(Object proxy) {
        this.proxy=proxy;
    }

    @Override
    public Object invoke(Object proxy, Method method, Object[] args)
            throws Throwable {
        System.out.println("这是代理方法之前....");
        Object object = method.invoke(this.proxy, args);
        System.out.println("这是代理方法之后....");
        return object;
    }

}

4.测试

public class Test {

    public static void main(String[] args) {
        HelloService helloService = new HelloServiceImpl();
        //正常调用
        //helloService.sayHello();
        //动态代理
        HelloService proxy = (HelloService)Proxy.newProxyInstance(helloService.getClass().getClassLoader(), new Class[]{HelloService.class}, new ProxyHandler(helloService));
        proxy.sayHello();
    }

}

jdk动态代理使用的局限性:

通过反射类Proxy和InvocationHandler回调接口实现的jdk动态代理,要求委托类必须实现一个接口,但事实上并不是所有类都有接口,对于没有实现接口的类,便无法使用该方式实现动态代理。

4.3. 通过cglib实现动态代理

注意:cglib为第三方工具类,需要将jar包导入工程,并添加到classpath里。
1.编写类

public class HelloService {

    public void sayHello(){
        System.out.println("hello proxy...");
    }
}

2.编写代理类

public class ProxyHandler implements MethodInterceptor{

    private Object target; 

    public Object getInstance(Object obj){
        this.target = obj;
        Enhancer enhancer = new Enhancer(); 
        enhancer.setSuperclass(this.target.getClass()); 
        // 回调方法 
        enhancer.setCallback(this); 
        // 创建代理对象 
        return enhancer.create(); 

    }

    @Override
    public Object intercept(Object proxyObject, Method method, Object[] args,
            MethodProxy methodProxy) throws Throwable {

        System.out.println("代理方法前...");
        Object object = methodProxy.invokeSuper(proxyObject, args);
        System.out.println("代理方法后...");
        return object;
    }

}

3.测试

public class Test {

    public static void main(String[] args) {
        ProxyHandler handler = new ProxyHandler();
        HelloService helloService = (HelloService)handler.getInstance(new HelloService());
        helloService.sayHello();
    }
}

动态代理与AOP(Aspect Orient Programming)面向切面编程

aop思想就是建立在动态代理之上,spring aop就是使用动态代理实现的(支持jdk原生代理和cglib代理)

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值