注解
注解分为三类
- 内置注解 @Override @Deprecated @SuppressWarnings
- 元注解 @Target @Documented @Retention @Inherited 等等
- 自定义注解
元注解
@Target
表示在什么地方使用该注解
- ElementType.METHOD 作用于方法上
- ElementType.TYPE 作用于class上
- ElementType.FILED 作用于字段上
- ...
@Retention
表示什么时候该注解会有效
- RetentionPolicy.SOURCE (源码)
- RetentionPolicy.CLASS (编译阶段)
- RetentionPolicy.RUNTIME (运行时)
- 注:RUNTIME > CLASS > SOURCE,选择了RUNTIME,那么CLASS、SOURCE都支持,一般情况下都是RUNTIME
@Documented @Inherited
- @Documented 表示将该注解生成到Java Doc中
- @Inherited 表示子类可以继承父类的注解
自定义注解
定义一个简单的注解
@Target(value = {ElementType.TYPE, ElementType.METHOD})
@Retention(value = RetentionPolicy.RUNTIME)
@interface SimpleAnnotation {
}
定义一个复杂的注解
情况1: 当只有一个参数时,需要把参数名定义为value,这样在使用该注解时可以直接写参数值
@Target(value = {ElementType.TYPE, ElementType.METHOD})
@Retention(value = RetentionPolicy.RUNTIME)
@interface OneParamAnnotation {
String value();
}
@OneParamAnnotation("Kieran")
public class Test {
}
情况2:多个参数,可以设置默认值
@Target(value = {ElementType.TYPE, ElementType.METHOD})
@Retention(value = RetentionPolicy.RUNTIME)
@interface HardAnnotation {
String name() default "";
int age() default 0;
int id() default -1; // -1表示该参数不存在
String[] colors() default {"white","blue"};
}
@HardAnnotation(name = "kieran", id = "75", colors = {"red","green","yellow"})
public class Test {
}
反射
- 一个类在内存中只有一个类的class对象
- 一个类被加载后,类的整个结构都会被封装在class对象中
- 在java中类是获取的,不是创建的
- 获得class的几种方式
A a = new A(); Class<?> c1 = a.getClass();Class<?> c2 = Class.forName("com.xxxxxx.reflection.demo.A);Class<?> c3 = A.class;Class<Integer> c4 = Integer.TYPE;
Person person = new Student();
System.err.println(person.name);
System.err.println("-----");
// 方式一:通过对象获取
Class<? extends Person> c1 = person.getClass();
System.err.println(c1);
System.err.println(c1.hashCode());
System.err.println("-----");
// 方式二: forName获取
Class<?> c2 = Class.forName("com.shinefriends.juc.reflection.Student");
System.err.println(c2);
System.err.println(c2.hashCode());
System.err.println("-----");
// 方式三:通过类名.class获取
Class<Student> c3 = Student.class;
System.err.println(c3);
System.err.println(c3.hashCode());
System.err.println("-----");
// 方式四:基本内置类型的包装类都有一个TYPE属性
Class<Integer> c4 = Integer.TYPE;
System.err.println(c4);
System.err.println(c4.hashCode());
System.err.println("-----");
// 获取父类类型
Class<?> s1 = c1.getSuperclass();
System.err.println(s1);
System.err.println(s1.hashCode());
System.err.println("-----");
Class<?> s2 = c2.getSuperclass();
System.err.println(s2);
System.err.println(s2.hashCode());
System.err.println("-----");
Class<? super Student> s3 = c3.getSuperclass();
System.err.println(s3);
System.err.println(s3.hashCode());
System.err.println("-----");
// superClass与new Class()不一样
Person p = new Person();
System.err.println(p);
System.err.println(p.hashCode());
System.err.println("-----");
5. 所有类型的class
- Class c1 = Object.class; // 类
- Class c2 = Serializable.class; // 接口
- Class c3 = ElementType.class; // 枚举
- Class c4 = Integer.class; // 基本数据类型
- Class c5 = String[].class; // 一维数组
- Class c6 = int[][].class; // 二维数组
- Class c7 = void.class; // void
- Class c8 = override.class; // 注解
- Class c9 = Class.class; // class
- 只要类型相同和维度相同,就是同一个class
int[] i1 = new int[10];
int[] i2 = new int[100];
i1.getClass().hashCode() 等于 i2.getClass().hashCode();
7. 测试类什么时候会被加载(类的加载分为主动和被动)
/**
* 测试类什么时候会初始化
*/
public class Demo5 {
static {
System.err.println("main类被加载");
}
public static void main(String[] args) throws ClassNotFoundException {
// 1.主动引用
// Son son = new Son();
// 1.主动引用 - 反射也会产生主动引用
// Class son = Class.forName("com.shinefriends.juc.reflection.Son");
// 2.被动引用 - 不会发生类的初始化 调用父类的静态变量
// System.err.println(Son.b);
// 2.被动引用 - 初始化数组也不会发生类的初始化 - 此处也不会加载父类,只是给空间命名了,并不会加载一个类
// Son[] son = new Son[5];
// 2.被动引用 - 常量,也不会发生类的初始化
System.err.println(Son.M);
}
}
class Father {
static int b = 2;
static {
System.err.println("父类被加载");
}
}
class Son extends Father {
static {
System.err.println("子类被加载");
index = 300;
}
static int index = 100;
static final int M = 1;
}
类加载器
- 由父类到子类的三个类加载器
- 引导类加载器(根加载器) rt.jar
- 扩展类加载器 ext
- 系统类加载器
- 获取三个类加载器
ClassLoader systemClassLoader = ClassLoader.getSystemClassLoader();ClassLoader extClassLoader = systemClassLoader.getParent();ClassLoader rootClassLoader = extClassLoader.getParent();- 根加载器说明:由于根加载器是由c/c++编写的,因此获取不到,输出为null
- 系统加载器说:输出时AppClassLoader和SystemClassLoader是同一个东西
- 如何获取系统类加载可以加载的路径
System.getProperty("java.class.path");
双亲委派机制
- 比如自己定义了一个 java.lang.String,系统会保证安全性,先到系统类加载器中寻找类String,找不到再到扩展类加载器寻找类String,找不到最后到引导类加载器寻找leiString。如果找到了,则会使用找到的类。
- 1.避免了类的重复加载 2.保护了程序的安全性,防止核心API被修改
动态创建对象,通过反射,设置属性
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
/**
* 动态创建对象,通过反射
*/
public class Demo8 {
public static void main(String[] args) throws ClassNotFoundException,
NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException, NoSuchFieldException {
Class c1 = Class.forName("com.shinefriends.juc.reflection.User");
// 创建个对象,本质是调用了一个无参构造器
User u1 = (User) c1.newInstance();
System.err.println(u1);
// 通过构造器,创建一个对象
User u2 = (User) c1.getDeclaredConstructor(String.class, int.class, int.class).newInstance("pyc", 10, 50);
System.err.println(u2);
// 通过反射获取方法,invoke激活
Method method = c1.getDeclaredMethod("setName", String.class);
method.invoke(u2, "kieran");
System.err.println(u2);
// 通过反射操作属性,不能直接操作私有属性
Field name = c1.getDeclaredField("name");
name.setAccessible(true); // 因为是name是private修饰的,因此需要把操作权限打开
name.set(u2, "基兰");
System.err.println(u2);
}
}
获取类中的各种信息
public class Demo {
psvm {
Class c = Class.forName("com.xxx.User");
// 获取类的名字
c.getName(); // com.xxx.User
c.getSimpleName(); // User
// 获取类的字段,只能获取到public
Field[] fields = c.getFields();
// 获取类的所有字段,包括private
Field[] fields = c.getDeclaredFields();
// 获取类的方法,本类及父类的所有public方法
Method[] methods = c.getMethods();
// 获取类的所有方法,包括private
Method[] methods = c.getDeclaredMethods();
// 获取类的指定方法
Method method = c.getMethod("getName", null);
Method method = c.getMethod("setName", String.class);
// 获取类的默认无参构造器
Constructor constructor = c.getConstructor();
// 获取类的全部公有构造器
Constructor[] constructors = c.getConstructors();
// 获取类的全部构造器,包含私有
Constructor[] constructors = c.getDeclaredConstructors();
// 获取类的指定构造器
Constructor constructor = c.getConstructor(String.class, int.class, int.class);
}
}
获取泛型
public class Demo10 {
public void test1(Map<String, User> map, List<User> list) {
System.err.println("test1");
}
public Map<String, User> test2() {
System.err.println("test2");
return null;
}
public static void main(String[] args) throws NoSuchMethodException {
Method test1 = Demo10.class.getMethod("test1", Map.class, List.class);
Type[] genericParameterTypes = test1.getGenericParameterTypes();
for (Type genericParameterType : genericParameterTypes) {
System.err.println("#" + genericParameterType);
if (genericParameterType instanceof ParameterizedType) {
Type[] actualTypeArguments = ((ParameterizedType) genericParameterType).getActualTypeArguments();
for (Type actualTypeArgument : actualTypeArguments) {
System.err.println("##" + actualTypeArgument);
}
}
}
Method test2 = Demo10.class.getMethod("test2", null);
Class returnType = test2.getReturnType();
System.err.println(returnType);
Type genericReturnType = test2.getGenericReturnType();
System.err.println(genericReturnType);
if (genericReturnType instanceof ParameterizedType) {
for (Type actualTypeArgument : ((ParameterizedType) genericReturnType).getActualTypeArguments()) {
System.err.println("#" + actualTypeArgument);
}
}
}
}
获取注解
public class Demo11 {
public static void main(String[] args) throws ClassNotFoundException {
Class c1 = Class.forName("com.shinefriends.juc.reflection.Air");
Annotation[] annotations = c1.getAnnotations();
for (Annotation annotation : annotations) {
System.err.println(annotation);
}
AirAnno airAnno = (AirAnno) c1.getAnnotation(AirAnno.class);
String value =airAnno.value();
System.err.println(value);
System.err.println("============");
Field[] fields = c1.getDeclaredFields();
for (Field field : fields) {
Annotation[] fa = field.getAnnotations();
for (Annotation annotation : fa) {
System.err.println(annotation);
}
AirField airField = field.getAnnotation(AirField.class);
System.err.println(airField.columnName() + " - " + airField.type() + " - " + airField.length());
}
}
}
@AirAnno(value = "sweet")
class Air {
@AirField(columnName = "id", type = "integer", length = 10)
private int id;
@AirField(columnName = "age", type = "integer", length = 5)
private int age;
@AirField(columnName = "name", type = "varchar", length = 20)
private String name;
public Air() {
}
public Air(int id, int age, 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;
}
@Override
public String toString() {
return "Air{" +
"id=" + id +
", age=" + age +
", name='" + name + ''' +
'}';
}
}
@Target(value = {ElementType.TYPE})
@Retention(value = RetentionPolicy.RUNTIME)
@interface AirAnno {
String value();
}
@Target(value = {ElementType.FIELD})
@Retention(value = RetentionPolicy.RUNTIME)
@interface AirField {
String columnName();
String type();
int length();
}