文章目录
1.反射
1.1定义反射:
框架设计的灵魂;什么是框架:是半成品软件,可以在框架的基础上进行软件开发,简化编码;概念:将类的各个组成部分封装成其他对象,这个封装的过程就是反射机制;在运行的过程中,你能够知道任意一个类的所有的属性和方法,这个知道的过程就是反射机制;概念:JAVA反射机制是在运行状态中,对于任意一个实体类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意方法和属性;这种动态获取信息以及动态调用对象方法的功能称为java语言的反射机制。要想 解析一个类,必须先要获取到该类的字节码文件对应的Class类型的对象,而解剖类中的各成分使用的就是Class类中的方法。
1.2java代码的三个阶段
source–>class阶段–》runtime阶段
1.Class.forName(“全类名”);把字节码文件加载到内存;
2.类名.class 通过类名的class属性获取Class对象
3.对象.getClass() 通过对象的getClass()方法获取Class对象;
双亲委派模型:https://blog.csdn.net/u013568373/article/details/93995246
1、启动类加载器(Bootstrap ClassLoader),它是属于虚拟机自身的一部分,用C++实现的,主要负责加载<JAVA_HOME>\lib目录中或被-Xbootclasspath指定的路径中的并且文件名是被虚拟机识别的文件。它等于是所有类加载器的爸爸。
2、扩展类加载器(Extension ClassLoader),它是Java实现的,独立于虚拟机,主要负责加载<JAVA_HOME>\lib\ext目录中或被java.ext.dirs系统变量所指定的路径的类库。
3、应用程序类加载器(Application ClassLoader),它是Java实现的,独立于虚拟机。主要负责加载用户类路径(classPath)上的类库,如果我们没有实现自定义的类加载器那这玩意就是我们程序中的默认加载器
原理:当一个类加载器收到类加载任务时,会先交给自己的父加载器去完成,因此最终加载任务都会传递到最顶层的BootstrapClassLoader,只有当父加载器无法完成加载任务时,才会尝试自己来加载。
具体:根据双亲委派模式,在加载类文件的时候,子类加载器首先将加载请求委托给它的父加载器,父加载器会检测自己是否已经加载过类,如果已经加载则加载过程结束,如果没有加载的话则请求继续向上传递直Bootstrap ClassLoader。如果请求向上委托过程中,如果始终没有检测到该类已经加载,则Bootstrap ClassLoader开始尝试从其对应路劲中加载该类文件,如果失败则由子类加载器继续尝试加载,直至发起加载请求的子加载器为止。
采用双亲委派模式可以保证类型加载的安全性,不管是哪个加载器加载这个类,最终都是委托给顶层的BootstrapClassLoader来加载的,只有父类无法加载自己猜尝试加载,这样就可以保证任何的类加载器最终得到的都是同样一个Object对象。
1.3将类的各个部分封装的对象
1.4获取
1.4.1获取类名
1.4.2获取成员变量
getFields()–>获取所有public修饰的成员变量;
getDeclaredFields()–>不考虑权限修饰符暴力反射概念;
属性.setAccessible(true);
值为 true 则指示反射的对象在使用时应该取消 Java 语言访问检查。值为 false 则指示反射的对象应该实施 Java 语言访问检查;实际上setAccessible是启用和禁用访问安全检查的开关,并不是为true就能访问为false就不能访问 ; // 由于JDK的安全检查耗时较多.所以通过setAccessible(true) 的方式关闭安全检查就可以达到提升反射速度的目的
操作:
获取值:属性.get(对象)
设置值:属性.set(对象,值)
1.4.3获取构造方法
1.4.4获取成员方法
操作方法:
invoke(对象,参数);
方法名.invoke(对象)
取消安全检查(暴力反射)
方法名.setAccessible(true)
1.4.5获取注解
2.注解
2.1概念和作用
注解:说明程序的,给计算机看的;注释:描述程序的,给程序员看的;
作用:
1.用来编写API文档举例:@since @author写一个方法注释使用javadoc生成文档
2.代码分析通过代码里标识的注解可以对代码进行分析,结合反射使用;
3.编译检查通过注解能够实现基本的编译检查;例如@override注解三部分:预定义注解 元注解 自定义注解
2.2预定义注解
@Override :检测被该注解标注的方法是否是继承自父类(接口)的
@Deprecated:该注解标注的内容,表示已过时 举例:方法上标注该注解,然后在另一个方法中去使用,大家看现象;
@SuppressWarnings:压制警告 * 一般传递参数all @SuppressWarnings(“all”),一般写在类上面;
2.3自定义注解定义格式元注解
public @interface 注解名称{
属性列表;
}
定义一个注解然后反编译查看注解的本质
本质
注解的本质就是一个接口,默认继承Annotation接口public interface MyAnno extends java.lang.annotation.Annotation {}
属性
要求如下:
- 属性的返回值类型有下列取值,不能是void必须有返回值,因为返回值就是该属性的数据类型,其他的自定义的引用类型也不可以,比如自定义的Book不可以;
* 基本数据类型
* String
* 枚举
* 注解
以上类型的数组举例
-
定义了属性,在使用时需要给属性赋值;属性就是接口中的抽象方法
- 如果定义属性时,使用default关键字给属性默认初始化值,则使用注解时,可以不进行属性的赋值。
- 如果只有一个属性需要赋值,并且属性的名称是value,则value可以省略,直接定义值即可。
- 数组赋值时,值使用{}包裹。如果数组中只有一个值,则{}可以省略举例
2.4元注解
Target使用属性ElementType
概念
用于描述注解的注解就是元注解举例
@override
@Target(ElementType.METHOD)-->注解作用的位置
@Retention(RetentionPolicy.SOURCE)--》描述注解停留的阶段//source
class runtimepublic @interface Override {}
元素
解析注解
获取注解中定义的属性值
获取任意的类执行该类的方法
注解用来替代配置文件
3、注解与反射案例
写一个注解添加的方法
public class BaseDao<T> {
static {
try {
Class.forName("com.mysql.cj.jdbc.Driver");
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
public int save(T t) throws Exception {
//传过来的对象
Class<?> aClass = t.getClass();
//获取表名
TableName annotation = aClass.getAnnotation(TableName.class);
String name = annotation.name();
//获得属性值
Field[] declaredFields = aClass.getDeclaredFields();
//存列名和值
ArrayList<String> columns = new ArrayList<>();
ArrayList<String> columnvalues = new ArrayList<>();
if(declaredFields.length > 0){
for (Field declaredField : declaredFields) {
//属性值的
TableColumn annotation1 = declaredField.getAnnotation(TableColumn.class);
String name1 = annotation1.value();
// System.out.println("列名"+name1);
columns.add("`"+name1+"`");
//通过属性名.get(对象)获得传过来的对象值
declaredField.setAccessible(true);
Object o = declaredField.get(t);
// System.out.println("当前属性 : "+declaredField+"值 : " + o.toString());
columnvalues.add("'"+o+"'");
}
}
String tablecolumns = columns.toString().replace("[", "(").replace("]", ")");
String tablevalue = columnvalues.toString().replace("[", "(").replace("]", ")");
System.out.println(tablecolumns);
System.out.println(tablecolumns);
String sql = "insert "+ name +tablecolumns+"values"+tablevalue;
System.out.println(sql);
Connection root = DriverManager.getConnection("jdbc:mysql://localhost:3306/casemanage?useUnicode=true&EncodingCharacter=utf-8", "root", "1214521");
PreparedStatement preparedStatement = root.prepareStatement(sql);
int i = preparedStatement.executeUpdate();
return i;
}