Day12=枚举+注解+反射+类加载器+双亲委派+如何加载配置文件+class对象+反射获取注解+内省

本文主要是介绍Day12=枚举+注解+反射+类加载器+双亲委派+如何加载配置文件+class对象+反射获取注解+内省,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

枚举

(记忆中可以阻止反射破坏单例模式?)
定义多个常量(public static final)并分组管理。
举例:Thread.state,有六种状态,每个都是该类对象

枚举定义

public enum Level{LOW(1),MID(50),HIGH(100);//描述完毕private int levelVal;private Level(int levelVal){this.levelval = levelVal;}}

或者:

public enum Level{LOW,MID,HIGH;
}

Enum是个抽象类

只有一个toString()可以重写
获取对象Level x = Enum.valueOf(Level.class,"LOW");
Level.Low.show();

定义接口,实现不同的show

public enumm Level implements LShow{LOW(){@Overridepublic void show(){System.out.println("低级别");}},MID{ //这里()可写可不写,调用午餐构造方法@Overridepublic void show(){System.out.println("中级别");}
}interface LShow{void show();
}

枚举类使用时注意事项

  • 定义好之后尽量不修改
  • 默认继承的是java.lang.Enum而不是Object
  • 枚举类不能有子类,默认被final
  • 只能有private构造方法,不允许外部创建他
  • switch中使用时直接使用常量名,不带类名
  • 不要提供set属性的方法
  • 不能定义name属性,因为它自带name

注解

Annotation,JDK5.0引入的注释机制
可以标注的:类、方法、变量、参数、包。

注释是不会编译到class文件里的,注解是给机器看的,可以被嵌入到字节码中。

注解有什么作用?

  • 编译格式检查
  • 反射中解析(通过反射获取内容)
  • 生成帮助文档
  • 跟踪代码依赖
  • 。。。其他

内置注解

  • @Override 重写 【编译格式检查,必须重写了父类的方法】
  • @Deprecated 废弃 【不用了,开发时会利用反射发现这个方法废弃并告知】
  • @SafeVarargs 忽略任何使用参数为泛型变量的方法或构造函数调用产生的警告 【JDK7出现】
  • @FunctionalInterface 函数式接口 【8开始,标识一个匿名函数或函数式接口】

只包含一个方法的接口 lambda无法单独出现,需要一个函数式接口来盛放,lambda表达式方法体就是函数接口的实现。Runnable r = ()->System.out.println("lambda");

  • @SuppressWarnings 抑制编译时的警告信息(“all”)
    获取方法->获取方法注解

元注解与自定义注解

元注解是给自定义注解加注解,进行一些配置。

  • @Retentino 保持,注解应该只在代码中还是编入class中或者运行时反射访问(枚举)
  • @Documented 这些注解是否包含在用户文档javadoc
  • @Target 标记这个注解是那种Java成员
  • @Inherited 注解是自动继承的 子类会自动继承父类使用的注解中被@Inherited修饰的注解,接口继承中不会接收任何父接口中的注解,类实现接口时也不会
    自定义注解关系:
  • 指定数个ElementType确定范围(方法,参数,字段,类型)(这个也是枚举)
  • RetentionPolicy 属性唯一 持久策略

定义格式

@interface name()

@Documented
@Target({ElementType.TYPE, ElementType.METHOD})//可以用在类或方法上,控制注解可以作用的位置
@Retention(RetentionPolicy.RUNTIME)//一个注解至少对应一个持久策略(Runtime包含class包含source)
@Inherited //可以继承
@interface MyAnnotation{ //自动继承java.lang.annotation.Annotation接口String value() default "aa";//给一个默认值int num() default 1;//给一个默认值
}@MyAnnotation(value="xx",num=100)
public class Demo{
}

反射(国企特别喜欢考这点)

运行状态中获取任意一个类的结构去创建对象,去得到方法,执行方法和属性操作。正常的流程是通过java文件编写代码转换为class文件再由类加载器加载到内存,jvm通过内存里的类信息创建对象。反射是在运行状态获取信息并动态调用对象方法。

  • 反射reflection机制,在程序的运行状态中,构造任意类的对象, 了解任意对象所属的类,了解任意类的成员变量和方法,调用任意对象属性和方法。(反封装)
  • 体现在动态(代码运行过程中)获取程序信息和动态调用对象功能。

类加载器

是Java运行时环境的一部分,负责动态加载类到JVM的内存空间里。
默认有三种类加载器:

  • 引导启动类加载器 BootstrapClassLoader 用C++写的,加载JAVA_HOME/lib下的类库⬇️
  • 扩展类加载器 ExtensionClassLoader⬇️
  • 应用类AppClassLoader 负责加载应用程序classpath目录下的所有jar和class文件
    父->子->子的子这个关系

双亲委派模型(面试常考)

当子加载类时,首先会告知父加载这个类,父又往上找父,如果Bootstrap没有加载(搜索范围内没找到这个类),那么让子加载。这样可以去避免有些类被重复加载。
如何加载配置文件?找到app加载器(通过Demo1.class.getClassLoader().getResourceAsStream(“config.txt”);这样可以直接获取输入流之后再打印)。
如果修改文件夹为source,再getResourceAsStream就不是src下的了,就时source文件夹里的那个文件。

所有类型的class对象

Demo.java Person.java–>>编译–>>Demo.class Person.class–>>加载–>>内存(Class类型的对象Demo.class和Person.class)

得到Class的三种方式(面试常考)

  1. 拥有类的对象,可以通过 .getClass()得到类对象
  2. 知道类的名称,Class.forName(包名+类名)
  3. 知道类的名称且类已经存在,直接包名+类名.class就可以得到一个类的类对象
    调用时,如果类不在内存中,则会加载到内存。如果已经存在,不会重复加载,直接用。(一个class文件在内存中不会存在两个类对象)
    举例:
//1. 包.类.class
Class<Person> c1 = com.java.demo.Person.class;
//2. 已有类对象
Class<Person> c2 = (Class<Person>)p.getClass();//需要强转
//通过==比较c1c2是true
//3. Person都不存在,让他自己找包
Class.forName("com.java.demo.Person");//注意抛出ClassNotFoundException

如果把person删了编译时3是不会报错的。其他都不行。只有在运行时才知道不行。

通过反射获取Constructor构造方法

  1. getConstructor(参数类型的class) 指定的参数类型来获取指定的构造方法【获取对象的类->获取对象的构造方法->指定新的Class对象数组,里面包含指定的参数的.Class】
Constructor c = p.getClass().getConstructor(new Class[]{String.class, int.class});
  1. 获取构造方法数组 getConstructors();
    举例:
//把Person的类加载到内存
Class<Person> pClass = (Class<Person>) Class.forName("com.java.demo.Person");
//找到全参构造方法
Constructor<Person> p1 = pClass.getConstructor(String.class, int.class);
//或者new Class[]{String.class, int.class}
//使用构造方法创建对象
Person p = p1.newInstance();

如何忽略构造方法的private?getDeclaredConstructor()+p1.setAccessible(true);这样就可以获取访问受限的构造方法【打破单例模式】
总结:创建对象

  • 如果为true则表明忽略访问权限检查setAccessible(true);
  • newInstance()调用构造方法把对象创建出来

通过反射获取方法

  1. getMethod(mathodName, class)
  2. getMethods
  3. getDeclaredMethod(String methodNam, class…class)
  4. getDeclaredMethods
  • 执行方法:method.invoke(对象,传参);
//加载类
Class c1 = Class.forName("com.jav.demo.Person");//泛型可以不指定,但创建对象时要强转
//获取构造方法
Constructor c = c1.getConstructor();
//创建对象
Object o = c.newInstance();
//获取类的方法
c1.getMethod("setName", param:String.class);
//执行方法 执行setName方法的对象;调用方法时传递的参数0-n个
setName.invoke(o,"xx");

通过反射获取Field属性

  1. getDeclaredField(String fieldName);根据属性名称获取属性对象
  2. getDeclaredFields()获取所有属性
  3. getField(String fieldName)根据属性名称获取属性对象(public)
  4. getFields()获取所有属性public
    操作
  • f.get(Object o);参数是要获取属性的对象,获取指定对象的该属性值
  • f.set(Object o, Object value);对象,要设置的值
  • getName()获取属性的名称
  • setAccessible(flag)
    举例
//...创建对象o,类是c
Field phone = c.getField("phone");
phone.set(o,"123");

通过反射获取注解

ORM框架 对象关系映射

Person类->数据库里创建Person表格里面是一行各种属性

创建注解
//类与表名对应
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface TableAnnotation{//用于标注某个类对应的表格名称String value();
}//属性与列对应(名称、类型、长度)
@Target(ElementType.FIELD)//对应属性
@Retention(RetentionPolicy.RUNTIME)
public @interface ColumnAnnotation{//描述列名String colName();//描述类型String type();//描述数据长度String length();
}public class Book {
//Book类对应数据库中的Book表@ColumnAnnotation(columnName = "id", type="int", length = "11")private int id;@...private String name;@...private String info;
}

RetentionPolicy持久策略,SOURCE注解的信息只记录在源文件中,编译时会丢弃;CLASS注解记录在文件中,但不会加载到JVM中,这也是默认值;RUNTIME注解信息保留在源文件、类文件中,执行时也加载到Java的JVM中,因此可以用反射读取。

//类信息
Class c = Class.forName("com.java.demo2.Book");
//注解
Annotation[] as = c.getAnnotations();
for(Annotation a:as){//输出注解
}
TableAnnotation ta = (TableAnnotation)c.getAnnotation(TableAnnotation.class);
String value = ta.value();
Field[] fs = c.getDeclaredFields();
//获取属性注解
for(Field f: fs){ColumnAnnotation ca = f.getAnnotation(ColumnAnnotation.class);
//f.getName() ca.columnName() ca.type() ca.length()
}

内省Introspector(基于反射延伸出来的API)应用到JavaBean

bean类(没有包含业务逻辑,存储属性并提供get/set)

重要,理解后设计bean的时候一定要规范,让框架得以运用

  • 无参构造器
  • 所有属性私有
  • 所有属性提供get/set方法
  • 实现序列化接口
    Java提供了一套API对反射的操作进行封装
    getBeanInfo(Class c)传class->得到BeanInfo对象->getPropertyDescriptors()->获得MethodDecriptor[]对象(一个属性的get/set方法)->
  • getReadMethod() get
  • getWriterMethod() set
    通过内省的形式更快地获取bean的get/set,封装好的。
BeanInfo bi = Introspector.getBeanInfo(c);
PropertyDescriptor[] pds = bi.getPropertyDescriptors();
//遍历数组获取属性的get和set方法
for(PropertyDescriptor pd:pds){Method get = pd.getReadMethod();Method set = pd.getWriteMethod();//属性名称 pd.getName();//属性类型 pd.getPropertyType();
}

如果属性是boolean的话,get变为isName(),框架也是这么识别的

这篇关于Day12=枚举+注解+反射+类加载器+双亲委派+如何加载配置文件+class对象+反射获取注解+内省的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/558681

相关文章

SpringMVC高效获取JavaBean对象指南

《SpringMVC高效获取JavaBean对象指南》SpringMVC通过数据绑定自动将请求参数映射到JavaBean,支持表单、URL及JSON数据,需用@ModelAttribute、@Requ... 目录Spring MVC 获取 JavaBean 对象指南核心机制:数据绑定实现步骤1. 定义 Ja

Python打印对象所有属性和值的方法小结

《Python打印对象所有属性和值的方法小结》在Python开发过程中,调试代码时经常需要查看对象的当前状态,也就是对象的所有属性和对应的值,然而,Python并没有像PHP的print_r那样直接提... 目录python中打印对象所有属性和值的方法实现步骤1. 使用vars()和pprint()2. 使

nginx启动命令和默认配置文件的使用

《nginx启动命令和默认配置文件的使用》:本文主要介绍nginx启动命令和默认配置文件的使用,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录常见命令nginx.conf配置文件location匹配规则图片服务器总结常见命令# 默认配置文件启动./nginx

C++中RAII资源获取即初始化

《C++中RAII资源获取即初始化》RAII通过构造/析构自动管理资源生命周期,确保安全释放,本文就来介绍一下C++中的RAII技术及其应用,具有一定的参考价值,感兴趣的可以了解一下... 目录一、核心原理与机制二、标准库中的RAII实现三、自定义RAII类设计原则四、常见应用场景1. 内存管理2. 文件操

mapstruct中的@Mapper注解的基本用法

《mapstruct中的@Mapper注解的基本用法》在MapStruct中,@Mapper注解是核心注解之一,用于标记一个接口或抽象类为MapStruct的映射器(Mapper),本文给大家介绍ma... 目录1. 基本用法2. 常用属性3. 高级用法4. 注意事项5. 总结6. 编译异常处理在MapSt

SpringBoot服务获取Pod当前IP的两种方案

《SpringBoot服务获取Pod当前IP的两种方案》在Kubernetes集群中,SpringBoot服务获取Pod当前IP的方案主要有两种,通过环境变量注入或通过Java代码动态获取网络接口IP... 目录方案一:通过 Kubernetes Downward API 注入环境变量原理步骤方案二:通过

MySQL JSON 查询中的对象与数组技巧及查询示例

《MySQLJSON查询中的对象与数组技巧及查询示例》MySQL中JSON对象和JSON数组查询的详细介绍及带有WHERE条件的查询示例,本文给大家介绍的非常详细,mysqljson查询示例相关知... 目录jsON 对象查询1. JSON_CONTAINS2. JSON_EXTRACT3. JSON_TA

C#之List集合去重复对象的实现方法

《C#之List集合去重复对象的实现方法》:本文主要介绍C#之List集合去重复对象的实现方法,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录C# List集合去重复对象方法1、测试数据2、测试数据3、知识点补充总结C# List集合去重复对象方法1、测试数据

springboot加载不到nacos配置中心的配置问题处理

《springboot加载不到nacos配置中心的配置问题处理》:本文主要介绍springboot加载不到nacos配置中心的配置问题处理,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑... 目录springboot加载不到nacos配置中心的配置两种可能Spring Boot 版本Nacos

Java反射实现多属性去重与分组功能

《Java反射实现多属性去重与分组功能》在Java开发中,​​List是一种非常常用的数据结构,通常我们会遇到这样的问题:如何处理​​List​​​中的相同字段?无论是去重还是分组,合理的操作可以提高... 目录一、开发环境与基础组件准备1.环境配置:2. 代码结构说明:二、基础反射工具:BeanUtils