之前在读源码的时候由于java的基础知识实在太拉闸,所以暂时放弃源码阅读任务,既然基础差那就学基础呗,所以学了注解和反射机制。
首先是注解
注解,顾名思义啊,和注释有点类似,但是注解是给代码看的,不是给人看的,作用是对程序做出解释,可以被其他程序读取(比如用反射来操作注解),
用于过时的类、方法、成员变量等
覆盖父类方法
阻止警告,用来抑制编译时的警告
指定接口必须为函数式接口
一直"堆污染警告"
用于注解定义的时候规范注解行为
就像定义类一样,使用@interface来自定义注解
里面的每一个方法->声明了一个参数
方法名->参数名
返回值->参数类型
可以在括号后面使用default一个默认值,如果默认值为-1代表不存在
若只有一个参数建议使用value来命名,在使用的时候可以省略value。
为啥叫反射呢,因为它相对于new一个对象是反着来的哈哈哈
java本来是静态语言 但是加上反射,就变成准动态语言了。
反射主要是靠一个Class对象来做事的,Class对象就像一面镜子,可以看到其他类的所有结构
反射的优点是实现了动态创建对象和编译
缺点是影响性能,用反射没有new来得快
这里介绍一下Class对象:
获取class实列:
所有的类都有class对象,不仅如此,接口、数组、注解、枚举、void都有class对象
那么类声明时候会发生初始化呢
主动引用√
被动引用×
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-hjEWPBFn-1591694374500)(/img/artImg/lyc091233451591677226255.png ‘‘图片title’’)]
//获取系统类加载器 sun.misc.Launcher$AppClassLoader@18b4aac2
ClassLoader systemClassLoader = ClassLoader.getSystemClassLoader();
System.out.println(systemClassLoader);
//获取系统 sun.misc.Launcher$ExtClassLoader@1b6d3586
ClassLoader parent = systemClassLoader.getParent();
System.out.println(parent);
//获取扩展类加载器的父类加载器---->根加载器(C/C++) Java获取不到,返回null
ClassLoader parent1 = parent.getParent();
System.out.println(parent1);
//测试当前类是哪个类加载器的 sun.misc.Launcher$AppClassLoader@18b4aac2
ClassLoader classLoader = Class.forName("com.lcy.reflection.Test07").getClassLoader();
System.out.println(classLoader);
//测试JDK内置的类是谁加载的 null
classLoader = Class.forName("java.lang.Object").getClassLoader();
System.out.println(classLoader);
//如何获得系统类加载器可以加载的路径 如果类不在这些地方则读取不到
System.out.println(System.getProperty("java.class.path"));
//双亲委派机制:多重检测,保证安全性
// 比如自己定义一个java.lang.String类,要去加载,它先看用户类加载器有没有--->扩展类加载器--->根加载器
//如果有自己写的就无效
在获取class对象后,使用get+field、method、name等等获取对应的信息
可以通过newInstance方法调用无参构造器构造一个对象,在没有无参构造器的时候,可以调用getDecluredConstructor来得到构造器,通过给这个构造器传参newInstance一个对象
Constructor declaredConstructor = c1.getDeclaredConstructor(String.class, int.class, int.class);
user User2 = (user)declaredConstructor.newInstance("sblzq",21,21);
通过反射的方式来调用方法的时候,使用invoke来激活:
Method setName = c1.getDeclaredMethod("setName", String.class);
setName.invoke(User,"lzqzhenshisb");
通过反射的方式来获取字段的时候,如果字段是private的,那么需要setAccessible(true)来关闭安全监测:
Field name = c1.getDeclaredField("name");
name.setAccessible(true);
name.set(User,"lzqdsb");
普通方式嘴快,反射慢,如果关闭安全监测能显著提高反射速度,但也比普通方式慢
可以通过type类中的方法来解析泛型:
package reflection;
import java.lang.reflect.Method;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.List;
import java.util.Map;
public class test08 {
public static void test01(Map<String,user> map,List<user> list){
System.out.println("this is test01");
}
public static Map<String,user> test02(List<user> list){
System.out.println("this is test02");
return null;
}
public static void main(String[] args) throws NoSuchMethodException {
Method method1 = test08.class.getMethod("test01", Map.class, List.class);
Type[] genericParameterTypes = method1.getGenericParameterTypes();
for (Type genericParameterType : genericParameterTypes) {
System.out.println(genericParameterType+"~~~~~~~~");
if(genericParameterType instanceof ParameterizedType){
Type[] actualTypeArguments = ((ParameterizedType) genericParameterType).getActualTypeArguments();
for (Type actualTypeArgument : actualTypeArguments) {
System.out.println(actualTypeArgument);
}
}
}
Method method2 = test08.class.getMethod("test02", List.class);
Type genericReturnType = method2.getGenericReturnType();
if(genericReturnType instanceof ParameterizedType){
Type[] actualTypeArguments = ((ParameterizedType) genericReturnType).getActualTypeArguments();
for (Type actualTypeArgument : actualTypeArguments) {
System.out.println(actualTypeArgument);
}
}
}
}
然后还可以用反射来操作注解(其实这才是最重要的吧喂!)
//反射操作注解
public class Test12 {
public static void main(String[] args) throws ClassNotFoundException, NoSuchFieldException {
Class c1 = Class.forName("com.lcy.reflection.Student");
//通过反射获得注解
Annotation[] annotations = c1.getAnnotations();
for (Annotation annotation :annotations) {
//找到了外面的注解@com.lcy.reflection.TableTemp(value=db_stu)
System.out.println(annotation);
}
//获得注解value的值 db_stu
TableTemp tableTemp = (TableTemp) c1.getAnnotation(TableTemp.class);
String value = tableTemp.value();
System.out.println(value);
/**
* 获得类指定的注解
* db_stu
* db_name
* String
* 10
*/
Field f = c1.getDeclaredField("name"); //name对应表中的字段
FieldTemp annotation = f.getAnnotation(FieldTemp.class);
System.out.println(annotation.columnName());
System.out.println(annotation.type());
System.out.println(annotation.length());
}
}
@TableTemp("db_stu")
class Student{
@FieldTemp(columnName = "db_id",type = "int",length = 10)
private int id;
@FieldTemp(columnName = "db_name",type = "String",length = 10)
private String name;
@FieldTemp(columnName = "db_age",type = "varchar",length = 5)
private int age;
public Student() {
}
public Student(int id, String name, int age) {
this.id = id;
this.name = name;
this.age = age;
}
@Override
public String toString() {
return "Student{" +
"id=" + id +
", name='" + name + '\'' +
", age=" + age +
'}';
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
}
//类名的注解
@Target(ElementType.TYPE) //设置作用域
@Retention(RetentionPolicy.RUNTIME) //设置什么级别可以获取
@interface TableTemp{
String value();
}
//属性的注解
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
@interface FieldTemp{
String columnName(); //列名的注解
String type(); //类型
int length(); //长度
}
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
}
//类名的注解
@Target(ElementType.TYPE) //设置作用域
@Retention(RetentionPolicy.RUNTIME) //设置什么级别可以获取
@interface TableTemp{
String value();
}
//属性的注解
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
@interface FieldTemp{
String columnName(); //列名的注解
String type(); //类型
int length(); //长度
}
就没了,其实内容不多,但我还是学了好几天,看来划水时间有点长。
因篇幅问题不能全部显示,请点此查看更多更全内容