1. 程式人生 > 實用技巧 >PDF檔案解析&拆分在SAP憑證列印場景中的運用(二)

PDF檔案解析&拆分在SAP憑證列印場景中的運用(二)

1.Class類

  • Class本身也是一個類

  • Class物件只能由系統建立物件

  • 一個載入的類在JVM中只會有一個Class例項

  • 一個Class物件對應的是一個載入到JVM中的一個class檔案

  • 每個類的例項都會記得自己是由哪個Class例項所生成

  • 通過Class可以完整的得到一個類中的所有被載入的結構

@Test
public void test1() throws ClassNotFoundException {
//通過反射獲取類的class物件
Class c1 = Class.forName("com.yl.pojo.User");
System.out.println(c1);

//一個類在記憶體中只有一個Class物件
//一個類被載入後,類的整個結構都會被封裝在Class物件中
Class c2 = Class.forName("com.yl.pojo.User");
System.out.println(c1==c2);
}

2.獲取Class類的例項

//測試Class類的建立方法
@Test
public void test2() throws ClassNotFoundException{
User user = new Student();
System.out.println("這個人是:"+user.name);

//方式一:通過物件獲得
Class c1 = user.getClass();
System.out.println(c1);

//方式二:forName獲得
Class c2 = Class.forName("com.yl.pojo.Student");

//方式三:通過類名.class獲得
Class<Student> c3 = Student.class;//c1 c2 c3是同一個物件

//方式四:基本內建型別的包裝類都有一個Type屬性
Class<Integer> c4 = Integer.TYPE;
System.out.println(c4);//int

//獲得父類型別
Class c5 = c1.getSuperclass();
System.out.println(c5);
}

3.哪些型別可以有Class物件

class、interface、陣列、enum、annotation、基本資料型別、void

只要元素型別和維度一樣,就是同一個Class物件

4.類的載入

什麼時候發生類的初始化:(new一個類和通過反射呼叫才發生)

5.獲取執行時類的完整結構

@Test
public void test4() throws NoSuchFieldException, NoSuchMethodException {
User student = new Student();
Class c1 = student.getClass();
//獲得類的名字
System.out.println(c1.getName());//獲得類名+包名
System.out.println(c1.getSimpleName());//獲得類名

//獲得類的屬性
Field[] fields = c1.getFields();//獲得public屬性,包括父類中的欄位
for (Field field : fields) {
System.out.println(field);
}
Field[] declaredFields = c1.getDeclaredFields();//獲得某個類的所有宣告的欄位,但不包括父類中的欄位
for (Field declaredField : declaredFields) {
System.out.println(declaredField);
}
System.out.println(c1.getField("name"));

//獲得類的方法
Method[] methods = c1.getMethods();
for (Method method : methods) {
System.out.println(method);
}

Method[] declaredMethods = c1.getDeclaredMethods();
for (Field declaredField : declaredFields) {
System.out.println(declaredField);
}

Method getName = c1.getMethod("getName", null);
Method setName = c1.getMethod("setName", String.class);

//獲得構造器,同樣可以指定
System.out.println(c1.getConstructors());
System.out.println(c1.getDeclaredConstructors());
}

6.動態建立物件執行方法

@Test
public void test5() throws ClassNotFoundException, IllegalAccessException, InstantiationException, NoSuchMethodException, InvocationTargetException, NoSuchFieldException {
Class c1 = Class.forName("com.yl.pojo.User");

User user = (User)c1.newInstance();//本質上是呼叫類的無參構造器
System.out.println(user);

//通過構造器建立物件
Constructor constructor = c1.getDeclaredConstructor(String.class, int.class, int.class,String.class);
User user2 = (User) constructor.newInstance("lulu", 1, 18,"女");
System.out.println(user2);

//通過反射呼叫普通方法
Method setGender = c1.getDeclaredMethod("setGender", String.class);
User user3 = (User) c1.newInstance();
setGender.invoke(user3,"男");//invoke:啟用
System.out.println(user3.getGender());

//通過反射操作屬性,不能直接操作私有屬性,需要關閉安全檢測
Field gender = c1.getDeclaredField("gender");//gender是私有欄位
gender.setAccessible(true);//關閉安全檢測
User user4 = (User) c1.newInstance();
gender.set(user4,"女");
System.out.println(user4.getGender());
}

7.通過反射獲取泛型資訊

public void test6(Map<String,User> map, List<User> list){
System.out.println("test6");
}

@Test
public void test7() throws NoSuchMethodException {
Method test6 = myTest.class.getMethod("test6", Map.class, List.class);
//獲得泛型引數
Type[] genericParameterTypes = test6.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);
}
}
}
}

8.反射操作註解

類註解:

package com.yl.annotation;


import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

//類名的註解
//target:作用域,retention:獲取級別
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface MyTable{
String value();
}

屬性註解:

package com.yl.annotation;


import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

//屬性的註解
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
public @interface MyField{
String columnName();
String type();
int length();
}

pojo:

@MyTable("db_User")
public class User {
@MyField(columnName = "id",type = "int",length = 10)
private int id;
@MyField(columnName = "name",type = "varchar",length = 15)
private String name;
@MyField(columnName = "age",type = "int",length = 3)
private int age;
}

測試:

@Test
public void test() throws ClassNotFoundException, NoSuchFieldException {
Class c1 = Class.forName("com.yl.pojo.User");
//通過反射獲得註解
Annotation[] annotations = c1.getAnnotations();
for (Annotation annotation : annotations) {
System.out.println(annotation);
}

//獲得註解的value的值
MyTable myTable = (MyTable)c1.getAnnotation(MyTable.class);
System.out.println(myTable.value());

Field name = c1.getDeclaredField("name");
MyField annotation = name.getAnnotation(MyField.class);
System.out.println(annotation.columnName());
System.out.println(annotation.type());
System.out.println(annotation.length());
}