概述
Annotation的作用
- 不是程序本身,可以對程序作出結束(與注釋comment無異)
- 可以備其他程序(比如編譯器)讀取
Annotation的格式
- 注解是以
@注釋名在代碼中存在的,還可以添加一些參數值,例如@SuppressWarnings(value = “unchecked”)
Annotation在哪里使用?
- 可以附加在package,class,method,field上面,相當於添加額外的輔助信息,可以通過反射機制編程實現對這些元數據的訪問
內置注解
-
@Override定義在java.lang.Override中,此注釋只適用於修辭手法,表示一個方法聲明打算重寫超類中的另一個方法聲明 -
@Deprecated定義在java.lang.Deprecated中,此注釋可以用於修飾方法、屬性、類,表示不鼓勵程序員使用這樣的元素,通常是因為它很危險或者存在更好的選擇 -
@SuppressWarnings定義在java.lang.SuppressWarnings中,用來抑制編譯時的警告信息,與前兩個有所不同的是需要添加一個參數才能正常使用,這些參數都是定義好的@SuppressWarnings("all") @SuppressWarnings("unchecked") @SuppressWarnings(value = {"unchecked", "deprecation"}) ...
元注解
元注解的作用就是負責注解其他注解,java定義了4個標准的meta-annotation類型,他們被用來提供對其他annotation類型作說明
☆ @Target //用於描述注解的適用范圍
☆ @Retention //表示在什么級別保存該注釋信息,用於描述注解的生命周期(source < class < RUNTIME)
@Document // 說明該注解將被包含在javadoc中
@Inherited // 說明子類可以繼承父類中的該注解
自定義注解
使用@interface自定義注解時,自動繼承了java.lang.annotation.Annotation接口
分析:
- @interface用來聲明一個注解,格式
public @inteface 注解名 { content }- 其中的每一個方法實際上是聲明了一個配置參數
- 方法的名稱就是參數的名稱
- 返回值類型就是參數的類型(返回值只能是基本類型 class、String、 enum)
- 可以通過default來聲明參數的默認值
- 如果只有一個參數成員,一般參數名為value
- 注解元素必須要有值,我們定義注解元素時,經常使用空字符串、0作為默認值
package com.company.annotation;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
// 自定義注解
public class test1 {
// 注解可以顯示賦值 如果沒有默認值,就必須給注解賦值
@MyAnnotation(name = "oho", age = 19)
public void test(){
}
}
@Target({ElementType.TYPE, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@interface MyAnnotation{
// 注解的參數: 參數類型 + 參數名();
// String value(); 此時上面的引用可以不需要 value = "xxx"
String name() default "";
int age() default 0;
int id() default -1;// 如果默認值為-1,代表不存在
String[] schoold() default "TshinghuaU";
}
反射機制


package com.company.annotation;
public class reflection {
public static void main(String[] args) throws ClassNotFoundException {
Class c1 = Class.forName("com.company.annotation.User");
System.out.println(c1);
Class c2 = Class.forName("com.company.annotation.User");
Class c3 = Class.forName("com.company.annotation.User");
Class c4 = Class.forName("com.company.annotation.User");
// 一個類在內存中只有一個class對象
// 一個類被加載后,類的整個結構都會被封裝在class對象中
System.out.println(c2.hashCode());
System.out.println(c3.hashCode());
System.out.println(c4.hashCode());
}
}
// 實體類 : 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 com.company.annotation.User
284720968
284720968
284720968
*/
Class 類



獲取Class類的實例

package com.company.annotation;
public class refClass {
public static void main(String[] args) throws ClassNotFoundException {
Person person = new Student();
System.out.println("this is :" + person.name);
// 方式一: 通過對象獲得
Class c1 = person.getClass();
System.out.println(c1);
// 方式二: forname獲得
Class c2 = Class.forName("com.company.annotation.Student");
System.out.println(c2);
// 方式三:通過類名.class獲得
Class c3 = Student.class;
System.out.println(c3);
// 方法四 :基本內置類型的包裝類都有一個Type屬性
Class c4 = Integer.TYPE;
System.out.println(c4);
// 獲得父類類型
Class c5 = c1.getSuperclass();
System.out.println(c5);
}
}
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 = "Stu";
}
}class Teacher extends Person{
public Teacher(){
this.name = "Teac";
}
}
package com.company.annotation;
import java.lang.annotation.ElementType;
// 所有類型的 Class
public class test2 {
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);
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
int[] a = new int[10];
int[] b = new int[100];
System.out.println(a.getClass().hashCode());
System.out.println(b.getClass().hashCode());
}
}
Java 內存分析

類初始化

package com.company.annotation;
// 測試類聲明時候會被初始化
public class test3 {
static {
System.out.println("Main 被加載");
}
public static void main(String[] args) throws ClassNotFoundException {
// 1. 主動引用
Son son = new Son();
// 2. 反射也會產生主動引用
Class.forName("com.company.annotation.Son");
// 不會產生類的引用方法
System.out.println(Son.b);
Son[] array = new Son[100];
}
}
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.company.annotation;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
// 獲取類的信息
public class test4 {
public static void main(String[] args) throws ClassNotFoundException, NoSuchFieldException, NoSuchMethodException {
Class c1 = Class.forName("com.company.annotation.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);
}
// 獲得指定方法
// 重載
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, int.class);
System.out.println("指定的:" + declaredConstructor);
}
}
有了Class對象后續操作

package com.company.annotation;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
public class test5 {
public static void main(String[] args) throws IllegalAccessException, InstantiationException, NoSuchMethodException, InvocationTargetException, NoSuchFieldException, ClassNotFoundException {
// 獲得class對象
Class c1 = Class.forName("com.company.annotation.User");
// 構造一個對象
User user = (User)c1.newInstance(); // 本質是調用了類的無參構造器
System.out.println(user);
// 通過構造器創建對象
Constructor constructor = c1.getDeclaredConstructor(String.class, int.class, int.class);
User user2 = (User)constructor.newInstance("快樂哥", 001, 20);
System.out.println(user2);
// 通過反射調用普通方法
User user3 = (User)c1.newInstance();
// 通過反射獲取一個方法
Method setName = c1.getDeclaredMethod("setName", String.class);
// (對象, “方法的值”)
setName.invoke(user3, "olao");
System.out.println(user3.getName());
// 通過反射操作屬性
System.out.println("---------------------");
User user4 = (User)c1.newInstance();
Field name = c1.getDeclaredField("name");
//不能直接操作私有屬性,我們需要關閉程序的安全監測,
// 開啟訪問權限
name.setAccessible(true);
name.set(user4, "oila");
System.out.println(user4.getName());
}
}
反射操作泛型

通過反射操作注解 (練習ORM)

package com.company.annotation;
import java.lang.annotation.*;
import java.lang.reflect.Field;
public class orm {
public static void main(String[] args) throws ClassNotFoundException, NoSuchFieldException {
Class c1 = Class.forName("com.company.annotation.Stu");
// 通過反射獲得注解
Annotation[] annotations = c1.getAnnotations();
for (Annotation annotation : annotations) {
System.out.println(annotation);
}
// 獲得注解的value的值
TableStu tableStu = (TableStu)c1.getAnnotation(TableStu.class);
String value = tableStu.value();
System.out.println(value);
// 獲得類指定注解
Field f = c1.getDeclaredField("name");
FieldStu annotation = f.getAnnotation(FieldStu.class);
System.out.println(annotation.columnName());
System.out.println(annotation.length());
System.out.println(annotation.type());
}
}
@TableStu("db_stu")
class Stu{
@FieldStu(columnName = "db_id", type = "int", length = 10)
private int id;
@FieldStu(columnName = "db_age", type = "int", length = 10)
private int age;
@FieldStu(columnName = "db_name", type = "varchar", length = 3)
private String name;
public Stu() {
}
public Stu(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 "Stu{" +
"id=" + id +
", age=" + age +
", name='" + name + '\'' +
'}';
}
}
// 類名的注解
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@interface TableStu{
String value();
}
// 屬性的注解
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
@interface FieldStu{
String columnName();
String type();
int length();
}
