目录
一、java注解
二、java反射机制
三、java1.8新特性
一、Java注解(jdk1.5+)
1、注解概述
注解:Annotation
编写代码时可以在不改变代码原逻辑的情况下,在源文件中通过注解的方式嵌入补充信息,并且注解的信息可以在类的编译、加载、运行时被读取,执行有关操作
在JavaSE中,注解的使用目的简单,主要有用来标记方法的重写@Override,标记过时的方法,测试方法等;在JavaEE开发中,注解扮演者特别重要的角色,通常与反射一同使用。
框架 = 注解 + 反射 + 设计模式
2、注解的使用
- 注解通常在方法或属性上方标识,有的注解后的()中可以添加相关元素,取决于注解是如何定义的
- 注解在编译时及逆行格式的检查,JDK内置的几个基本注解使用方法:
- @Override : 限定重写父类方法,该注解只能用于方法
- @Deprecated: 用于表示所修饰的元素(类、方法)已经过时。(旧结构存在缺陷或已经有其它更好的选择)
- @SuppressWarnings : 抑制编译器警告
- 在后面的使用中,多用来代替配置文件,实现容器注入功能。
3、元注解
jdk为我们提供了四种元注解,他们分别是:
- @Retention : 指定所修饰的Annotion的生命周期
- 参数:RetentionPolicy.XXX
- SOURCE: 只在源码保留,编译时将它忽视
- CLASS:只保留到编译时候
- RUNTION: (默认),保留到运行时,可被JVM加载到内存中
- @Target: 指定所修饰的Annotion可以被那些结构所使用
- 参数:ElementType.XXX
- TYPE: 给类加注解
- FIELD: 给属性加注解
- METHOD: 给方法加注解
- PARAMETER: 给方法内参数加注解
- CONSTRUCTOR: 给构造器加注解
- LOCAL_VARIABLE: 给局部变量加注解
- ANNOTATION_TYPE: 给注解添加注解
- PACKAGE: 给包添加注解
- @Inherited: 被它修饰的Annotion将具有继承性
- @Repeatable: 被修饰的Annotion被javadoc解析后可以保留下来
4、自定义注解
步骤:
- 注解声明为@interface
- 内部定义成员,用value表示
- 可以指定成员默认值,用default定义
- 如果自定义注解内没有成员,表明该注解代表一个标识
- 自定义注解还需要搭配元注解使用
@Inherited
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.FIELD,ElementType.METHOD})
public @interface MyAnnotion1 {
int value() default 12;
}
5、如何获得注解信息
前提:此注解的元注解Retention中声明的生命周期为RUNTIME
然后通过反射来获取到相关的信息,那我们来看看是如何通过反射获取到注解信息!
JDK1.8中新增:可重复注解、类型注解
二、java反射机制
1、反射概述
- Reflection反射机制允许程序在执行期借助于Reflection API取得任何类的内部信息,并能直接操作任意对象的内部属性及方法。
- Reflection API:
- java.long.Class
- java.long.reflect.Method
- java.long.reflect.Field
- java.long.reflect.Constructor...
- Reflection API:
- 反射机制是被视为动态语言的关键,在运行时才能确定到底运行的是什么。
- 反射机制依靠JVM的加载器将类加载到内存中,然后获取相关类的信息
- 在运行时可以判断对象所属的类
- 在运行时构造任意类的对象
- 运行时可以判断一个类所具有的成员变量和方法
- 在运行时获取泛型信息
- 运行时可调用任何对象的方法
- 运行时处理注解
- 生成动态代理
2、Class类的加载过程
- 程序先执行javac.exe命令,生成一个或多个(.class)字节码文件。
- 我们使用java.exe命令对某个字节码文件进行解释运行。相当于将某个字节码文件加载到内存中。此过程就称为类的加载。
- 加载到内存中的类,我们就称为运行时类,此运行时类,就作为Class的一个实例。
获取Class的四种方式:
①调用运行时类的属性:类.class
Class clazz1 = Person.class;
②通过运行时类的对象,调用getClass()
Person p1 = new Person();
Class clazz2 = p1.getClass();
③调用Class的静态方法:forName(String classPath)
Class clazz3 = Class.forName("com.xiongmdd.Person");
④使用类的加载器:ClassLoader
ClassLoader classLoader = ReflectText.class.getClassLoader();
Class clazz = classLoader.loadClass("com.xingmdd.Person");
Class实例可以是:class,interface,数组,enum,annotation,基本数据类型,void
3、反射的应用
①创建运行时类的对象
- newInstance():创建运行时类的对象
- 前提:必须访问到运行时类的空参构造器
Class<Person> clazz = Person.class;
Person llj= clazz.newInstance();
System.out.println(llj);
②获取运行时类的完整结构
- 我们可以通过反射,获取对应的运行时类中所有的属性、方法、构造器、父类、接口、父类的泛型、包、注解、异常
- getFields(): 获取当前运行时类及其父类中声明为public访问权限的属性
- getDeclaredFields(): 获取当前运行时类中声明的所属性。(不包含父类中声明的属性)
- getMethods(): 获取当前运行时类及其所父类中声明为public权限的方法
- getDeclaredMethods(): 获取当前运行时类中声明的所方法。(不包含父类中声明的方法)
- getConstructors(): 获取当前运行时类中声明为public的构造器
- getDeclaredConstructors(): 获取当前运行时类中声明的所的构造器
- getSuperclass():获取当前运行时类的父类
- getGenericSuperclass():获取运行时类的带泛型的父类
- getInterfaces():获取运行时类实现的接口
- getPackage(): 获取运行时类所在的包
- getAnnotations() : 获取运行时类声明的注解
③获取运行时类的指定结构
- 在参数中添加相关形参,即可获取指定参数的数据,但是要保证当前方法可访问: setAccessible(true)
- getDeclaredField(String fieldName):获取运行时类中指定变量名的属性
- getDeclaredMethod(methodName, 该方法的形参列表) :获取指定的某个方法 + 调用invoke(方法调用者,方法形参)执行方法:
- getDeclaredConstructor(参数列表类型.class): 获取指定的构造器 + newInstance("Xxx")创建对象;
三、java1.8新特性
1、Lambda表达式
- Lambda表达式格式
- -> : lambda 操作符
- -> : 左边:接口抽象方法形参列表
- -> : 右边:lambda实体,重写方法的方法体
- 例子1:
Runnable r1 = () -> System.out.println("重写的run方法方法体内");
r2.run();
- 例子2:
Comparator<Integer> c1 = (o1,o2) -> Integer.compare(o1,o2); //只有一条语句时,return {} 可省略
int com = com2.compare(32,21);
语法格式:
1、无参无返回值 : ()-> { 代码; };
2、需要一个参数,无返回值: (String str)-> { 代码; };
3、数据类型可有编译器判断得出: (str) -> { 代码; };
4、若只有一个型参,()可以以省略 : str -> { 代码;};
5、参数多且有返回值: (x,y) -> { 代码;return 代码; };
6、只有一条返回语句:return 和 {} 都可以省略 : (x,y) -> 返回代码;
2、函数式接口
- 果一个接口中,只声明了一个抽象方法,则此接口就称为函数式接口。
- 我们可以在一个接口上使用 @FunctionalInterface 注解,这样做可以检查它是否是一个函数式接口。
> Lambda表达式的本质:作为函数式接口的实例 - Java8中关于Lambda表达式提供的4个基本的函数式接口:
3、方法引用
方法引用就是Lambda表达式,也就是函数式接口的一个实例,通过方法的名字来指向一个方法。
格式:类(或对象) :: 方法名
- 对象 :: 实例方法
- 类 :: 静态方法
- 类 :: 实例方法 (难度)
public void test1() {
Consumer<String> con1 = str -> System.out.println(str);
con1.accept("西安");
//
PrintStream ps = System.out;
Consumer<String> con2 = ps::println;
con2.accept("xi'an");
}
public void test2() {
Comparator<Integer> com1 = (t1,t2) -> Integer.compare(t1,t2);
System.out.println(com1.compare(12,21));
//
Comparator<Integer> com2 = Integer::compare;
System.out.println(com2.compare(12,3));
}
public void test3() {
Comparator<String> com1 = (s1,s2) -> s1.compareTo(s2);
System.out.println(com1.compare("abc","abd"));
//
Comparator<String> com2 = String :: compareTo;
System.out.println(com2.compare("abd","abm"));
}
4、构造器引用与数组引用
- 类名::new
Supplier<Employee> sup1 = () -> new Employee();
System.out.println(sup1.get());
System.out.println("*******************");
Supplier<Employee> sup2 = Employee :: new;
System.out.println(sup2.get());
- 数组类型[ ] :: new
public void test4(){
Function<Integer,String[]> func1 = length -> new String[length];
String[] arr1 = func1.apply(5);
System.out.println(Arrays.toString(arr1));
System.out.println("*******************");
Function<Integer,String[]> func2 = String[] :: new;
String[] arr2 = func2.apply(10);
System.out.println(Arrays.toString(arr2));
}
jdk1.8还有很多新增的特性,以后再做更详细的分享哦
下一阶段:mySQL数据库!