注解和泛型
面試題 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 自動列印日志 思路分析:

日志注解:
@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);
}
}
總結
以上就是今天要講的内容,本文僅僅簡單介紹了注解和泛型的使用,當然,筆者深度欠缺,如有不足,還請指正。