目录
1.注解
Annotation是JDK5.0开始引入的新技术。
1.1内置注解:
1.2元注解:
元注解的作用是负责注解其他注解 。
@Retention:表示需要在什么级别保存该注释信息,用于描述注解的生命周期
(source(注解在程序是源代码.java的时候会被识别) < class(注解在程序是字节码文件.class的时候可以被识别) < runtime(注解在程序运行时可以被识别))
@Target表示我们的注解可以使用在什么地方。
枚举ElementType如下:
package java.lang.annotation;
/**
* The constants of this enumerated type provide a simple classification of the
* syntactic locations where annotations may appear in a Java program. These
* constants are used in {@link Target java.lang.annotation.Target}
* meta-annotations to specify where it is legal to write annotations of a
* given type.
*
* <p>The syntactic locations where annotations may appear are split into
* <em>declaration contexts</em> , where annotations apply to declarations, and
* <em>type contexts</em> , where annotations apply to types used in
* declarations and expressions.
*
* <p>The constants {@link #ANNOTATION_TYPE} , {@link #CONSTRUCTOR} , {@link
* #FIELD} , {@link #LOCAL_VARIABLE} , {@link #METHOD} , {@link #PACKAGE} ,
* {@link #PARAMETER} , {@link #TYPE} , and {@link #TYPE_PARAMETER} correspond
* to the declaration contexts in JLS 9.6.4.1.
*
* <p>For example, an annotation whose type is meta-annotated with
* {@code @Target(ElementType.FIELD)} may only be written as a modifier for a
* field declaration.
*
* <p>The constant {@link #TYPE_USE} corresponds to the 15 type contexts in JLS
* 4.11, as well as to two declaration contexts: type declarations (including
* annotation type declarations) and type parameter declarations.
*
* <p>For example, an annotation whose type is meta-annotated with
* {@code @Target(ElementType.TYPE_USE)} may be written on the type of a field
* (or within the type of the field, if it is a nested, parameterized, or array
* type), and may also appear as a modifier for, say, a class declaration.
*
* <p>The {@code TYPE_USE} constant includes type declarations and type
* parameter declarations as a convenience for designers of type checkers which
* give semantics to annotation types. For example, if the annotation type
* {@code NonNull} is meta-annotated with
* {@code @Target(ElementType.TYPE_USE)}, then {@code @NonNull}
* {@code class C {...}} could be treated by a type checker as indicating that
* all variables of class {@code C} are non-null, while still allowing
* variables of other classes to be non-null or not non-null based on whether
* {@code @NonNull} appears at the variable's declaration.
*
* @author Joshua Bloch
* @since 1.5
* @jls 9.6.4.1 @Target
* @jls 4.1 The Kinds of Types and Values
*/
public enum ElementType {
/** Class, interface (including annotation type), or enum declaration */
TYPE,
/** Field declaration (includes enum constants) */
FIELD,
/** Method declaration */
METHOD,
/** Formal parameter declaration */
PARAMETER,
/** Constructor declaration */
CONSTRUCTOR,
/** Local variable declaration */
LOCAL_VARIABLE,
/** Annotation type declaration */
ANNOTATION_TYPE,
/** Package declaration */
PACKAGE,
/**
* Type parameter declaration
*
* @since 1.8
*/
TYPE_PARAMETER,
/**
* Use of a type
*
* @since 1.8
*/
TYPE_USE
}
@Target注解需要传入的是数组值,定义的属性ElementType[] value()为,@Target源码如下:
package java.lang.annotation;
/**
* Indicates the contexts in which an annotation type is applicable. The
* declaration contexts and type contexts in which an annotation type may be
* applicable are specified in JLS 9.6.4.1, and denoted in source code by enum
* constants of {@link ElementType java.lang.annotation.ElementType}.
*
* <p>If an {@code @Target} meta-annotation is not present on an annotation type
* {@code T} , then an annotation of type {@code T} may be written as a
* modifier for any declaration except a type parameter declaration.
*
* <p>If an {@code @Target} meta-annotation is present, the compiler will enforce
* the usage restrictions indicated by {@code ElementType}
* enum constants, in line with JLS 9.7.4.
*
* <p>For example, this {@code @Target} meta-annotation indicates that the
* declared type is itself a meta-annotation type. It can only be used on
* annotation type declarations:
* <pre>
* @Target(ElementType.ANNOTATION_TYPE)
* public @interface MetaAnnotationType {
* ...
* }
* </pre>
*
* <p>This {@code @Target} meta-annotation indicates that the declared type is
* intended solely for use as a member type in complex annotation type
* declarations. It cannot be used to annotate anything directly:
* <pre>
* @Target({})
* public @interface MemberType {
* ...
* }
* </pre>
*
* <p>It is a compile-time error for a single {@code ElementType} constant to
* appear more than once in an {@code @Target} annotation. For example, the
* following {@code @Target} meta-annotation is illegal:
* <pre>
* @Target({ElementType.FIELD, ElementType.METHOD, ElementType.FIELD})
* public @interface Bogus {
* ...
* }
* </pre>
*
* @since 1.5
* @jls 9.6.4.1 @Target
* @jls 9.7.4 Where Annotations May Appear
*/
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.ANNOTATION_TYPE)
public @interface Target {
/**
* Returns an array of the kinds of elements an annotation type
* can be applied to.
* @return an array of the kinds of elements an annotation type
* can be applied to
*/
ElementType[] value();
}
@Target注解的使用案例如下:
package com.minstone;
import net.bytebuddy.implementation.bind.annotation.RuntimeType;
import java.lang.annotation.*;
/**
* 测试元注解
*/
@MyAnnotation
public class Test01 {
public static void main(String[] args) {
}
@MyAnnotation
public void test(){
}
}
// 表示我们的注解可以用在什么地方
@Target(value = {ElementType.METHOD})
// 表示我们的注解在什么地方生效
// runtime > class > sources
// 定义为runtime的runtime、class、sources 3个阶段生效
// 定义为class的可以在class、sources 2个阶段生效
// 定义为sources的只能在sources阶段生效
@Retention(value = RetentionPolicy.SOURCE)
// 表示是否将我们的注解生成在 JAVAdoc中
@Documented
// 子类可以继承父类的注解
@Inherited
@interface MyAnnotation{
}
1.3自定义注解
注解可以显示赋值,如果没有默认值,我们就必须给注解赋值。
自定义注解未设置参数默认值,在使用该注解的时候不给该参设值则报错
自定义注解为设置参数默认值,使用该注解的时候不给该参设值则正常
2.反射
反射学习的大纲:
Java反射机制概述
理解Class类并获取Class实例
类的加载与ClassLoader
创建运行时类的对象
获取运行时类的完整结构
调用运行时类的指定结构
静态语言和动态语言的区别:
Java Reflection(反射)
反射是什么,反射和正常方式的区别?如下:
Java 反射机制提供的功能 有哪些?
Java 反射的优点和缺点 是什么?
反射相关的主要API
得到class类的几种方式
哪一些类型可以有class对象?
类输出展示:
Java内存分析:
类的加载与ClassLoader 的理解:
类的加载过程:
分析类的初始化
什么时候会发生类的初始化:
初始化代码:
输出结果:
所以反射和手动new 对象();都是一样的,都属于类的主动引用。
类的被动引用:(不会发生类的初始化)
// 子类调用父类的 static 属性,不会初始化子类
// Son [] = new Son[5]新建一个子类的数字,只是分配一块内存空间 给该数组,是不存在子类的初始化的
// 调用子类的 常量 private static final int M = f1;
父类和子类都不会去初始化
原因:常量 是在类加载的链接过程中 的第二阶段(准备)的时候就会给该常量分配内存空间并且赋值。
类加载器:
Java代码的在计算机中经历的三个阶段
1. 源代码 (.java)编译为
2.字节码文件(class)编译为
3.计算机能够识别的二进制文件。
引导类加载器,C++编写,负责Java平台核心库 rt.jar
rt.jar 里面的内容:java.lang \ java.io \ java.beans等等
在Java中获取根加载器、扩展类加载器、系统类的加载器
当前类 是 什么类加载器加载的?JDK内置的类是什么 类加载器加载的?
系统类加载器可以加载的路径有哪些?
程序:
输出结果:
这些路径下面的类都可以被加载到,如何不在该路径下面就无法加载该类
类的加载不是凭空的而是由类加载器加载的,是需要遵守规则的。
顺便提一口双亲委派机制:
如果你自定义一个java.lang.String类的话,程序在加载的时候会去往父类一层层的寻找,java原生的是否存在该类,如果存在的话,java只会用它自带的类,而不是去加载用户自定义的同名的类。
原因:这是出于安全的考虑,java自带的安全机制。
获取类的运行时结构
小结:
在实际操作中,取得类的信息的操作代码,并不会经常开发。
一定要熟悉java.lang.reflect包的作用,反射机制。
如何取得属性,方法,构造器的名称,修饰符等。
重点:通过反射 动态创建对象 执行方法
有了Class对象,能做什么?
如何通过反射来操作方法?
如何通过反射操作属性?
注意:使用反射操作属性的时候,不能直接操作私有属性,我们需要关闭程序的安全监测,
属性或者方法的serAccessible(true)
setAccessible的使用:
性能对比分析(普通、反射开启安全机制、反射关闭安全机制):
package com.minstone;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
public class Test05 {
public static void main(String[] args) throws InvocationTargetException, NoSuchMethodException, IllegalAccessException {
test01();
test02();
test03();
}
private static void test01(){
User user = new User();
long start = System.currentTimeMillis();
for (int i = 0; i < 100000000; i++) {
user.getName();
}
long endtime = System.currentTimeMillis();
System.out.println("普通方法执行10亿次的时间:"+ (endtime - start) + "ms");
}
private static void test02() throws NoSuchMethodException, InvocationTargetException, IllegalAccessException {
User user = new User();
Class<? extends User> c1 = user.getClass();
// 获取getName方法
Method getName = c1.getDeclaredMethod("getName", null);
long start = System.currentTimeMillis();
for (int i = 0; i < 1000000000; i++) {
// 执行getName方法,传入对象,和方法的入参
getName.invoke(user, null);
}
long endtime = System.currentTimeMillis();
System.out.println("反射开启安全检查策略,执行10亿次的时间:"+ (endtime - start) + "ms");
}
private static void test03() throws NoSuchMethodException, InvocationTargetException, IllegalAccessException {
User user = new User();
Class<? extends User> 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");
}
}
结果:
普通方法执行10亿次的时间:18ms
反射开启安全检查策略,执行10亿次的时间:12828ms
反射关闭安全检查策略,执行10亿次的时间:5682ms
Process finished with exit code 0
通过反射操作泛型:
打印结果:
反射操作注解:
练习使用反射操作注解
package com.minstone;
import java.lang.annotation.*;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
/**
* 联系反射操作注解
*/
public class Test06 {
public static void main(String[] args) throws ClassNotFoundException, NoSuchFieldException {
Class<?> c1 = Class.forName("com.minstone.Student2");
// 通过反射获取注解
Annotation[] annotations = c1.getAnnotations();
for (Annotation annotation : annotations) {
System.out.println(annotation);
}
// 获取类 上注解的value的值
Tablekuang tablekuang = c1.getAnnotation(Tablekuang.class);
String value = tablekuang.value();
System.out.println(value);
// 获取属性 上注解的value的值
Field[] declaredFields = c1.getDeclaredFields(); // 获取所以的字段
// Field nameDeclaredFields = c1.getDeclaredField("name"); // 获取指定名字的字段
for (Field field : declaredFields) {
Fieldkuang fieldkuang = field.getAnnotation(Fieldkuang.class);
String cloumnName = fieldkuang.cloumnName();
int length = fieldkuang.length();
String type = fieldkuang.type();
System.out.println(field.getName()+ " " + cloumnName + " " + type + " " + length);
}
}
}
@Tablekuang("db_student")
class Student2{
@Fieldkuang(cloumnName = "db_name", type = "varchar", length = 10)
private String name;
@Fieldkuang(cloumnName = "db_age", type = "int", length = 4)
private int age;
@Fieldkuang(cloumnName = "db_id", type = "int", length = 4)
private int id;
public void setName(String name) {
this.name = name;
}
public void setAge(int age) {
this.age = age;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public int getAge() {
return age;
}
public int getId() {
return id;
}
}
/**
* 类名的注解
*/
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@interface Tablekuang{
String value();
}
/**
* 属性的注解
*/
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
@interface Fieldkuang{
String cloumnName();
String type();
int length();
}
输出结果:
@com.minstone.Tablekuang(value=db_student)
db_student
name db_name varchar 10
age db_age int 4
id db_id int 4
Process finished with exit code 0
总结:
什么是注解
内置注解
自定义注解
什么是反射
学习地址: