一、注解(Annotation)
1.1 作用:
1、不是程序本身,对程序做处解释
2、能被其他程序读取
1.2 内置注解
@Override 重写
@Deprecated 不推荐使用,但是可以使用,或者存在更好的方式
@SuppressWarning 镇压警告
1.3 元注解
负责注解其他注解
@Target 表示注解可以用到哪些地方
@Rentention 表示注解在什么地方才有效 runtime>class>source
@Document 表示是否将注解生成在Javadoc文档中
@Inherited 子类可以继承父类的注解
1.4 自定义注解
1、使用@interface定义
2、可以有参数:参数类型 + 参数名()
3、参数可以设置default默认值,如果没有默认值就必须要给注解赋值;默认值为-1表示不存在
4、如果只有一个参数,可以使用value命名,使用时可以省略参数名
二、反射
通过反射机制实现对元数据(注解)的访问
2.1 java反射机制:
动态语言:在运行时可以根据某些条件改变自身结构
2.2 创建对象的过程
正常创建对象过程:定义一个类,new实例化对象
反射过程:通过对象反射求出类名
2.3 Class类:
- Class类本身是一个类
- 只能由系统建立对象
- 一个加载的类在JVM中只会有一个class实例
- 一个class对象对应一个在JVM中的.class文件
- 每个类的实例都会记得自己是由那个Class实例生成的
- 通过class可以完整地得到一个类中的所有被加载的结构
- Class类是Reflection的根源,针对任何你想动态加载、运行的类,唯有先获得对应的Class对象
2.4 java内存分析
堆:存放new对象和数组,可以被所有线程共享,不会存放别的对象引用
栈:存在基本变量类型(包含这个变量类型的具体数据),引用对象的变量(会存放这个引用在对里面的具体地址)
方法区:可以被所有线程共享,包含所有的class和static变量
2.5 类加载过程:
- 加载:将class文件字节码内容加载到内存中,并将静态数据转成方法区运行 时数据结构,然后生成java.lang.class对象。
- 连接:将java类的二进制代码合并到JVM的运行状态中数据的过程。
- 初始化:<clinit>()方法初始化赋值
2.6 类主动引用(初始化)方法:
- new对象
- 反射
2.7 方法运行顺序:main > 父类 > 子类
2.8 类加载器 ClassLoader
引导类加载器(C/C++编写),根加载器,系统读取不到
扩展类加载器
系统类加载器
自定义类加载器
package com.yans.java.reflect;
public class Test03 {
public static void main(String[] args) throws ClassNotFoundException {
//获取系统类加载器, AppClassLoader
ClassLoader systemClassLoader = ClassLoader.getSystemClassLoader();
System.out.println(systemClassLoader);
//获取系统加载器的父类 --》 扩展类加载器, PlatformClassLoader
ClassLoader parent = systemClassLoader.getParent();
System.out.println(parent);
//获取扩展类加载器的父类 --》根加载器,返回null
ClassLoader parent1 = parent.getParent();
System.out.println(parent1);
//测试当前类是由那个类加载器加载的 AppClassLoader
ClassLoader classLoader = Class.forName("com.yans.java.reflect.Test03").getClassLoader();
System.out.println(classLoader);
//测试JDK内置的类是谁加载的 -> 根加载器, 返回null
ClassLoader classLoader1 = Class.forName("java.lang.String").getClassLoader();
System.out.println(classLoader1);
//如何获得系统类加载器可以加载的路径
System.out.println(System.getProperty("java.class.path"));
//双亲委派机制
//先找用户类加载器-》找到后,然后找扩展类加载器 -》 找到后,然后根加载器,
// 如果根加载器存在,其他加载器定义的就会失效
//自定义一个java.lang.String类,执行会报错找不到,因为根加载器存在了java.lang.String类
}
}
2.9 通过反射获取类信息
package com.yans.java.reflect;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
//获得类信息,通过反射
public class Test04 {
public static void main(String[] args) throws ClassNotFoundException, NoSuchFieldException, NoSuchMethodException {
Class cl = Class.forName("com.yans.java.reflect.User");
//获得类名
System.out.println(cl.getName()); //包名 + 类名
System.out.println(cl.getSimpleName()); //类名
//获得类属性
System.out.println("=======获得属性=====");
Field[] fields = cl.getFields(); //只能找到public属性
fields = cl.getDeclaredFields(); //找到全部属性
for (Field field : fields) {
System.out.println(field);
}
//获得指定属性
System.out.println("=======获得指定属性=====");
//Field name = cl.getField("name"); //只能获得public属性
Field name = cl.getDeclaredField("name");
System.out.println(name);
//获得方法
System.out.println("=======获得方法=====");
Method[] methods = cl.getMethods(); //获得本类及父类所有public方法
for (Method method : methods) {
System.out.println(method);
}
Method[] declaredMethods = cl.getDeclaredMethods();// 获得本类及父类所有所有方法
for (Method method : declaredMethods) {
System.out.println(method);
}
System.out.println("=======获得指定方法=====");
//重载
Method getName = cl.getMethod("getName", null);
System.out.println(getName);
System.out.println("=======获得全部构造器=====");
Constructor[] constructors = cl.getConstructors();
for (Constructor constructor : constructors) {
System.out.println(constructor);
}
System.out.println("=======获得指定构造器=====");
Constructor declaredConstructor = cl.getDeclaredConstructor(String.class, int.class, int.class);
System.out.println(declaredConstructor);
}
}
2.10 通过反射动态创建类
package com.yans.java.reflect;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
//动态创建对象,通过反射
public class Test05 {
public static void main(String[] args) throws ClassNotFoundException, InstantiationException, IllegalAccessException, NoSuchMethodException, InvocationTargetException, NoSuchFieldException {
//获取class对象
Class c1 = Class.forName("com.yans.java.reflect.User");
//构造一个对象
//对象类必须要有无参构造器
//类的访问权限足够
User user1 = (User) c1.newInstance(); //本质是调用无参构造器
System.out.println(user1);
//通过构造器创建对象
Constructor declaredConstructor = c1.getDeclaredConstructor(String.class, int.class, int.class);
User user2 = (User)declaredConstructor.newInstance("jack", 001, 18);
System.out.println(user2);
//通过反射调用普通方法
System.out.println("==================");
User user3 = (User) c1.newInstance();
//通过反射获取一个方法
Method setName = c1.getDeclaredMethod("setName", String.class);
//invoke:激活
//(对象, “方法的值”)
setName.invoke(user3, "jack1");
System.out.println(user3.getName());
//通过反射操作属性
System.out.println("==================");
User user4 = (User) c1.newInstance();
Field name = c1.getDeclaredField("name");
//name属性是private私有的,不能直接操作
//需要关闭安全检查(可以提高效率),通过属性或者方法、构造器的 setAccessible(true) 方法
name.setAccessible(true);
name.set(user4, "jack2");
System.out.println(user4.getName());
}
}
2.11 通过反射获取泛型
package com.yans.java.reflect;
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 Test06 {
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 method = Test06.class.getMethod("test01", Map.class, List.class);
Type[] genericParameterTypes = method.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);
}
}
}
method = Test06.class.getMethod("test02", null);
Type genericReturnType = method.getGenericReturnType(); //获取泛型返回值
Type[] actualTypeArguments = ((ParameterizedType) genericReturnType).getActualTypeArguments(); //获取真实类型
for (Type actualTypeArgument : actualTypeArguments) {
System.out.println(actualTypeArgument);
}
}
}
2.12 通过反射获取注解
package com.yans.java.reflect;
import java.lang.annotation.*;
import java.lang.reflect.Field;
//通过反射获取注解
//ORM 对象关系映射
public class Test07 {
public static void main(String[] args) throws ClassNotFoundException, NoSuchFieldException {
Class c1 = Class.forName("com.yans.java.reflect.Student01");
//获取类的注解
Annotation[] annotations = c1.getAnnotations();
for (Annotation annotation : annotations) {
System.out.println(annotation);
}
//获得注解里value的值
Table table = (Table) c1.getAnnotation(Table.class);
System.out.println(table.value());
//获得属性注解的值
Field f = c1.getDeclaredField("name");
FieldAtrribute annotation = f.getAnnotation(FieldAtrribute.class);
System.out.println(annotation.columName());
System.out.println(annotation.type());
System.out.println(annotation.length());
}
}
@Table("db")
class Student01 {
@FieldAtrribute(columName = "db_id", type = "int", length = 10)
private int id;
@FieldAtrribute(columName = "db_age", type = "int", length = 3)
private int age;
@FieldAtrribute(columName = "db_name", type = "varcahr", length = 60)
private String name;
public Student01() {
}
public Student01(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 "Student01{" +
"id=" + id +
", age=" + age +
", name='" + name + '\'' +
'}';
}
}
//定义一个类的注解
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@interface Table {
String value();
}
//定义属性的注解
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
@interface FieldAtrribute {
String columName();
String type();
int length();
}