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

相关文章

Java注解之超越Javadoc的元数据利器详解

《Java注解之超越Javadoc的元数据利器详解》本文将深入探讨Java注解的定义、类型、内置注解、自定义注解、保留策略、实际应用场景及最佳实践,无论是初学者还是资深开发者,都能通过本文了解如何利用... 目录什么是注解?注解的类型内置注编程解自定义注解注解的保留策略实际用例最佳实践总结在 Java 编程

Java 中的 @SneakyThrows 注解使用方法(简化异常处理的利与弊)

《Java中的@SneakyThrows注解使用方法(简化异常处理的利与弊)》为了简化异常处理,Lombok提供了一个强大的注解@SneakyThrows,本文将详细介绍@SneakyThro... 目录1. @SneakyThrows 简介 1.1 什么是 Lombok?2. @SneakyThrows

Java Spring 中 @PostConstruct 注解使用原理及常见场景

《JavaSpring中@PostConstruct注解使用原理及常见场景》在JavaSpring中,@PostConstruct注解是一个非常实用的功能,它允许开发者在Spring容器完全初... 目录一、@PostConstruct 注解概述二、@PostConstruct 注解的基本使用2.1 基本代

SpringBoot整合mybatisPlus实现批量插入并获取ID详解

《SpringBoot整合mybatisPlus实现批量插入并获取ID详解》这篇文章主要为大家详细介绍了SpringBoot如何整合mybatisPlus实现批量插入并获取ID,文中的示例代码讲解详细... 目录【1】saveBATch(一万条数据总耗时:2478ms)【2】集合方式foreach(一万条数

SpringBoot中配置文件的加载顺序解读

《SpringBoot中配置文件的加载顺序解读》:本文主要介绍SpringBoot中配置文件的加载顺序,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录SpringBoot配置文件的加载顺序1、命令⾏参数2、Java系统属性3、操作系统环境变量5、项目【外部】的ap

python获取网页表格的多种方法汇总

《python获取网页表格的多种方法汇总》我们在网页上看到很多的表格,如果要获取里面的数据或者转化成其他格式,就需要将表格获取下来并进行整理,在Python中,获取网页表格的方法有多种,下面就跟随小编... 目录1. 使用Pandas的read_html2. 使用BeautifulSoup和pandas3.

SpringBoot UserAgentUtils获取用户浏览器的用法

《SpringBootUserAgentUtils获取用户浏览器的用法》UserAgentUtils是于处理用户代理(User-Agent)字符串的工具类,一般用于解析和处理浏览器、操作系统以及设备... 目录介绍效果图依赖封装客户端工具封装IP工具实体类获取设备信息入库介绍UserAgentUtils

Java对象转换的实现方式汇总

《Java对象转换的实现方式汇总》:本文主要介绍Java对象转换的多种实现方式,本文通过实例代码给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友参考下吧... 目录Java对象转换的多种实现方式1. 手动映射(Manual Mapping)2. Builder模式3. 工具类辅助映

Spring Boot读取配置文件的五种方式小结

《SpringBoot读取配置文件的五种方式小结》SpringBoot提供了灵活多样的方式来读取配置文件,这篇文章为大家介绍了5种常见的读取方式,文中的示例代码简洁易懂,大家可以根据自己的需要进... 目录1. 配置文件位置与加载顺序2. 读取配置文件的方式汇总方式一:使用 @Value 注解读取配置方式二

Java中的@SneakyThrows注解用法详解

《Java中的@SneakyThrows注解用法详解》:本文主要介绍Java中的@SneakyThrows注解用法的相关资料,Lombok的@SneakyThrows注解简化了Java方法中的异常... 目录前言一、@SneakyThrows 简介1.1 什么是 Lombok?二、@SneakyThrows