反射、jdk新特性
反射
多个模块之间产生关联—耦合度
1)Service层
可以读取配置文件内容中的字符串内容,可以通过技术来把字符串内容解析成对应的类从而创建对象----这门技术就是反射
2)Dao层—(连接)—MysqlImpl------Mysql
提供数据库操作的接口
概念
解析类,由字节码对象来获取实例对象的过程—反射(发生在运行时期)
图形解释:
Person.class—>方法区(Person.class(字节码对象))-----反射---->堆(new Person()(实例对象))
Class
代表类的类 创建的对象就是具体的类(一个具体类等效为一个.class文件对应一个字节码对象)
1、获取字节码对象
1)通过数据类型.class来获取字节码对象
Class <String> c=String.class
2)对象.getClass()返回字节码对象
Class<String> c=(Class<String>“zuo”.getclass
3)把字符串内容传入到forName静态方法中来返回字节码对象(保证字符串内容没有问题)
Class<String> c=(Class<String>)Class.forName("java.lang.String")
2、通过字节码对象来获取实例对象
//字节码对象
Class<String> clz=String.class;
1)字节码对象调用newInstance无参方法默认调用无参构造来返回实例对象
String s=clz.newInstance();
2)先获取有参构造,再通过构造方法类的对象调用newInstance有参方法来给有参构造进行赋值最后返回实例对象
Constructor<String> c=clz.getConstructor(String.class);
String s=c.newInstance("zuo");
Method
代表方法的类 创建的对象就是具体的方法
Field
代表属性的类 创建对象就是具体的属性
Constructor
代表构造方法的类 创建对象就是具体的构造方法
Package
代表包的类 创建对象就是具体的包
缺点
1、打破了封装原则
//字节码对象
Class<String> clz=String.class;
//会获取指定属性(私有化属性)
Fileld f=clz.getDeclaredField("hash");
//提供实例对象
String str="zuo";
//暴力破解(获取私有化属性)
f.setAccessible(true);
//改变实例对象的hash属性值
//第一个参数代表选择的实例对象,第二个参数代表传入的新的对象属性值
//可以给私有化属性赋值
f.set(str,21);//str.hashCode()返回21
//获取实例对象的私有化属性的值
System.out.println(f.get(str));//21
Class<String> clz = String.class;
//获取指定方法
Method m = clz.getDeclaredMethod("charAt", int.class);
//提供实例对象
String str="asadfvqw";
//通过Method类的对象来选择具体的实例对象
//执行方法:第一个参数代表选择的实例对象,第二个参数代表实参
//等效于---str.charAt(3)
System.out.println(m.invoke(str,3));;
//获取所有实现的接口
Class<String>[] cs = (Class<String>[]) clz.getInterfaces();
//返回的是包名+类名
clz.getName()
// 返回包名以及相关版本信息
clz.getPackage()
//类名
clz.getSuperclass()
//判断字节码对象的类型是否是基本数据类型
int.class.isPrimitive()
2、跳过泛型的类型检测
1)泛型擦除发生在编译时期,限定存储元素的数据类型
2)反射在运行时期跳过了泛型的类型检测,可以指定存储元素的类型为Object类型就可以存储任意类型数据
List<String> list=new ArrayList<>();
Class<List> clz = (Class<List>) list.getClass();
Method m = clz.getDeclaredMethod("add", Object.class);
m.setAccessible(true);
m.invoke(list,true);
jdk新特性
jdk1.5新特性
1、静态导入
1)可以把静态方法进行导入就可以直接使用
2)静态导入的方法先加载。
2、可变参数
1)表现形式:参数类型…
2)可以接受任意多个参数值(要和参数类型他同意)
3)底层根据数组来实现,数组的每个元素来接收对应接收的参数值
4)只能出现在参数列表的最右边
3、枚举
1)将值一一列举
2)枚举常量要在一行并在首行
3)可以定义属性和普通方法
4)定义的构造方法只能是私有化的,外部不能重新创建对象
5)可以定义抽象方法(保证枚举常量需要重写抽象方法)
6)从jdk1.5开始switch的表达式支持枚举类型
jdk1.8新特性
1)接口中支持定义实体方法(可以用default或者static来修饰的方法)
public class LambdaDemo {
public static void main(String[] args) {
//创建实现类对象可以调用接口中的实体方法
/* CalcImpl c=new CalcImpl();
System.out.println(c.sum(1,2));
//接口名.调用静态实体方法
System.out.println(Calc.jc(3,4));*/
//匿名内部类默认重写抽象方法并创建匿名内部类的对象调用重写方法
/* System.out.println(new Calc() {
@Override
public int max(int m, int n) {
return m>n?m:n;
}
}.max(2,3));*/
//Lambda表达式
//(参数列表)->{重写方法体}
//Calc c=(int m,int n)->{return m>n?m:n;};
//参数类型可以由前推导出来所以可以省略不写,如果方法体只有一句话可以省略return和{}不写
//保证接口中只有一个抽象方法才能使用
Calc c=(m,n)->m>n?m:n;
System.out.println(c.max(3,4));
}
}
//定义代表计算器的接口
//函数式接口(只能有一个抽象方法)---函数式编程
@FunctionalInterface
interface Calc{
//求大小(抽象方法)
int max(int m,int n);
//用default修饰的实体方法
public default int sum(int x,int y){
return x+y;
}
//用static修饰的实体方法
public static int jc(int x,int y){
return x*y;
}
}
//实现类
class CalcImpl implements Calc{
@Override
public int max(int m, int n) {
return m>n?m:n;
}
}
①函数式接口(只能有一个抽象方法)----函数式编程
@FunctionalInterface
②main方法中,创建实现类对象可以调用接口中的实体方法
eg:CalcImpl c=new CalcImpl();
③接口名.调用静态实体方法
④匿名内部类默认重写抽象方法并创建匿名内部类的对象调用重写方法
2)Lambda表达式默认实现函数式接口类重写抽象方法
①(参数列表)->{重写方法体}
eg:Calc c=(int m,int n)->{return m>n?m:n;};
②参数类型可以由前推导出来所以可以省略不写,如果方法体只有一句话可以省略return和{}不写
保证接口中只有一个抽象方法才能使用
eg:Calc c=(m,n)->m>n?m:n;
c.max(3,4);
3)Stream—流式结构
流式操作集合元素
提供大量的函数式接口(可以使用Lambda表达式)
public class StreamDemo {
public static void main(String[] args) {
List<String > list=new ArrayList<>();
list.add("zuo");
list.add("zai");
list.add("yu");
list.add("zi");
/* //增强for循环
for(String s:list){
if(s.startsWith("z")){
System.out.println(s);
}
}*/
//流式结构
Stream<String> st=list.stream();
/* //过滤
st.filter(new Predicate<String>() {
@Override
public boolean test(String s) {
return s.startsWith("z");
}
}).forEach(new Consumer<String>() {
@Override
public void accept(String s) {
System.out.println(s);
}
});*/
st.filter(s1->s1.startsWith("z")).sorted((o1,o2)->o1.compareTo(o2)).forEach(s2-> System.out.println(s2));
}
}
单例设计模式
1)保证类产生单个实例对象
2)饿汉式:优点是没有线程安全问题,缺点是无论是否需要对象都会创建
懒汉式:优点是需要对象时才创建,缺点是线程不安全
了解其他的实现形式