动态代理
定义
代理:本来应该自己做的事情,请了别人来做,被请的人就是代理对象
动态代理:在程序运行过程中产生的这个对象,而程序运行过程中产生对象其实
就是我们刚才反射讲解的内容,所以,动态代理其实就是通过反射来生成一个代理对象。
java中动态代理的使用
在Java中java.lang.reflect包下提供了一个Proxy类和一个 接口,通过使用这个类和接口就可以生成动态代理对象
public static Object newProxyInstance(ClassLoader loader,Class<?>[] interfaces,InvocationHandler h)
最终会调用InvocationHandler的方法
InvocationHandler Object invoke(Object proxy,Method method,Object[] args)
演示
publicstaticvoidmain(String[]args)throwsException{
Studentstudent=newStudent();
//创建Student的代理对象
MyInterfacep=(MyInterface)Proxy.newProxyInstance(Student.class.getClassLoader(),Student.class.getInterfaces(),newInvocationHandler() {
@Override
publicObjectinvoke(Objectproxy,Methodmethod,Object[]args)throwsThrowable{
System.out.println("你好");
method.invoke(student);
returnnull;
}
});
p.method();
}
原理
利用对象的类的字节码接口,写出一个新的类到本地区,通过编译器直接编译成.class文件,再通过类加载器加载进来
弊端: 代理的对象必须实现接口
cglib
定义
非java原生的动态代理, 效率更高,限制更小
可以代理没有接口的类
使用
导包
演示
publicstaticvoidmain(String[]args) {
//导入包 cglib-core asm ant ant-launcher
//创建运行器
MethodInterceptormi=newMethodInterceptor() {
@Override
publicObjectintercept(Objectarg0,Methodarg1,Object[]arg2,MethodProxyarg3)throwsThrowable{
System.out.println("运行前");
arg3.invokeSuper(arg0,arg2);
System.out.println("运行后");
returnnull;
}
};
//获取代理类
Enhancerenhancer=newEnhancer();
//设置父类
enhancer.setSuperclass(Demo.class);
//运行任务
enhancer.setCallback(mi);
//创建代理对象
Demod=(Demo)enhancer.create();
d.method();
}
总结
单例模式
模式: 针对某种问题的最优解
懒汉式, 饿汉式 , 饿汉式的变形体
如何写单例模式
私有化构造方法
提供自己创建的对象给使用者
优点 :
节省内存空间, 提升访问的速度
缺点 :
相对于静态来说, 效率还是要低一些
枚举
枚举就是多例的简写形式
枚举项的权限, 修饰符, 类型, new 省略
枚举的注意事项
类加载
就是将.class文件从硬盘上读取到内存中,变成一个java可以使用的类
类加载器
四个类加载器和他们的应用范围
根类加载器不是java代码写的
双亲委派模型
加载一个类的时候,从最底层的类加载器开始逐层上传, 一直到顶层, 整个过程要检测这个类有没有被加载过
作用 : 保持类的唯一性
反射
反射其实就是java提供的另外一种编程模式
提高了代码的兼容性, 扩展性
反射操作构造方法, 操作成员变量, 操作成员方法
default关键字
定义
1.8中允许我们给接口添加一个非抽象的方法实现, 在方法使用default关键字就可以了,这个特征又叫做拓展方法
演示
publicinterfaceMyInterface{
//使用default的关键字
publicdefaultvoidmethod(){
System.out.println("你好....");
}
}
注意事项
我们都知道, java之所以支持多实现就是应为接口中没有具体的逻辑代码, 不会造成冲突的问题, 那么1.8之后我们可以在接口中编写具体的逻辑代码了,那么多实现的时候会冲突吗 ?
肯定会冲突的,所以为了解决这个问题, 编译器要求如果多实现的时候出现了相同名称的非抽象方法的话,子类就必须重写这个方法
多实现
publicclassDemoimplementsMyInterface,MyInterface2{
@Override
publicvoidmethod() {
System.out.println("子类必须重写多个接口中相同名称的非抽象方法");
MyInterface.super.method();
}
}
二. 接口中的静态方法
定义
在接口中定义一个静态的方法, 可以有具体的代码实现
演示
publicinterfaceMyInterface{
//静态方法 只能接口自己使用
//接口中的静态方法权限必须是public的, 默认加上public
staticvoidmethod3(){
System.out.println("我是接口中的静态方法");
}
}
注意事项
子类无法使用接口中的静态方法
接口中的静态方法的权限必须是公共的,可以不写,默认是公共的
lambda表达式
定义
一种简写形式,格式精简, 很酷
每一个lambda的表达都对应一个类型,通常是接口类型的
适用于函数式接口(只有一个抽象方法的接口)
格式
(参数...) -> {执行代码} 返回一个可用的对象
当只有一句代码时,大括号可以省略, 建议省略
演示
publicstaticvoidmain(String[]args) {
List<String>list=Arrays.asList("hh","dd","ni","kk");
//之前的写法
Collections.sort(list,newComparator<String>() {
publicintcompare(Stringo1,Stringo2) {
returno1.compareTo(o2);
}
});
//lambda表达式的写法
Collections.sort(list, (Stringa,Stringb)->{
returna.compareTo(b);
});
System.out.println(list);
}
方法的引用
使用 : : 来引用一个类的方法
publicinterfaceDoing<K,T>{
publicTdoing(Kk);
}
publicstaticvoidmain(String[]args) {
//调用类中的静态方法来处理接口中方法上的参数
Doing<String,Integer>d=Integer::valueOf;
Integerinteger=d.doing("123");
System.out.println(integer);
}
publicstaticvoidmain(String[]args) {
//调用对象的方法
Doing<String,Integer>d="java"::lastIndexOf;
Integeri=d.doing("v");
System.out.println(i);
}
构造方法的引用
用new关键字来代替构造方法
publicclassPerson{
Stringname;
Person(Stringname) {
super();
this.name=name;
}
@Override
publicStringtoString() {
return"Person [name="+name+"]";
}
}
publicstaticvoidmain(String[]args) {
//引用对象的构造方法
Doing<String,Person>d=Person::new;
Personperson=d.doing("小明");
System.out.println(person);
}
注意事项
lambda表达式指向的接口必须和调用的方法的参数一致,也就是说相当于是接口实现类中的方法调用你指向的方法
lambda表达式中访问外层作用域和老版本的匿名对象的方式很相似, 你可以直接访问标记了final的外层局部变量, 或者示例的字段以及静态变量
lambda表达式中无法访问接口中的默认方法(就是被default修饰的方法)
四. Stream接口
定义
表示能应用在一组元素上一次执行的操作序列
其实就是找了一个地方将执行了某个方法后剩下的元素存放起来
提供了许多操作集合的方法,而且原集合数据不受影响
常用的方法
filter 过滤
sorted 排序
map 转化
match 匹配
count 计数
演示
publicstaticvoidmain(String[]args) {
List<String>stringCollection=newArrayList<>();
stringCollection.add("ddd2");
stringCollection.add("aaa2");
stringCollection.add("bbb1");
stringCollection.add("aaa1");
stringCollection.add("bbb3");
stringCollection.add("ccc");
stringCollection.add("bbb2");
stringCollection.add("ddd1");
//过滤出以a开头的元素并遍历
stringCollection.stream().
filter((s)->s.startsWith("a"))
.forEach(System.out::println);;
}
并行
并行Stream可以在多个线程上同时执行
publicstaticvoidmain(String[]args) {
intmax=1000000;
List<String>values=newArrayList<>(max);
for(inti=0;i<max;i++) {
//创建随机id
UUIDuuid=UUID.randomUUID();
values.add(uuid.toString());
}
longt1=System.nanoTime();
//获取并行的stream
longcount=values.parallelStream().sorted().count();
System.out.println(count);
longt2=System.nanoTime();
System.out.println(t2-t1);
}
五. Date
定义
java 8 在包java.time下包含了一组全新的时间日期API
ZoneId
定义时区
publicstaticvoidmain(String[]args) {
System.out.println(ZoneId.getAvailableZoneIds());
//获取某个城市的时区
ZoneIdzone1=ZoneId.of("Europe/Berlin");
ZoneIdzone2=ZoneId.of("Asia/Shanghai");
System.out.println(zone1.getRules());
System.out.println(zone2.getRules());
}
LocalTime
一个没有时区信息的时间,以设置的时区为准备
publicstaticvoidmain(String[]args) {
//获取所有的时区信息
System.out.println(ZoneId.getAvailableZoneIds());
//获取某个城市的时区
ZoneIdzone1=ZoneId.of("Europe/Berlin");
ZoneIdzone2=ZoneId.of("Asia/Shanghai");
LocalTimenow1=LocalTime.now(zone1);
LocalTimenow2=LocalTime.now(zone2);
//判断时间1以是否在时间2之前
System.out.println(now1.isBefore(now2));// true
//使用ChronoUnit计算两个时间差值
longhoursBetween=ChronoUnit.HOURS.between(now1,now2);
longminutesBetween=ChronoUnit.MINUTES.between(now1,now2);
System.out.println(hoursBetween);
System.out.println(minutesBetween);
}
六.其他新特性
重复注解
可以将参数的名字保留到字节码中
Nashorn引擎 : jjs , 可以执行js代码
移除了FermGen空间,用Metaspace代替
-XX:MetaSpaceSize与-XX:MaxMetaspaceSize被代替-XX:PermSize与-XX:MaxPermSize
一阶段的知识点
了解计算机基础知识
了解的dos命令
了解java的历史
jdk的安装和环境变量的配置
进制
java的编译-运行方式
变量, 常量 数据类型(基本的8个,引用的5个)
运算符 : 算数运算符 复制运算符 关系运算符 逻辑运算符(双与双或/单与单或) 位运算符(& | ~ >> << >>>) 三元运算符
判断 循环
数组 (长度固定) 二维数组
方法 (方法的组成, 重载: 方法名相同,参数列表不同)
面向对象
如何写一个类
如何使用一个类
类和类之间的关系(重写)
抽象类和接口
多态 : 提高扩展性和兼容性
内部类 : 成员的, 静态的, 局部的, 匿名的
异常 : 最重要的时类名
常用类
Object
String (方法必须记熟)
StringBuffer StringBuilder
Math Date SimpleDateFormat
Random BigInteger BigDcimal
集合
Collection Map
List Set Queue
List :
ArrayList: 查改快 增删慢 LInkedList: 增删快, 查改慢
Set
HashSet : 去重 TreeSet : 去重 排序
Map (key不能重复)
HashMap : 快 TreeMap : 排序
Collections
迭代器 迭代器运行时不能改变原集合
泛型 :
多线程
多线程的好处
多线程的创建使用
多线程的状态
锁
线程的通信
线程池
File 类
操作本地路径(文件和文件夹)
递归
流
字节流 字符流
文件流中, 除了FileInputStream和FileOutputStream之外, 其他的都是缓冲流
缓冲流有缓冲区, 使用时要注意
网络编程
ip 端口号
UDP TCP
java 两种网络编程方式(主要记TCP)
NIO
非阻塞 模拟多线程, 没有多线程的开销, 实质还是轮询处理, 只适合小流量高并发的场景
通道管理器
单例 多例 枚举 类加载器 反射 多态代理 注解
1 . 8 新特性 : 接口中 default static的使用 la