天天看點

java注解和泛型注解和泛型總結

注解和泛型

            面試題                1、注解是什麼?                  2、如何自定義注解?                  3、java中的泛型是什麼?有什麼好處?                  4、List<? extends T>和List <? super T>之間有什麼差別?                         5、如何編寫一個泛型方法,讓它能接受泛型參數并傳回泛型類型?

學習目标

1、注解(注釋):Annotation   2、泛型   泛型集合   泛型類,泛型接口,泛型方法   通配符:?   泛型擦除   一、 Annotation   1.1 什麼是注解 ?   Java 注解(Annotation)又稱 Java 标注,是 JDK5.0 引入的一種注釋機制。   Java 語言中的類、方法、變量、參數和包等都可以被标注。Java标注可以通過 反射擷取标注内容。在編譯器生成類檔案時,标注可以被嵌入到位元組碼中。   Java 虛拟機可以保留标注内容,在運作時可以擷取到标注内容 。   Java 注解用于為 Java 代碼提供中繼資料。作為中繼資料,注解不直接影響你的代碼執行,但也有一些類型的注解實際上可以用于這一目的。   常見注解 @WebServlet @WebListener @WebFilter: servlet規範中的三大元件 @Override @Controller 解釋:注釋(說明,标簽),不是單行注釋,多行注釋; 是讓編譯器, JVM, 通過反射去分析的注釋;

1.2 注解的定義 注解通過 @interface 關鍵字進行定義。

public @interface TestAnnotation {
}
           

它的形式跟接口很類似,不過前面多了一個 @ 符号。上面的代碼就建立了一個名字為 TestAnnotaion 的注解。

1.3 注解分類 注解主要分為: 内置注解 元注解 自定義注解

1.3.1 内置注解 Java目前内置了三種注解: @Override:在編譯期檢查方法是否符合重寫的文法 @Deprecated:标注已過時 @SupressWarnings:抑制編譯器警告

/**
         * 注解是添加在類/方法/屬性...以@符号開頭,在編譯時,運作時起到不同得作用。
   */
        @SuppressWarnings("unused")
        public class ChildDemo implements SuperDemo {
            // 棄用,過時,聲明方法/屬性已經過時,不推薦使用,但是可以正常使用
            @Deprecated
            String a = "a";
            // 抑制警告資訊,取消警告提示,unchecked不檢查,unuserd未使用,all所有
            @SuppressWarnings("all")
            public void m1(){
                int i = 1/0;
            }
            @Deprecated
// 重寫,表明目前得方法是重寫得父類/接口中得方法,區分私有得方法
            @Override
            public int add() {
                return 0;
            }
            public void m2(){
                Date date = new Date();
                int date1 = date.getDate();
            }
        
}
           

1.3.2 元注解 用來聲明(建立)的注解的一種注解

名稱 說明
@Target 明确注解在哪裡使用(類,方法、屬性、接口、局部變量)
@Retention 辨別:注解的保留期
@Documented 儲存在javadoc中
@Inherited 允許注解繼承注解
@Retention:注解的保留位置
該階段的注解,主要為了約定程式的規範,程式異常(編譯時異常/運作時異常)及限制程式的
@Retention(RetentionPolicy.SOURCE) //注解僅存在于源碼中,在class位元組碼檔案中不包含
//比如@Override, @SuppressWarnings
//@Data 自動生成get set
/*<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.4</version>
<scope>provided</scope>
</dependency>*/
@Retention(RetentionPolicy.CLASS) // 預設的保留政策,注解會在class位元組碼檔案中存在,但運作
時無法獲得,
@Retention(RetentionPolicy.RUNTIME) // 注解會在class位元組碼檔案中存在,在運作時可以通過反
射擷取到
@Target:注解的作用目标
@Target(ElementType.TYPE) //接口、類、枚舉
@Target(ElementType.FIELD) //字段、枚舉的常量
@Target(ElementType.METHOD) //方法
@Target(ElementType.PARAMETER) //方法參數
@Target(ElementType.CONSTRUCTOR) //構造函數
@Target(ElementType.LOCAL_VARIABLE)//局部變量
@Target(ElementType.ANNOTATION_TYPE)//注解
@Target(ElementType.PACKAGE) ///包
@Document:說明該注解将被包含在javadoc中
@Inherited:說明子類可以繼承父類中的該注解
           

ElementType 枚舉類型,封裝的是一些特定的值,可讀性強

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 java元注解
             */
            TYPE_PARAMETER,
            /**
             * Use of a type
             *
             * @since 1.8
             */
            TYPE_USE
        }
           

RetentionPolicy .java檔案先編譯為.class檔案,運作時執行.class檔案得内容,注解有效期

public enum RetentionPolicy {
            /**
             * Annotations are to be discarded by the compiler.
             源碼階段保留,會被編譯器識别,不會保留在class檔案中;編譯期間起作用
             */
            SOURCE,
/**
 * Annotations are to be recorded in the class file by the compiler
 * but need not be retained by the VM at run time. This is the default
 * * behavior.
 * 會保留到class檔案中,不會被jvm識别(運作期間無法擷取)(預設)
 */
 *CLASS,
 
             /**
             * Annotations are to be recorded in the class file by the compiler and
             * retained by the VM at run time, so they may be read reflectively.
             * 在運作期間保留,可以通過反射去擷取分析
             * @see java.lang.reflect.AnnotatedElement
             */
           RUNTIME
   }
           

1.3.3 自定義注解 建立

//标注該注解可以用在哪裡(目标)
@Target(value={ElementType.METHOD,ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
public @interface MyAnnotation {
String value() ;
int test();
int[] types();
}
           

使用:

@MyAnnotation(value="test",test=1,types = {1,2,3})
public class Test {
}
           

1.4 注解處理 單純說注解,注解本身沒有任何的作用。簡單說和注釋沒啥差別,而它有作用的原因是: 注解解釋類,也就是相關 對代碼進行解釋的特定類。一般這些類使用反射是可以拿到的。 是以,通過注解和反射這兩者的結合使用,是可以做到很多功能的。   1.4.2 ORM 實作 自定義注解:

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
public @interface Table {
String name() default "";
}
           

實體類使用注解:

@Table
 public class Emp {
        private Integer id;
        private String name;
        ......
}
           

注解解釋類:

public class MyORM {
            //實作查詢資料表的功能 一個項目有30張資料表 30個
//寫一個公共的方法實作對所有不同表的查詢功能
//參數為不同表對應實體類的class執行個體
            public static <T> List<T> queryAll(Class<T> clazz){
                String sql ="";
//此時的 A.isAnnotationPresent(B.class);意思就是:注釋B是否在此A上。如果在則傳回true;
//                不在則傳回false。
                if(clazz.isAnnotationPresent(Table.class)){
                    Table annotation = clazz.getAnnotation(Table.class);
                    String tableName = annotation.name();
                    if(tableName.equals("")){
                        tableName = clazz.getSimpleName();//Emp emp
                        System.out.println(tableName);
                    }
                    sql = "select * from "+tableName;
                }
                System.out.println(sql);
                return null;
            }
    }
           

調用:

public static void main(String[] args) {
   List<Emp> emps = MyORM.queryAll(Emp.class);
}
           

1.4.2 自動列印日志 思路分析:

java注解和泛型注解和泛型總結

日志注解:

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
public @interface LogAnocation {

}
           

實驗類:

@Service
        @LogAnocation
        public class EmpService {
            public int add(int a,int b){
                return 1;
            }
            public List select(){
                return null;
            }
  }
           

使用AOP完成注解分析類

@Component
        @Aspect
        public class LoggingAspect {
            @Before("within(demo03.service.*)")
            public void log(JoinPoint joinPoint) {
                Signature signature = joinPoint.getSignature();
                Class<?> targetClass = joinPoint.getTarget().getClass();
                if (targetClass.isAnnotationPresent(LogAnocation.class)) {
                    System.out.println(new Date() + ":調用" + targetClass.getName() + "." + signature.getName());
                    Object[] args = joinPoint.getArgs();
                    System.out.println("\tparams:"+Arrays.toString(args));
                }
            }
     }
           

測試類:

public static void main(String[] args) {
            ClassPathXmlApplicationContext context = new
                    ClassPathXmlApplicationContext("classpath:applicationContext.xml");
            EmpService empService = context.getBean(EmpService.class);
            empService.add(1,2);
            empService.select();
 }
           

完整示例:

實體類

import lombok.Builder;
import lombok.Data;

/*
@Data:注解在類上,将類提供的所有屬性都添加get、set方法,并添加、equals、canEquals、hashCode、toString方法
@Setter:注解在類上,為所有屬性添加set方法、注解在屬性上為該屬性提供set方法
@Getter:注解在類上,為所有的屬性添加get方法、注解在屬性上為該屬性提供get方法
@NotNull:在參數中使用時,如果調用時傳了null值,就會抛出空指針異常
@Synchronized 用于方法,可以鎖定指定的對象,如果不指定,則預設建立一個對象鎖定
@Log作用于類,建立一個log屬性
@Builder:使用builder模式建立對象
@NoArgsConstructor:建立一個無參構造函數
@AllArgsConstructor:建立一個全參構造函數
@ToStirng:建立一個toString方法
@Accessors(chain = true)使用鍊式設定屬性,set方法傳回的是this對象。
@RequiredArgsConstructor:建立對象
@UtilityClass:工具類
@ExtensionMethod:設定父類
@FieldDefaults:設定屬性的使用範圍,如private、public等,也可以設定屬性是否被final修飾。
@Cleanup: 關閉流、連接配接點。
@EqualsAndHashCode:重寫equals和hashcode方法。
@toString:建立toString方法。

 */
@Data
@Builder
// 為Person類配置了剛剛定義的注解@Info
@Info(isDelete = true)
public class Person {

    /**
     * 姓名
     */
    private String name;

    /**
     * 年齡
     */
    private int age;

    /**
     * 是否有效
     */
    private boolean isDelete;
}
           
/*
注解是一種能被添加到java源代碼中的中繼資料,方法、類、參數和包都可以用注解來修飾。
注解可以看作是一種特殊的标記,可以用在方法、類、參數和包上,
程式在編譯或者運作時可以檢測到這些标記而進行一些特殊的處理。

    聲明一個注解要用到的東西

    修飾符
      通路修飾符必須為public,不寫預設為pubic;
    關鍵字
      關鍵字為@interface;
    注解名稱
      注解名稱為自定義注解的名稱,使用時還會用到;
    注解類型元素
      注解類型元素是注解中内容,可以了解成自定義接口的實作部分;

使用元注解修飾注解:
JDK中有一些元注解,主要有@Target,@Retention,@Document,
@Inherited用來修飾注解。
@Target:  表明該注解可以應用的java元素類型



Target類型	         描述
ElementType.TYPE	應用于類、接口(包括注解類型)、枚舉
ElementType.FIELD	應用于屬性(包括枚舉中的常量)
ElementType.METHOD	應用于方法
ElementType.PARAMETER	應用于方法的形參
ElementType.CONSTRUCTOR	應用于構造函數
ElementType.LOCAL_VARIABLE	應用于局部變量
ElementType.ANNOTATION_TYPE	應用于注解類型
ElementType.PACKAGE	應用于包
ElementType.TYPE_PARAMETER	1.8版本新增,應用于類型變量)
ElementType.TYPE_USE	1.8版本新增,應用于任何使用類型的語句中(例如聲明語句、泛型和強制轉換語句中的類型)


@Retention:表明該注解的生命周期

  生命周期類型	            描述
RetentionPolicy.SOURCE	編譯時被丢棄,不包含在類檔案中
RetentionPolicy.CLASS	JVM加載時被丢棄,包含在類檔案中,預設值
RetentionPolicy.RUNTIME	由JVM 加載,包含在類檔案中,在運作時可以被擷取到
 */

/*
@Document
  表明該注解标記的元素可以被Javadoc 或類似的工具文檔化
@Inherited
  表明使用了@Inherited注解的注解,所标記的類的子類也會擁有這個注解
 */

import java.lang.annotation.*;

@Target({ElementType.FIELD, ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Info {
    String value() default "tracy";
    boolean isDelete();
}
           

測試類

/*
    對于一個類或者接口來說,Class類(java.lang包下)中提供了一些方法用于反射注解,
    當然對于字段、方法來說反射注解的方式很類似。

//傳回指定的注解
getAnnotation
//判斷目前元素是否被指定注解修飾
isAnnotationPresent
//傳回所有的注解
getAnnotation   s

 */
public class AnnotationTest {
    public static void main(String[] args) {
        try {
            //擷取Person的Class對象
            Person person = Person.builder().build();
            Class clazz = person.getClass();
            //判斷person對象上是否有Info注解
            if (clazz.isAnnotationPresent(Info.class)) {
                System.out.println("Person類上配置了Info注解!");
                //擷取該對象上Info類型的注解
                Info infoAnno = (Info) clazz.getAnnotation(Info.class);
                System.out.println("person.name :" + infoAnno.value() + ",person.isDelete:" + infoAnno.isDelete());
            } else {
                System.out.println("Person類上沒有配置Info注解!");
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}
           

二、泛型   2.1 泛型簡介   集合中的泛型:  

List<String> list = new ArrayList<>();
           

泛型定義: 參數化的類型,将資料類型當成參數來使用,對類型進行限制(限制),在 編譯期起作用; 優點:   1、提高效率: 限定資料類型,隻存某一種特定的類型,減少類型轉化的時間(其他類型--->object--->其他類型)   2、防止類型轉換出現問題 推薦使用各種泛型接口,類 常用的 類型占位符:T E K V: 代表一種類型

2.2 泛型接口、泛型類 PageBean pb=new PageBean();  

public class PageBean<T> {
            private String name;
            private List <T> resultLists;//存儲每張表查詢出來的分頁資料集合
            public String getName() {
                return name;
            }
            public void setName(String name) {
                this.name = name;
            }
            public T getT() {
                return t;
            }
            public void setT(T t) {
                this.t = t;
            }
            public void show(Class<T> clz){
// clz.getDeclaredFields();
// clz.getDeclaredFields();
            }
        }
           
public class Test2 {
            public static void main(String[] args) {
// 如果不指定類型,預設是Object類型
                MyGeneric generic=new MyGeneric();
                generic.setT("aa");
                System.out.println(generic.getT());
                MyGeneric<String> generic1=new MyGeneric<>();
                generic1.setT("中國越來越強大");
                System.out.println(generic1.getT());
            }
     }
           

2.3 泛型方法

// 在傳回值類型前面:<類型占位符> ,定義類型的形參;方法中可以使用E當成一種資料類型來使用
        public <E> E query(Class<E> clz) throws NoSuchMethodException,
                IllegalAccessException, InvocationTargetException, InstantiationException {
// 擷取構造方法,通過構造擷取該類型的對象
            E object= clz.getConstructor().newInstance();
// 擷取所有的字段
            Field[] fields = clz.getDeclaredFields();
            for (int i = 0; i < fields.length; i++) {
                Field field = fields[i];
// 允許通路
                field.setAccessible(true);
                if(field.getName().equals("name")){
                    field.set(object,"張三"+Math.random());
                }else if(field.getName().equals("age")){
                    field.set(object,18);
                }
            }
            return object;
     }
           

示例:

public class Test2 {
            public static void main(String[] args) {
// 如果不指定類型,預設是Object類型
                MyGeneric generic=new MyGeneric();
                generic.setT("aa");
                System.out.println(generic.getT());
                MyGeneric<String> generic1=new MyGeneric<>();
                generic1.setT("中國越來越強大");
                System.out.println(generic1.getT());
                try {
                    Emp emp = generic1.query(Emp.class);
                    System.out.println(emp);
                    Student student = generic1.query(Student.class);
                    System.out.println(student);
                } catch (NoSuchMethodException e) {
                    e.printStackTrace();
                } catch (IllegalAccessException e) {
                    e.printStackTrace();
                } catch (InvocationTargetException e) {
                    e.printStackTrace();
                } catch (InstantiationException e) {
                    e.printStackTrace();
                }
            }
     }
           

2.4 泛型通配符 通配符:<?>: 真實的資料類型,泛指所有類型,不同于類型占位符

@CallerSensitive
        public static Class<?> forName(String className)throws ClassNotFoundException {
            Class<?> caller = Reflection.getCallerClass();
            return forName0(className, true, ClassLoader.getClassLoader(caller), caller);
   }
           

通配符上限:<? extends T>: 限定的類型隻能是T類型或者是T類型的子類型

// 限定:隻能傳進來 Number 集合 ,或者Number子類型的集合
        public static void test6(List<? extends Number> list){
            for (Number number : list) {
                System.out.println(number);
            }
    }
           

通配符下限:<? super T>:限定的類型隻能是T類型或者是T類型的父類型 示例:

public class Test3 {
            public static void main(String[] args) {
                test(Emp.class);
                test(Student.class);
                List<Emp> list1=new ArrayList<>();
                List<Student> list2=new ArrayList<>();
                List<String> list3=new ArrayList<>();
                test2(list1);
                test2(list2);
                test2(list3);
                List<Number> numbers=new ArrayList<>();
                List<Integer> integers=new ArrayList<>();
                test3(numbers);
                test4(integers);
//
// test3(integers);
                test6(numbers);
                test6(integers);
                Emp emp=new Emp();
                test5(emp);
            }
            public static void test(Class<?> clz){
            }
            public static void test2(List<?> list){
                for (Object o : list) {
                    System.out.println(o);
                }
            }
            // Integer 繼承自 Number 類型
            public static void test3(List<Number> list){
                for (Object o : list) {
                    System.out.println(o);
                }
            }
            public static void test4(List<Integer> list){
                for (Object o : list) {
                    System.out.println(o);
                }
            }
            // 限定:隻能傳進來 Number 集合 ,或者Number子類型的集合
            public static void test6(List<? extends Number> list){
                for (Number number : list) {
                    System.out.println(number);
                }
       }
  // 需要使用父類型的地方可以傳進來子類型的執行個體,任何時候子類型都可以替換父類型
        public static void test5(Person person){
            System.out.println(person);
        }
    }
           

2.5 泛型擦除 泛型擦除:在編譯泛型的時候,會将: 去掉,位元組碼種存儲的泛型實際上是一種類型。

public class Test4 {
            public static void main(String[] args) {
                List<String> list0=show();
                List list=show();
// 本質上是一種類型
                System.out.println(list0.getClass()==list.getClass());
            }
            public static List show(){
                List<String> list=new ArrayList<>();
                return list;
            }
    }
           

通過反射向泛型集合中存儲任意類型的資料

最後附上一個泛型的完整案例

通過泛型封裝一個簡單的JDBC連結工具

package com.aaa.Reflect_Two_day;

import com.aaa.Reflect_Two.Goods_info;
import com.aaa.Reflect_Two.Type_info;

import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.sql.*;
import java.util.ArrayList;
import java.util.List;

public class BaseDao {
    //jdbc連接配接資料的工具類
    private static String driver="com.mysql.jdbc.Driver";
    private static String url="jdbc:mysql://localhost:3306/goods?useSSL=false";
    private static String userName="root";
    private static String psdw="lian211314";
    //資料庫連接配接的擷取方法
    private static Connection getConn()
    {
        Connection conn = null;
        try {
            //第一步:加載驅動
            Class.forName(driver);
            //第二部:建立資料庫連接配接對象
            conn = DriverManager.getConnection(url,userName,psdw);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return conn;
    }
    /**
     * 增删改
     *
     * @param sql
     *            執行sql語句
     * @return
     */
    public static int update(String sql, Object... objs) {
        Connection conn = null;
        PreparedStatement ptm = null;
        int rs = 0;
        try {
            conn = getConn();
            ptm = conn.prepareStatement(sql);
            setParams(ptm, objs);
            rs = ptm.executeUpdate();
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            closeAll(null, ptm, conn);
        }
        return rs;
    }
    // 5.參數設定
    private static void setParams(PreparedStatement ptm, Object... objs) {
        if (null != objs) {
            for (int i = 0; i < objs.length; i++) {
                try {
                    ptm.setObject(i + 1, objs[i]);
                } catch (SQLException e) {
                    e.printStackTrace();
                }
            }
        }
    }
    //查詢方法
    public static <T> List<T> queryList(String sql, T t, Object ... objs)
    {
        //Class<? extends Object>:傳遞的對象可以是任何類型
        Class <? extends Object > tClass = t.getClass();//getClass得到實體類對象的class執行個體
        Connection conn = null;
        PreparedStatement psmt=null;
        ResultSet rs = null;
        //使用泛型加上占位符(<T>)
        List<T> list = new ArrayList<>();//存儲查詢結果集的集合
            try {
                conn =getConn();//連接配接資料庫對象
                psmt = conn.prepareStatement(sql);//執行sql
                //如果執行對象不為空的話
                if (null!=psmt&&null!=objs)
                {
                    //循環周遊執行對象(sql)
                    for (int i = 0;i<objs.length;i++)
                    {
                        psmt.setObject(i+1,objs[i]);
                    }
                }
                // 擷取查詢結果
                rs = psmt.executeQuery();
                // 擷取結果集結構(列的結構)
                ResultSetMetaData metaData = rs.getMetaData();
                // 擷取結果集列數
                int count = metaData.getColumnCount();// 擷取所有列的個數,即所有字段的總個數
                // 循環擷取每一行
                while (rs.next())
                {
                    //封裝每條資料對象,強轉泛型。
                    // 并且newInstance()建立對象t1
                    T t1 = (T) tClass.newInstance();//利用class執行個體建立目前類的對象(newInstance) new Book
                    //循環擷取目前每一列的值
                    for (int i = 0 ; i<count;i++)
                    {
                        //metaData.getColumnName(i+1)得到本列的字段名稱的
                        String fieldName = metaData.getColumnName(i+1);
                        //每一行中的某一列(單個屬性成員)
                        Field fi = tClass.getDeclaredField(fieldName);//擷取指定字段屬性的值
                        //利用getMethod得到裡邊的對應方法的對象,getSetter(fieldName)動态擷取該屬性對應的方法名字
                        //tClass.getMethod:得到指定名字的方法對象
                        Method method = tClass.getMethod(getSetter(fieldName),fi.getType());
                        method.invoke(t1,rs.getObject(i+1));//利用反射執行該方法
                    }
                    //将上邊封裝好的每條資料對象添加到最後的結果集裡
                    list.add(t1);
                }
            } catch (Exception e) {
                e.printStackTrace();
            }finally {
                closeAll(rs,psmt,conn);
            }
            //把查詢到的結果集傳回出去
        return list;
    }

    //拼接設定該屬性值的set方法的方法名字
    public  static String getSetter(String fieldName)
    {
        //查詢到的資料的各個字段
        return "set"+fieldName.substring(0,1).toUpperCase()+fieldName.substring(1);
    }

    //關閉資料庫多個對象的方法
    private static void closeAll(ResultSet rs , PreparedStatement pstmt,Connection conn) {
        try {
            if (rs!=null)
            {
                rs.close();
            }
            if (null!=pstmt)
            {
                pstmt.close();
            }
            if (conn!=null)
            {
                conn.close();
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    public static void main(String[] args) {
        String sql = "select * from goods_info ";
        List<Goods_info> list= BaseDao.queryList(sql,new Goods_info());
        for (Goods_info s : list)
        {
            System.out.println(s);
            s.getGoods_name();
            System.out.println(s.getGoods_name());
            s.setGoods_id(1);
        }

        String sql2 ="insert into goods_info (goods_name,type_id,goods_spec,goods_price,goods_date  ) values (1,1,1,1,'2012-12-12')";
        BaseDao.update(sql2);
        System.out.println("==========================");
        String sql3 = "select * from type_info ";
        List<Type_info> list3= BaseDao.queryList(sql3,new Type_info());
        System.out.println(list3);

        List<Type_info>list1 = new ArrayList<>();
        list1.add(new Type_info());
        List<Goods_info>list2 = new ArrayList<>();
        list2.add(new Goods_info());
//        BaseDao.queryList(sql,list1);
//        System.out.println();

    }

}
           

實體類

package com.aaa.comment;

import com.aaa.Reflect_Two.Type_info;

import java.util.Date;

@TableAnnotion(tName = "goods_info")
public class Goods_In extends Type_info {
    private Integer goods_id;
    private String goods_name;
    private Integer type_id;
    private String goods_spec;
    private Double goods_price;
    private Date goods_date;

    public Goods_In() {
    }

    public Goods_In(Integer goods_id, String goods_name, Integer type_id, String goods_spec, Double goods_price, Date goods_date) {
        this.goods_id = goods_id;
        this.goods_name = goods_name;
        this.type_id = type_id;
        this.goods_spec = goods_spec;
        this.goods_price = goods_price;
        this.goods_date = goods_date;
    }

    public Integer getGoods_id() {
        return goods_id;
    }

    public void setGoods_id(Integer goods_id) {
        this.goods_id = goods_id;
    }

    public String getGoods_name() {
        return goods_name;
    }

    public void setGoods_name(String goods_name) {
        this.goods_name = goods_name;
    }

    public Integer getType_id() {
        return type_id;
    }

    public void setType_id(Integer type_id) {
        this.type_id = type_id;
    }

    public String getGoods_spec() {
        return goods_spec;
    }

    public void setGoods_spec(String goods_spec) {
        this.goods_spec = goods_spec;
    }

    public Double getGoods_price() {
        return goods_price;
    }

    public void setGoods_price(Double goods_price) {
        this.goods_price = goods_price;
    }

    public Date getGoods_date() {
        return goods_date;
    }

    public void setGoods_date(Date goods_date) {
        this.goods_date = goods_date;
    }

    @Override
    public String toString() {
        return "Goods_info{" +
                "goods_id=" + goods_id +
                ", goods_name='" + goods_name + '\'' +
                ", type_id=" + type_id +
                ", goods_spec='" + goods_spec + '\'' +
                ", goods_price=" + goods_price +
                ", goods_date=" + goods_date +
                '}';
    }
}
           

泛型封裝類

package com.aaa.utlis;

import com.aaa.Reflect_Two.Goods_info;
import com.aaa.Reflect_Two_day.BaseDao;
import com.aaa.comment.Goods_In;
import com.aaa.comment.TableAnnotion;

import java.util.ArrayList;
import java.util.List;

public class TableJdbc<K> {
    //參數為不同表對應實體類的class執行個體
    public static <K>List<K> queryAll(Class<K> kClass)
    {
        String sql="";
//        System.out.println(clazz.isAnnotationPresent(TableAnnotation.class));
        //此時的 T.isAnnotationPresent(TableAnnotation.class);意思就是:注釋TableAnnotation是否在此T上。如果在則傳回true;不在則傳回false。
        if (kClass.isAnnotationPresent(TableAnnotion.class))
        {
            TableAnnotion annotion = kClass.getAnnotation(TableAnnotion.class);//得到自定義注解對象TableAnnotation
            String tableName = annotion.tName();//得到tName的屬性值
            if (tableName.equals(""))
            {
                tableName = kClass.getSimpleName();//得到class執行個體的類名字
                System.out.println(tableName);
            }
            sql = "select * from "+tableName;
        }
//        System.out.println(sql);xd
        List<Goods_In> list= BaseDao.queryList(sql,new Goods_In());
//        List<K> list2= BaseDao.queryList(sql,kClass);
        for (Goods_In s : list)
        {
            System.out.println(s);
//            System.out.println(s.getGoods_name());
//            s.setGoods_id(1);
        }
//        System.out.println(list);
//        return BaseDao.queryList(sql,<K>);
//        return (List<K>) list;
//        List list1 = new ArrayList();
//        return BaseDao.queryList(sql,(List<K>) list);
        return null;
    }

    public static void main(String[] args) {
        TableJdbc.queryAll(Goods_In.class);
//        TableJdbc.queryAll(new Goods_In().getClass());
    }
}
           

測試

package com.aaa.Test;

import com.aaa.Reflect_Two_day.BaseDao;
import com.aaa.comment.Goods_In;
import com.aaa.utlis.TableJdbc;

import java.util.List;

public class MyaJbdc<K> {
    public static <K> List<K> queryAll(Class<K> kClass) {
        String sql = "";
        if (kClass.isAnnotationPresent(Mya.class)) {
            Mya annotion = kClass.getAnnotation(Mya.class);//得到自定義注解對象TableAnnotation
            String tableName = annotion.Mya();
            if (tableName.equals("")) {
                System.out.println("");
                tableName = kClass.getSimpleName();
                System.out.println(tableName);
            }
            sql = "select * from " + tableName;
        }
        List<Goods_In> list = BaseDao.queryList(sql, new Goods_In());
        for (Goods_In a : list) {
            System.out.println(a);
            System.out.println();
        }
        return null;
    }

    public static void main(String[] args) {
        TableJdbc.queryAll(Goods_In.class);
    }
}
           

總結

以上就是今天要講的内容,本文僅僅簡單介紹了注解和泛型的使用,當然,筆者深度欠缺,如有不足,還請指正。

繼續閱讀