目录
一、注解
1、内置注解
@Override | 注解在方法上 表示重写父类方法,编译时期报错,提高可读性 |
@Deprecated | 注解在方法上 表示方法已经过时 |
@SuppressWarning | 注解在类或方法或变量上 忽略指定的警告 |
2、元注解
@Target 表示我们的注解可以用在哪些地方 @Retention 表示我们的注解在什么地方才有效 runtime>class>sources @Document 表示是否将我们的注解生成在JAVAdoc中 @Inherited 子类可以继承父类的注解
package com.wxl.springbootpro01;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Test.MyAnnotation
public class Test {
@org.junit.jupiter.api.Test
public void test(){
}
@MyAnnotation
public void method(){
}
//定义一个注解
//Target 表示我们的注解可以用在哪些地方
@Target(value={ElementType.METHOD,ElementType.TYPE})
//Retention 表示我们的注解在什么地方才有效
//runtime>class>sources
@Retention(value = RetentionPolicy.RUNTIME)//运行时有效
@interface MyAnnotation{
}
}
3、自定义注解
package com.wxl.springbootpro01;
import java.lang.annotation.*;
//自定义注解
public class Test {
@org.junit.jupiter.api.Test
public void test(){
}
//注解可以显示赋值,如果没有默认值,我们就必须给注解赋值
@MyAnnotation(name="Jack",schools = {"撤犊子大学"})
public void method(){
}
@MyAnnotation2("Jack")
public void method2(){
}
@Target({ElementType.TYPE,ElementType.METHOD})//作用域
@Retention(RetentionPolicy.RUNTIME)//运行时生效
@interface MyAnnotation{
//注解的参数:参数类型+参数名();
String name() default "";
int age() default 0;
int id() default -1;//如果默认值为-1,代表不存在,类似于indexof,如果找不到就返回-1
String[] schools() default {"清华大学"};
}
@Target({ElementType.TYPE,ElementType.METHOD})//作用域
@Retention(RetentionPolicy.RUNTIME)//运行时生效
@interface MyAnnotation2{
String value();//如果只有一个值建议使用value命名,赋值时可省略value
}
}
二、反射
1、什么是反射(Reflection )?
主要是指程序可以访问、检测和修改它本身状态或行为的一种能力。
2、反射可以实现的功能
Java 反射机制主要提供了以下功能,这些功能都位于java.lang.reflect
包。
- 在运行时判断任意一个对象所属的类。
- 在运行时构造任意一个类的对象。
- 在运行时判断任意一个类所具有的成员变量和方法。
- 在运行时调用任意一个对象的方法。
- 生成动态代理。
3、反射常用方法
利用 Class 类的对象 labelCls 可以访问 labelCls 对象的描述信息、JLabel 类的信息以及基类 Object 的信息。表 1 列出了通过反射可以访问的信息。
类型 | 访问方法 | 返回值类型 | 说明 |
---|---|---|---|
包路径 | getPackage() | Package 对象 | 获取该类的存放路径 |
类名称 | getName() | String 对象 | 获取该类的名称 |
继承类 | getSuperclass() | Class 对象 | 获取该类继承的类 |
实现接口 | getlnterfaces() | Class 型数组 | 获取该类实现的所有接口 |
构造方法 | getConstructors() | Constructor 型数组 | 获取所有权限为 public 的构造方法 |
getDeclaredContruectors() | Constructor 对象 | 获取当前对象的所有构造方法 | |
方法 | getMethods() | Methods 型数组 | 获取所有权限为 public 的方法 |
getDeclaredMethods() | Methods 对象 | 获取当前对象的所有方法 | |
成员变量 | getFields() | Field 型数组 | 获取所有权限为 public 的成员变量 |
getDeclareFileds() | Field 对象 | 获取当前对象的所有成员变量 | |
内部类 | getClasses() | Class 型数组 | 获取所有权限为 public 的内部类 |
getDeclaredClasses() | Class 型数组 | 获取所有内部类 | |
内部类的声明类 | getDeclaringClass() | Class 对象 | 如果该类为内部类,则返回它的成员类,否则返回 null |
测试案例1:类地址等测试
package com.wxl.springbootpro01;
import java.lang.annotation.ElementType;
//什么叫反射
public class Test {
@org.junit.jupiter.api.Test
public void test() throws ClassNotFoundException {
//通过反射获取类的Class对象
Class c1 = Class.forName("com.wxl.springbootpro01.Test");
System.out.println(c1);
//一个类在内存中只有一个Class对象
//一个类被加载后,类的整个结构都会被封装在Class对象中。
}
//测试Class类的创建方式有哪些
@org.junit.jupiter.api.Test
public void test2() throws ClassNotFoundException {
User user = new User();
user.setName("Jack");
System.out.println(user.getName());
//方式一:通过对象获得
Class c1 = user.getClass();
System.out.println(c1.hashCode());
//方式二:forName获得
Class c2 = Class.forName("com.wxl.springbootpro01.User");
System.out.println(c2.hashCode());
//方式三:通过类名.class获得
Class c3 = User.class;
System.out.println(c3.hashCode());
//方式四:基本内置类型的包装类都有一个Type属性
Class c4 = Integer.TYPE;
System.out.println(c4);
//获得父类类型
Class c5 = c1.getSuperclass();
System.out.println(c5);
//运行测试可以看到地址都一样为对象的地址
// Jack
// 1582785598
// 1582785598
// 1582785598
}
@org.junit.jupiter.api.Test
public void test3() {
Class c1 = Object.class;//类
Class c2 = Comparable.class;//接口
Class c3 = String[].class;//一维数组
Class c4 = int[][].class;//二维数组
Class c5 = Override.class;//注解
Class c6 = ElementType.class;//枚举
Class c7 = Integer.class;//基本数据类型
Class c8 = void.class;//void
Class c9 = Class.class;//Class
System.out.println(c1);
System.out.println(c2);
System.out.println(c3);
System.out.println(c4);
System.out.println(c5);
System.out.println(c6);
System.out.println(c7);
System.out.println(c8);
System.out.println(c9);
// class java.lang.Object
// interface java.lang.Comparable
// class [Ljava.lang.String;
// class [[I
// interface java.lang.Override
// class java.lang.annotation.ElementType
// class java.lang.Integer
// void
// class java.lang.Class
//只要元素类型与维度一样,就是同一个Class
}
}
class User {
private String name;
private int age;
private String sex;
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;
}
public String getSex() {
return sex;
}
public void setSex(String sex) {
this.sex = sex;
}
@Override
public String toString() {
return "User{" +
"name='" + name + '\'' +
", age=" + age +
", sex='" + sex + '\'' +
'}';
}
}
测试案例2:类的相关属性和方法的查看
package com.wxl.springbootpro01;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
public class Test {
//获得类的信息
@org.junit.jupiter.api.Test
public void test() throws ClassNotFoundException, NoSuchFieldException, NoSuchMethodException {
Class c1 = Class.forName("com.wxl.springbootpro01.User");
//获得类的名字
System.out.println(c1.getName());//获得包名+类名
System.out.println(c1.getSimpleName());//获得类名
//获得类的属性
System.out.println("====================");
Field[] fields = c1.getFields();//只能找到public属性
fields = c1.getDeclaredFields();//找到全部的属性
for (Field field : fields) {
System.out.println(field);
}
//获得指定属性的值
Field name = c1.getDeclaredField("name");
System.out.println(name);
//获得类的方法
System.out.println("============================");
Method[] methods = c1.getMethods();//获取本类及其父类的全部public方法
for (Method method : methods) {
System.out.println("正常的" + method);
}
methods = c1.getDeclaredMethods();//获取本类的所有方法
for (Method method : methods) {
System.out.println("getDeclaredMethods" + method);
}
//获得指定方法
//重载
System.out.println("==========================");
Method getName = c1.getMethod("getName", null);
Method setName = c1.getMethod("setName", String.class);
System.out.println(getName);
System.out.println(setName);
//获得指定的构造器
System.out.println("=============================");
Constructor[] constructors = c1.getConstructors();
for (Constructor constructor : constructors) {
System.out.println(constructor);
}
constructors = c1.getDeclaredConstructors();
for (Constructor constructor : constructors) {
System.out.println("###" + constructor);
}
//获取指定的构造器
Constructor declaredConstructor=c1.getDeclaredConstructor(String.class,int.class);
System.out.println("指定:"+declaredConstructor);
}
}
class User {
private String name;
private int age;
public String getName() {
return name;
}
public User() {
}
public User(String name, int age) {
this.name = name;
this.age = age;
}
public void setName(String name) {
this.name = name;
}
@Override
public String toString() {
return "User{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
private void show() {
System.out.println("how are you");
}
}
测试案例3:通过反射动态操作对象及方法
package com.wxl.springbootpro01;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
public class Test {
//动态的创建对象,通过反射
@org.junit.jupiter.api.Test
public void test() throws ClassNotFoundException, NoSuchFieldException, NoSuchMethodException, IllegalAccessException, InstantiationException, InvocationTargetException {
//获得Class对象
Class c1 = Class.forName("com.wxl.springbootpro01.User");
//构造一个对象
User user = (User) c1.newInstance();//本质是调用了类的无参构造器
System.out.println(user);
//通过构造器创建对象
Constructor constructor = c1.getDeclaredConstructor(String.class, int.class);
User user2 = (User) constructor.newInstance("dragon", 233);
System.out.println(user2);
//通过反射调用普通方法
User user3 = (User) c1.newInstance();
//通过反射获取一个方法
Method setName = c1.getDeclaredMethod("setName", String.class);
//invoke:激活的意思
//(对象,”方法的值“)
setName.invoke(user3, "dragon wu");
System.out.println(user3.getName());
//通过反射操作属性
System.out.println("===============================");
User user4 = (User) c1.newInstance();
Field name = c1.getDeclaredField("name");
//不能直接操作私有属性,我们需要关闭程序的安全检测,属性或方法的setAccessible(true).
name.setAccessible(true);
name.set(user4, "dragon wu");
System.out.println(user4.getName());
}
}
class User {
private String name;
private int age;
public User() {
}
public User(String name, int age) {
this.name = name;
this.age = age;
}
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;
}
}
测试案例4:反射操作与普通操作速度对比
package com.wxl.springbootpro01;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
public class Test {
//普通方式调用
@org.junit.jupiter.api.Test
public void test() throws ClassNotFoundException, NoSuchFieldException, NoSuchMethodException, IllegalAccessException, InstantiationException, InvocationTargetException {
User user = new User();
long startTime = System.currentTimeMillis();
for (int i = 0; i < 1000000000; i++) {
user.getName();
}
long endTime = System.currentTimeMillis();
System.out.println("普通方式执行10亿次:" + (endTime - startTime) + "ms");
}
//反射方法调用
@org.junit.jupiter.api.Test
public void test2() throws ClassNotFoundException, NoSuchFieldException, NoSuchMethodException, IllegalAccessException, InstantiationException, InvocationTargetException {
User user = new User();
Class c1 = user.getClass();
Method getName = c1.getDeclaredMethod("getName", null);
long startTime = System.currentTimeMillis();
for (int i = 0; i < 1000000000; i++) {
getName.invoke(user, null);
}
long endTime = System.currentTimeMillis();
System.out.println("反射方式执行10亿次:" + (endTime - startTime) + "ms");
}
//反射方法调用 关闭检测
@org.junit.jupiter.api.Test
public void test3() throws ClassNotFoundException, NoSuchFieldException, NoSuchMethodException, IllegalAccessException, InstantiationException, InvocationTargetException {
User user = new User();
Class c1 = user.getClass();
Method getName = c1.getDeclaredMethod("getName", null);
getName.setAccessible(true);
long startTime = System.currentTimeMillis();
for (int i = 0; i < 1000000000; i++) {
getName.invoke(user, null);
}
long endTime = System.currentTimeMillis();
System.out.println("关闭检测,反射方式执行10亿次:" + (endTime - startTime) + "ms");
}
@org.junit.jupiter.api.Test
public void test5() throws NoSuchMethodException, IllegalAccessException, NoSuchFieldException, InstantiationException, InvocationTargetException, ClassNotFoundException {
test();
test2();
test3();
}
}
class User {
private String name;
private int age;
public User() {
}
public User(String name, int age) {
this.name = name;
this.age = age;
}
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;
}
}
测试案例5:注解与反射操作,框架底层逻辑
package com.wxl.springbootpro01;
import java.lang.annotation.*;
import java.lang.reflect.Field;
//练习反射操作注解
public class Test {
@org.junit.jupiter.api.Test
public void test() throws ClassNotFoundException, NoSuchFieldException {
Class c1=Class.forName("com.wxl.springbootpro01.Student");
//通过反射获得注解
Annotation[] annotations=c1.getAnnotations();
for(Annotation annotation:annotations){
System.out.println(annotation);
}
//获得注解的value的值
StudentTable studentTable=(StudentTable) c1.getAnnotation(StudentTable.class);
String value=studentTable.value();
System.out.println(value);
//获得类指定的注解
Field f=c1.getDeclaredField("name");
FieldStudent annotation=f.getAnnotation(FieldStudent.class);
System.out.println(annotation.columnName());
System.out.println(annotation.type());
System.out.println(annotation.length());
}
}
@StudentTable("db_student")
class Student{
@FieldStudent(columnName = "db_id",type = "int",length = 10)
private int id;
@FieldStudent(columnName = "db_age",type = "int",length = 10)
private int age;
@FieldStudent(columnName = "db_name",type = "varchar",length = 10)
private String name;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
//类名的注解
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@interface StudentTable{
String value();
}
//属性的注解
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
@interface FieldStudent{
String columnName();
String type();
int length();
}