注解和反射
注解
注解入门
![]()
内置注解
![]()
package com.lin.demo01;
import java.util.ArrayList;
import java.util.List;
//什么是注解
public class Test01 extends Object{
//@Override 重写的注解
@Override
public String toString() {
return super.toString();
}
//Deprecated不推荐程序员使用,但是可以使用,或者存在更好的方式
@Deprecated
public static void test(){
System.out.println("Deprecated");
}
//SuppressWarnings抑制警告
@SuppressWarnings("all")
public void test02(){
List list = new ArrayList();
}
public static void main(String[] args) {
test();
}
}
元注解
![]()
package com.lin.demo01;
import java.lang.annotation.*;
//测试元注解
@MyAnnotation
public class Test02 {
@MyAnnotation
public void test(){}
}
//定义一个注解
//@Target表示注解可以用在什么地方
//ElementType.METHOD用在方法上 ElementType.TYPE用在类上
@Target(value = {ElementType.METHOD,ElementType.TYPE})
//@Retention表示注解在哪里有效
//runtime>class>source
@Retention(value = RetentionPolicy.RUNTIME)
//Documented:表示是否将注解生成在Javadoc中
@Documented
//@Inherited子类可以继承父类中的该注解
@Inherited
@interface MyAnnotation{
}
自定义注解
![]()
package com.lin.demo01;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
//自定义注解
public class Test03 {
//注解可以显示赋值,如果没有默认值,就必须给注解赋值
@MyAnnotation2(name = "张三")
public void test(){}
@MyAnnotation3("李四")
public void test2(){}
}
@Target({ElementType.TYPE,ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@interface MyAnnotation2{
//注解的参数:参数类型 + 参数名();
String name() default "";
int age() default 0;
int id() default -1;//如果默认值为-1,代表不存在
String[] school()default {"东北大学","清华大学"};
}
@Target({ElementType.TYPE,ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@interface MyAnnotation3{
//只有一个参数时,命名为value在使用时可以省略参数名。
String value();
}
反射机制
Java反射机制概述
静态 & 动态语言
![]()
反射机制概念
![]()
反射机制研究与应用
![]()
反射机制优缺点
![]()
反射相关主要API
![]()
package com.lin.reflection;
//什么叫反射
public class Test02 extends Object{
public static void main(String[] args) throws ClassNotFoundException {
//通过反射获取类的class对象
Class c1 = Class.forName("com.lin.reflection.User");
System.out.println(c1);//class com.lin.reflection.User
Class c2 = Class.forName("com.lin.reflection.User");
Class c3 = Class.forName("com.lin.reflection.User");
Class c4 = Class.forName("com.lin.reflection.User");
//一个类在内存中只有一个Class对象
//一个类被加载后,类的整个结构都会被封装在Class对象中
System.out.println(c2.hashCode());//460141958
System.out.println(c3.hashCode());//460141958
System.out.println(c4.hashCode());//460141958
}
}
//实体类:pojo,entity
class User{
private String name;
private int id;
private int age;
public User() {
}
public User(String name, int id, int age) {
this.name = name;
this.id = id;
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = 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;
}
@Override
public String toString() {
return "User{" +
"name='" + name + '\'' +
", id=" + id +
", age=" + age +
'}';
}
}
理解Class类并获取Class实例
Class类
![]()
![]()
Class类的常用方法
![]()
获取Class类的实例
![]()
package com.lin.reflection;
import com.sun.scenario.effect.impl.sw.sse.SSEBlend_SRC_OUTPeer;
import com.sun.xml.internal.ws.api.model.wsdl.WSDLOutput;
//测试Class类的创建方式
public class Test03 {
public static void main(String[] args) throws ClassNotFoundException {
Person person = new Student();
System.out.println("这个人是:"+person.name);
//方式1:通过对象获得
Class c1 = person.getClass();
System.out.println(c1.hashCode());
//方式2:forName获得
Class c2 = Class.forName("com.lin.reflection.Student");
System.out.println(c2.hashCode());
//方式3:通过类名.class获得
Class c3 = Student.class;
System.out.println(c3.hashCode());
//方式4:基本内置类型的包装类都有一个Type属性
Class c4 = Integer.TYPE;
System.out.println(c4);//int
//获得父类类型
Class c5 = c1.getSuperclass();
System.out.println(c5);//class com.lin.reflection.Person
}
}
class Person{
String name;
public Person() {
}
public Person(String name) {
this.name = name;
}
@Override
public String toString() {
return "Person{" +
"name='" + name + '\'' +
'}';
}
}
class Student extends Person{
public Student(){
this.name = "学生";
}
}
class Teacher extends Person{
public Teacher(){
this.name = "老师";
}
}
哪些类型可以有Class对象
![]()
package com.lin.reflection;
import java.lang.annotation.ElementType;
//所有类型的Class
public class Test04 {
public static void main(String[] args) {
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);//class java.lang.Object
System.out.println(c2);//interface java.lang.Comparable
System.out.println(c3);//class [Ljava.lang.String;
System.out.println(c4);//class [[I
System.out.println(c5);//interface java.lang.Override
System.out.println(c6);//class java.lang.annotation.ElementType
System.out.println(c7);//class java.lang.Integer
System.out.println(c8);//void
System.out.println(c9);//class java.lang.Class
//只要元素类型与维度一样,就是同一个Class
int[] a = new int[10];
int[] b = new int[100];
System.out.println(a.getClass().hashCode());
System.out.println(b.getClass().hashCode());
}
}
类的加载与ClassLoader
Java内存分析
![]()
类的加载
![]()
![]()
package com.lin.reflection;
import com.sun.scenario.effect.impl.sw.sse.SSEBlend_SRC_OUTPeer;
public class Test05 {
public static void main(String[] args) {
A a = new A();
System.out.println(A.m);
/**
* 1. 加载到内存,会产生一个类对应Class对象
* 2. 链接,连接结束后m=0
* 3. 初始化
* <clinit>(){
* System.out.println("A类静态代码块初始化");
* m = 300;
* m = 100;
* }
*/
}
}
class A{
static{
System.out.println("A类静态代码块初始化");
m = 300;
}
static int m = 100;
public A() {
System.out.println("A类无参构造初始化");
}
}
![]()
![]()
什么时候发生类初始化
![]()
package com.lin.reflection;
import java.io.OutputStream;
//测试类什么时候会初始化
public class Test06 {
static {
System.out.println("main类被加载");
}
public static void main(String[] args) throws ClassNotFoundException {
//1.主动引用
//Son son = new Son();//main类被加载 父类被加载 子类被加载
//反射也会产生主动引用
//Class.forName("com.lin.reflection.Son");//main类被加载 父类被加载 子类被加载
//不会产生类的引用的方法
//System.out.println(Son.b);//main类被加载 父类被加载 2
Son[] array = new Son[5];//main类被加载
}
}
class Father{
static int b =2;
static{
System.out.println("父类被加载");
}
}
class Son extends Father{
static{
System.out.println("子类被加载");
m=300;
}
static int m = 100;
static final int M = 1;
}
类加载器的作用
![]()
![]()
package com.lin.reflection;
public class Test07 {
public static void main(String[] args) throws ClassNotFoundException {
//获取系统类的加载器
ClassLoader systemClassLoader = ClassLoader.getSystemClassLoader();
System.out.println(systemClassLoader);//sun.misc.Launcher$AppClassLoader@18b4aac2
//获取系统类加载器的父类加载器---->扩展类加载器
ClassLoader parent = systemClassLoader.getParent();
System.out.println(parent);//sun.misc.Launcher$ExtClassLoader@1b6d3586
//获取扩展类加载器的父类加载器--->根加载器
ClassLoader parent1 = parent.getParent();
System.out.println(parent1);//null
//测试当前类是那个加载器加载的
ClassLoader classLoader = Class.forName("com.lin.reflection.Test07").getClassLoader();
System.out.println(classLoader);//sun.misc.Launcher$AppClassLoader@18b4aac2
//测试jdk内置的类是谁加载的
ClassLoader classLoader1 = Class.forName("java.lang.Object").getClassLoader();
System.out.println(classLoader1);//null根加载器无法直接获取
//如何获得系统类加载器可以加载的路径
System.out.println(System.getProperty("java.class.path"));
//双亲委派机制
//java.lang.String--->往上推,如果类加载器、扩展类加载器、根加载器有这个包,不会使用自己定义的包,保证安全性
/**
* C:\Program Files\Java\jdk1.8.0_271\jre\lib\charsets.jar;
* C:\Program Files\Java\jdk1.8.0_271\jre\lib\deploy.jar;
* C:\Program Files\Java\jdk1.8.0_271\jre\lib\ext\access-bridge-64.jar;
* C:\Program Files\Java\jdk1.8.0_271\jre\lib\ext\cldrdata.jar;
* C:\Program Files\Java\jdk1.8.0_271\jre\lib\ext\dnsns.jar;
* C:\Program Files\Java\jdk1.8.0_271\jre\lib\ext\jaccess.jar;
* C:\Program Files\Java\jdk1.8.0_271\jre\lib\ext\jfxrt.jar;
* C:\Program Files\Java\jdk1.8.0_271\jre\lib\ext\localedata.jar;
* C:\Program Files\Java\jdk1.8.0_271\jre\lib\ext\nashorn.jar;
* C:\Program Files\Java\jdk1.8.0_271\jre\lib\ext\sunec.jar;
* C:\Program Files\Java\jdk1.8.0_271\jre\lib\ext\sunjce_provider.jar;
* C:\Program Files\Java\jdk1.8.0_271\jre\lib\ext\sunmscapi.jar;
* C:\Program Files\Java\jdk1.8.0_271\jre\lib\ext\sunpkcs11.jar;
* C:\Program Files\Java\jdk1.8.0_271\jre\lib\ext\zipfs.jar;
* C:\Program Files\Java\jdk1.8.0_271\jre\lib\javaws.jar;
* C:\Program Files\Java\jdk1.8.0_271\jre\lib\jce.jar;
* C:\Program Files\Java\jdk1.8.0_271\jre\lib\jfr.jar;
* C:\Program Files\Java\jdk1.8.0_271\jre\lib\jfxswt.jar;
* C:\Program Files\Java\jdk1.8.0_271\jre\lib\jsse.jar;
* C:\Program Files\Java\jdk1.8.0_271\jre\lib\management-agent.jar;
* C:\Program Files\Java\jdk1.8.0_271\jre\lib\plugin.jar;
* C:\Program Files\Java\jdk1.8.0_271\jre\lib\resources.jar;
* C:\Program Files\Java\jdk1.8.0_271\jre\lib\rt.jar;
* D:\Javaworkspace\Annotation\out\production\Annotation;
* D:\IntelliJ IDEA\lib\idea_rt.jar
*/
}
}
获取运行时类的完整结构
![]()
package com.lin.reflection;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
//获得类的信息
public class Test08 {
public static void main(String[] args) throws ClassNotFoundException, NoSuchFieldException, NoSuchMethodException {
Class c1 = Class.forName("com.lin.reflection.User");
//User user = new User();
//c1 = user.getClass();
//获得类的名字
System.out.println(c1.getName());//获得包名 + 类名 com.lin.reflection.User
System.out.println(c1.getSimpleName());//获得类名 User
//获得类的属性
System.out.println("=========");
Field[] fields = c1.getFields();//只能找到public属性
fields = c1.getDeclaredFields();//找到全部的属性
for (Field field : fields) {
System.out.println(field);
}
/**
* private java.lang.String com.lin.reflection.User.name
* private int com.lin.reflection.User.id
* private int com.lin.reflection.User.age
*/
//获得指定属性的值
Field name = c1.getDeclaredField("name");
System.out.println(name);//private java.lang.String com.lin.reflection.User.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("Declared:"+method);
}
//获得指定方法
//重载
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();//获得public构造器
for (Constructor constructor : constructors) {
System.out.println(constructor);
}
constructors = c1.getDeclaredConstructors();//获得本类所有构造器
for (Constructor constructor : constructors) {
System.out.println("*"+constructor);
}
//获得指定的构造器
Constructor constructor = c1.getConstructor(String.class, int.class, int.class);
System.out.println("指定:"+constructor);
}
}
![]()
调用运行时类的指定结构
有了clss对象能做什么
![]()
package com.lin.reflection;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
//动态创建对象,通过反射
public class Test09 {
public static void main(String[] args) throws ClassNotFoundException, InstantiationException, IllegalAccessException, NoSuchMethodException, InvocationTargetException, NoSuchFieldException {
//获得Class对象
Class c1 = Class.forName("com.lin.reflection.User");
//构造一个对象
User user = (User)c1.newInstance();//本质上调用了类的无参构造器
System.out.println(user);//User{name='null', id=0, age=0}
//通过构造器创建对象
Constructor constructor = c1.getDeclaredConstructor(String.class, int.class, int.class);
User user2 = (User)constructor.newInstance("张三", 001, 18);
System.out.println(user2);
//通过反射调用普通方法
User user3 = (User)c1.newInstance();
//通过反射获取一个方法
Method setName = c1.getDeclaredMethod("setName", String.class);
//invoke:激活(对象,"方法的值")
setName.invoke(user3,"李四");
System.out.println(user3.getName());
//通过反射操作属性
User user4 = (User)c1.newInstance();
Field name = c1.getDeclaredField("name");
//不能直接操作私有属性,我们需要关闭程序的安全检测,属性或方法的setAccessible(true)
name.setAccessible(true);
name.set(user4,"王五");
System.out.println(user4.getName());
}
}
![]()
调用指定的方法
![]()
![]()
setAccessible
![]()
性能检测
package com.lin.reflection;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
//分析性能问题
public class Test10 {
//普通方式调用
public static void Test01(){
User user = new User();
long startTime = System.currentTimeMillis();
for (int i = 0; i < 1000000000; i++) {
user.getName();
}
long endTime = System.currentTimeMillis();
System.out.println("普通方法执行十亿次:"+(endTime-startTime)+"ms");
}
//反射方式调用
public static void Test02() throws NoSuchMethodException, InvocationTargetException, IllegalAccessException {
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);
}
long endTime = System.currentTimeMillis();
System.out.println("反射方法执行十亿次:"+(endTime-startTime)+"ms");
}
//反射方式调用 关闭检测
public static void Test03() throws NoSuchMethodException, InvocationTargetException, IllegalAccessException {
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);
}
long endTime = System.currentTimeMillis();
System.out.println("反射方法关闭检测执行十亿次:"+(endTime-startTime)+"ms");
}
public static void main(String[] args) throws NoSuchMethodException, IllegalAccessException, InvocationTargetException {
Test01();
Test02();
Test03();
}
}
![]()
反射操作泛型
![]()
package com.lin.reflection;
import java.lang.reflect.Method;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.List;
import java.util.Map;
//通过反射获取泛型
public class Test11 {
public void test01(Map<String,User> map, List<User> list){
System.out.println("test01");
}
public Map<String,User> test02(){
System.out.println("test02");
return null;
}
public static void main(String[] args) throws NoSuchMethodException {
Method method01 = Test11.class.getMethod("test01", Map.class, List.class);//返回方法
Type[] genericParameterTypes = method01.getGenericParameterTypes();//获得泛型参数类型
for (Type genericParameterType : genericParameterTypes) {
System.out.println(genericParameterType);//打印泛型参数类型
if(genericParameterType instanceof ParameterizedType){//泛型参数类型是否是参数化类型
Type[] actualTypeArguments = ((ParameterizedType) genericParameterType).getActualTypeArguments();//强转调用方法获得真实参数信息
for (Type actualTypeArgument : actualTypeArguments) {
System.out.println(actualTypeArgument);//打印真实参数信息
}
}
}
/**
* java.util.Map<java.lang.String, com.lin.reflection.User>
* class java.lang.String
* class com.lin.reflection.User
* java.util.List<com.lin.reflection.User>
* class com.lin.reflection.User
*/
Method method02 = Test11.class.getMethod("test02",null);//返回方法
Type genericReturnType = method02.getGenericReturnType();//获取返回值泛型参数
if(genericReturnType instanceof ParameterizedType) {//泛型参数类型是否是参数化类型
Type[] actualTypeArguments = ((ParameterizedType) genericReturnType).getActualTypeArguments();//强转调用方法获得真实参数信息
for (Type actualTypeArgument : actualTypeArguments) {
System.out.println(actualTypeArgument);//打印真实参数信息
}
}
/**
* class java.lang.String
* class com.lin.reflection.User
*/
}
}
反射操作注解
![]()
![]()
package com.lin.reflection;
import java.lang.annotation.*;
import java.lang.reflect.Field;
//练习反射操作注解
public class Test12 {
public static void main(String[] args) throws ClassNotFoundException, NoSuchFieldException {
Class c1 = Class.forName("com.lin.reflection.Student2");
//通过反射获得注解
Annotation[] annotations = c1.getAnnotations();
for (Annotation annotation : annotations) {
System.out.println(annotation);//@com.lin.reflection.TableName(value=db_student)
}
//获得注解的value的值
TableName tableName = (TableName)c1.getAnnotation(TableName.class);
String value = tableName.value();
System.out.println(value);//db_student
//获得类指定的注解
Field f = c1.getDeclaredField("name");
FiledName annotation = f.getAnnotation(FiledName.class);
System.out.println(annotation.columnName());//db_name
System.out.println(annotation.type());//varchar
System.out.println(annotation.length());//3
}
}
@TableName("db_student")
class Student2{
@FiledName(columnName = "db_id",type = "int",length = 10)
private int id;
@FiledName(columnName = "db_age",type = "int",length = 10)
private int age;
@FiledName(columnName = "db_name",type = "varchar",length = 3)
private String name;
public Student2() {
}
public Student2(int id, int age, String name) {
this.id = id;
this.age = age;
this.name = 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;
}
@Override
public String toString() {
return "Student2{" +
"id=" + id +
", age=" + age +
", name='" + name + '\'' +
'}';
}
}
//类名的注解
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@interface TableName{
String value();
}
//属性的注解
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
@interface FiledName{
String columnName();
String type();
int length();
}