元注解
元注解是负责注解其他注解的注解
@Target:用于描述注解的使用范围(即:被描述的注解可以使用在什么地方)(value={可以有多个值})
@Retention:表示需要在什么等级保存该注解信息,用于描述注解的使用周期(SOURCE<CLASS<RUNTIME)
SOURCE:在源文件中可以用,
CLASS:在.class文件有效
RUNTIME:在运行是可以用(重点)
@Document:说明该注解讲被包含在javadoc中
表示该注解是否生成在javadoc文档当中
@Inherited:说明子类可以继承父类中的该注解
自定义注解
@interface
package com.wc.db;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
//注解作用域
@Target(value = {ElementType.TYPE,ElementType.FIELD})
//注解的生命周期
@Retention(RetentionPolicy.RUNTIME)
public @interface MyAnnotaion {
//这个不是方法而是注解的名字注解的类为string
String value();
//注解的默认值是10注解
int age() default 10;
}
反射机制(reflection)
反射机制使java语言是一个准动态的语言
反射机制允许程序在执行期间借助于reflection API获取任何类的内部信息,并能够直接操作任意对象的内部属性及方法
反射相关的主要API:
java.lang.Class:代表一个类
java.lang.reflect.Method:代表类的方法
java.lang.reflect.Field:代表类的方法
java.lang.reflect.Constructor:代表类的构造器
什么叫反射
一个类在内存中只有一个Class对象
一个类被加载后,整个类的结构都会被封装在Class对象中。
基本类型有特殊的获取class对象的方法:
Class 变量名=数据类型.Type;
//一个类咋内存中只有一个class对象
//数据类型对象有特殊的获取class对象的方法
public static void main(String[] args) throws ClassNotFoundException {
Class aClass = Class.forName("com.wc.dao.imp.BookseleImp");
BookseleImp bookseleImp = new BookseleImp();
Class aClass1 = bookseleImp.getClass();
Class bookseleImpClass = BookseleImp.class;
Class type = Integer.TYPE;
System.out.println(type);
System.out.println(aClass.hashCode());
System.out.println(aClass1.hashCode());
System.out.println(bookseleImpClass.hashCode());
}
类加载内存分析
Java内存:
堆:存放new的对象和数组
栈:存放基本变量类型(包含基本类型的具体数值)
引用对象的变量(存放这个引用在对堆里面的具体地址
类执行:静态的属性和代码块那个写在前面那个先执行
类的主动引用
子类被初始化之前会初始化父类:
实例化B(子类对象之前)会实例化父类对象
1.调用父类的静态代码块,2.在调用子类的静态代码块
3.在调用父类的无参构造器,4.在调用子类的无参构造器
package com.cw.demo01;
public class TestDui {
public static void main(String[] args) {
A b = new B();
}
}
class A{
static {
System.out.println("父类静态代码块");
}
public A() {
System.out.println("父类无参");
}
}
class B extends A{
static {
System.out.println("子类静态代码块");
}
static final int c=10;
public B(){
System.out.println("子类无参");
}
}
类的被动引用
通过子类调用父类的静态方法不会初始化子类对象
定义一个子类的数组是,不会给子类对象初始化
调用对象的常量(final)修饰的属性,不会实例化对象(但是如果调用final修饰的方法类会初始化)
public static void main(String[] args) {
B[] b=new B[5];
ArrayList<B> bs = new ArrayList<>();
int b1 = B.b;
int c = B.c;
}
类加载器的作用
源码.java文件–》Java编译器—》字节码文件.class–》类加载器----》字节码校验器—》解释器----》操作系统平台
package com.cw.demo01;
import java.util.ArrayList;
public class TestDui {
public static void main(String[] args) throws ClassNotFoundException {
//获取系统类的加载器
ClassLoader systemClassLoader = ClassLoader.getSystemClassLoader();
//获取类的父类加载器-》扩展加载器
ClassLoader parent = systemClassLoader.getParent();
//获取根加载器,无法直接获取
ClassLoader parent1 = parent.getParent();
//获取当前类加载器
// ClassLoader classLoader = Class.forName("com.cw.demo01.TestDui").getClassLoader();
//获取系统加载器的加载路径
System.out.println(System.getProperty("java.class.path"));
/**
* D:\bangong\Java\jdk-17.0.2\bin\java.exe "-javaagent:
* D:\Program Files\JetBrains\IntelliJ IDEA 2021.3\lib\idea_rt.jar=49832:
* D:\Program Files\JetBrains\IntelliJ IDEA 2021.3\bin" -Dfile.encoding=UTF-8 -classpath
* D:\projects\emp-sys-mgr\target\classes;
* C:\Users\Administrator\.m2\repository\org\apache\logging\log4j\log4j-slf4j-impl\2.17.2\log4j-slf4j-impl-2.17.2.jar;
* C:\Users\Administrator\.m2\repository\org\slf4j\slf4j-api\1.7.25\slf4j-api-1.7.25.jar;
* C:\Users\Administrator\.m2\repository\org\apache\logging\log4j\log4j-api\2.17.2\log4j-api-2.17.2.jar;
* C:\Users\Administrator\.m2\repository\org\apache\logging\log4j\log4j-core\2.17.2\log4j-core-2.17.2.jar com.cw.demo01.TestDui
*/
}
}
反射获取类的属性方法
package com.cw.demo01;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
public class TestDui {
public static void main(String[] args) throws ClassNotFoundException, NoSuchFieldException, NoSuchMethodException {
Class aClass = Class.forName("com.cw.demo01.B");
System.out.println(aClass.getName());//获取路径
System.out.println(aClass.getSimpleName());//获取类名
System.out.println(aClass.getPackageName());//获取包名不加类名
System.out.println(aClass.getTypeName());//获取路径
System.out.println("======");
Field[] fields = aClass.getFields();//获得当前类和父类的所有的public属性
for (Field field : fields) {
System.out.println(field);
}
System.out.println("====");
fields = aClass.getDeclaredFields();//获取当前类的所有属性
for (Field field : fields) {
System.out.println(field);
}
Field insp = aClass.getDeclaredField("insp");//获取当前类的某个属性
System.out.println("======");
Method[] methods = aClass.getMethods();//获得当前类的所有的public方法
for (Method method : methods) {
System.out.println(method);
// Class<?>[] parameterTypes = method.getParameterTypes();获取当前方法的参数
// for (Class<?> parameterType : parameterTypes) {
// System.out.println("++"+parameterType);
// }
Class<?> returnType = method.getReturnType();
System.out.println(returnType+"++");//获取当前方法的返回值类型
}
System.out.println(aClass.getMethod("setId", Integer.class));//获取当前类和父类的指定方法参数为该方法参数类型
System.out.println("=====");
methods = aClass.getDeclaredMethods();//获取当前类所有方法
for (Method method : methods) {
System.out.println(method);
Class<?>[] parameterTypes = method.getParameterTypes();//获取当前方法的参数
for (Class<?> parameterType : parameterTypes) {
System.out.println("++"+parameterType);
}
Class<?> returnType = method.getReturnType();
System.out.println(returnType+"++");//获取当前方法的返回值类型
}
System.out.println("---");
Constructor[] constructors = aClass.getConstructors();//获取当前类的所有public构造器
// for (Constructor constructor : constructors) {
// System.out.println(constructor);
// }
constructors = aClass.getDeclaredConstructors();//获取当前类的所有的构造器
for (Constructor constructor : constructors) {
Class[] parameterTypes = constructor.getParameterTypes();
System.out.println(constructor);
}
}
}
class A {
public Integer no;
private Integer id;
private String name;
public A() {
}
public A(Integer id, String name) {
this.id = id;
this.name = name;
}
private void fun() {
}
public void fun(Integer id) {
}
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
class B extends A {
private Integer insp;
public Integer getInsp() {
return insp;
}
public void setInsp(Integer insp) {
this.insp = insp;
}
public B(Integer id, String name, Integer insp) {
super(id, name);
this.insp = insp;
}
private B(Integer id, String name) {
super(id, name);
}
public B(String s) {
}
public B() {
}
}
创建运行时类对象
通过反射获取方法
方法. invoke(实例化的对象,值);
(方法是getMethod获取方法)
关闭权限检测
setAccessible(true)关闭安全检测可以使用改变私有的方法和属性
package com.cw.demo01;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
public class Demo2 {
public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, InvocationTargetException, IllegalAccessException, InstantiationException {
Class<?> aClass = Class.forName("com.cw.demo01.B");
Constructor<?> declaredConstructor = aClass.getDeclaredConstructor();
String simpleName = aClass.getSimpleName();
System.out.println(simpleName);
B o = (B)declaredConstructor.newInstance();
Method setId = aClass.getMethod("setId", Integer.class);
setId.invoke(o,123);
System.out.println(o.getId());
}
}
setAccessible
使用setAccessible(true)
package com.cw.demo01;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
public class Demo2 {
public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, InvocationTargetException, IllegalAccessException, InstantiationException, NoSuchFieldException {
Class aClass = Class.forName("com.cw.demo01.B");
String simpleName = aClass.getSimpleName();
Constructor declaredConstructor = aClass.getDeclaredConstructor();
B o = (B)declaredConstructor.newInstance();
// o.setInsp(15);
Method setId = aClass.getMethod("setId", Integer.class);
setId.invoke(o,15);
Method getId = aClass.getMethod("getId");
Object invoke = getId.invoke(o);
Field name = aClass.getDeclaredField("insp");
name.setAccessible(true);//使用
name.set(o,20);
System.out.println(o.getInsp());
}
}
反射操作泛型
instanceof判断反射获得类型是否相等
getgenericparametertypes():获取参数的类型
parameterizedType:表示一种参数化类型比如Colection泛型约束
GenericArrayType:表示一种元素类型是参数化类型或者参数化变量的数组类型
TypeVariable:是各种类型变量的公共父接口
WildcardType:代表一种通配符类型表达式
package com.cw.demo01;
import java.lang.reflect.Method;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.HashMap;
import java.util.List;
/**
* 反射获得的参数是否是泛型
*/
public class Demo03 {
public static HashMap<String, Integer> test01(HashMap<String,Demo03> map, List<Integer> list){
return null;
}
public static void main(String[] args) throws NoSuchMethodException {
Class c1 = Demo03.class;
Method t1 = c1.getMethod("test01", HashMap.class, List.class);
//获取方法的形参
Type[] genericParameterTypes = t1.getGenericParameterTypes();
for (Type genericParameterType : genericParameterTypes) {
if (genericParameterType instanceof ParameterizedType) {
Type[] actualTypeArguments = ((ParameterizedType) genericParameterType).getActualTypeArguments();
for (Type actualTypeArgument : actualTypeArguments) {
System.out.println(actualTypeArgument);
}
}
else{
System.out.println(genericParameterType+"else");
}
}
}
}
反射操作注解
注意:反射对象.getAnnotation(注解类)是获取当前对象的注解,
如果想要获得值可以:反射对象.getAnnoataion(注解类).value()------此处的value()就相当于注解的属性
package com.cw.demo01;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
import lombok.ToString;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import java.lang.reflect.Field;
@Setter
@Getter
@NoArgsConstructor
@AllArgsConstructor
@ToString
@Builder
@MyInterface("我的自定义")
public class MyAnnotationRef {
@MyInterfaceTwo("wpde")
private Integer id;
public static void main(String[] args) throws NoSuchFieldException, ClassNotFoundException {
Class c1 = MyAnnotationRef.class;//反射获取类对象
Field id = c1.getDeclaredField("id");//获取类对象的属性
//获取属性的某个值,括号内就是某个值的注解类
MyInterfaceTwo annotation = id.getAnnotation(MyInterfaceTwo.class);
System.out.println(annotation.length());//获取注解的值
System.out.println(annotation.value());
//获取当前类的对象
MyInterface myann = (MyInterface) c1.getAnnotation(MyInterface.class);
//获取类对象的值
System.out.println(myann.value());
}
}
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@interface MyInterface {
String value();
}
@Target({ElementType.FIELD, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@interface MyInterfaceTwo {
String value() default "默认";
int length() default 10;
}