Java泛型、反射和注解

Java泛型、反射和注解

本文是基于Windows 10系统环境,学习和使用java泛型、反射和注解

  • Windows 10
  • MyEclipse 10

一、泛型

(1) 基本概念

  • 泛型方法的定义
public <T,K> T save(T t, K k){
	return t;
}
  • 泛型类的定义
public class GenericDemo<T>{
	public T save(T t){
		return t;
	}
}
  • 泛型接口的定义
public interface IBaseDao<T> {
	void save(T t);
}
  • ?关键字
public class App_extends_super {
	
	//只带泛型特征的方法
	public void save(List<?> list) {
		// 只能获取、迭代list;  不能编辑list
	}
	@Test
	public void testGeneric() throws Exception {
		// ?  可以接收任何泛型集合, 但是不能编辑集合值; 所以一般在方法参数中用
		List<?> list = new ArrayList<String>();
		//list.add("");// 报错
	}
}
  • extends关键字
public class App_extends_super {
	
	
	/**
	 * list集合只能处理 Double/Float/Integer等类型
	 * 限定元素范围:元素的类型要继承自Number类  (上限)
	 * @param list
	 */
	public void save(List<? extends Number> list) {
	}
	@Test
	public void testGeneric() throws Exception {
		List<Double> list_1 = new ArrayList<Double>();
		List<Float> list_2 = new ArrayList<Float>();
		List<Integer> list_3 = new ArrayList<Integer>();
		
		List<String> list_4 = new ArrayList<String>();
		
		// 调用
		save(list_1);
		save(list_2);
		save(list_3);
		//save(list_4);  会报错
	}
}
  • super关键字
/**
 * 泛型, 涉及到一些关键字
 * 
 * Ctrl + shift + R   查看当前项目中类
 * Ctrl + shift + T   查看源码jar包中的类
 * @author Jie.Yuan
 *
 */
public class App_super {
	/**
	 * super限定元素范围:必须是String父类   【下限】
	 * @param list
	 */
	public void save(List<? super String> list) {
	}
	@Test
	public void testGeneric() throws Exception {
		// 调用上面方法,必须传入String的父类
		List<Object> list1 = new ArrayList<Object>();
		List<String> list2 = new ArrayList<String>();
		
		List<Integer> list3 = new ArrayList<Integer>();
		//save(list3);  会报错
	}
}
  • 声明泛型时,两端类型必须一致
List<Object> list = new ArrayList<Object>();
List<String> list1 = new ArrayList<String>();
// 两端类型必须一致,编译会报错
List<Object> list2 = new ArrayList<String>();
  • 泛型的类型只能是引用类型,不能是基本类型
// 编译会报错,因为泛型的类型不能是基本类型
List<int> list3 = new ArrayList<int>();

(2) 泛型擦除

  • 泛型只在编译时期有效,编译后的字节码文件中不存在有泛型信息!
// 编译会报错,因为编译器会认为参数都是List类型,不会认为是函数重载
public void save(List<Person> p);
public void save(List<String> name);

二、反射

(1) 反射技术

  • 反射定义
    可以在运行时期动态创建对象;获取对象的属性、方法。
  • Demo.java
/**
 * 
 */
package com.inspur.c_reflect;

import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;

import org.junit.Test;

/**
 * ClassName: Demo
 * Function: TODO ADD FUNCTION
 * @author: xuzheng
 * date: 2019-5-30 下午7:30:12
 */
public class Demo {
	@Test
	public void test1() throws Exception{
		String className = "com.inspur.c_reflect.Admin";
		Class<?> clazz = Class.forName(className);
		//创建对象1:默认构造函数简写
		//Admin admin = (Admin) clazz.newInstance();
		
		//创建对象2:通过带参数构造器创建对象
		Constructor<?> declaredConstructor = clazz.getDeclaredConstructor(String.class);
		declaredConstructor.newInstance("name");
	}
	
	//反射获取属性名称、值
	@Test
	public void test2() throws Exception{
		String className = "com.inspur.c_reflect.Admin";
		Class<?> clazz = Class.forName(className);
		Admin admin = (Admin) clazz.newInstance();
		
		Field[] fields = clazz.getDeclaredFields();
		for(Field f : fields){
			f.setAccessible(true);
			String name = f.getName();
			Object value = f.get(admin);
			System.out.println(name+ value);
		}
	}
	
	//反射获取方法对象
		@Test
		public void test3() throws Exception{
			String className = "com.inspur.c_reflect.Admin";
			Class<?> clazz = Class.forName(className);
			Admin admin = (Admin) clazz.newInstance();
			
			Method m = clazz.getDeclaredMethod("getId");
			Object value = m.invoke(admin);
			System.out.println(value);
		}
}
  • Admin.java
/**
 * 
 */
package com.inspur.c_reflect;

/**
 * ClassName: Admin
 * Function: TODO ADD FUNCTION
 * @author: xuzheng
 * date: 2019-5-30 ÏÂÎç7:29:19
 */
public class Admin {
	private int id = 100;
	private String name = "tom";
	public Admin(){
		System.out.println("Admin()");
	}
	public Admin(String name){
		System.out.println("Admin(name)");
	}
	public int getId() {
		return id;
	}
	public void setId(int id) {
		this.id = id;
	}
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	@Override
	public String toString() {
		return "Admin [id=" + id + ", name=" + name + "]";
	}
	
}

(2) 反射泛型

  • Demo.java
/**
 * 
 */
package com.inspur.b_reflect;

import org.junit.Test;

/**
 * ClassName: Demo
 * Function: TODO ADD FUNCTION
 * @author: xuzheng
 * date: 2019-5-30 ÏÂÎç4:14:36
 */
public class Demo {
	@Test
	public void test(){
		AdminDao adminDao = new AdminDao();
		Admin admin = adminDao.findById(1);
		System.out.println(admin);
		
		System.out.println(adminDao.getAll());
	}
}
  • Admin.java
/**
 * 
 */
package com.inspur.b_reflect;

/**
 * ClassName: Admin
 * Function: TODO ADD FUNCTION
 * @author: xuzheng
 * date: 2019-5-30 ÏÂÎç2:46:08
 */
public class Admin {
	private int id;
	private String userName;
	private String pwd;
	public int getId() {
		return id;
	}
	public void setId(int id) {
		this.id = id;
	}
	public String getUserName() {
		return userName;
	}
	public void setUserName(String userName) {
		this.userName = userName;
	}
	public String getPwd() {
		return pwd;
	}
	public void setPwd(String pwd) {
		this.pwd = pwd;
	}
	@Override
	public String toString() {
		return "Admin [id=" + id + ", userName=" + userName + ", pwd=" + pwd
				+ "]";
	}
	
}
  • Account.java
/**
 * 
 */
package com.inspur.b_reflect;

/**
 * ClassName: Account
 * Function: TODO ADD FUNCTION
 * @author: xuzheng
 * date: 2019-5-30 ÏÂÎç2:47:12
 */
public class Account {
	private int id;
	private String accountName;
	private double money;
	public int getId() {
		return id;
	}
	public void setId(int id) {
		this.id = id;
	}
	public String getAccountName() {
		return accountName;
	}
	public void setAccountName(String accountName) {
		this.accountName = accountName;
	}
	public double getMoney() {
		return money;
	}
	public void setMoney(double money) {
		this.money = money;
	}
	@Override
	public String toString() {
		return "Account [id=" + id + ", accountName=" + accountName
				+ ", money=" + money + "]";
	}
	
}
  • AdminDao.java
/**
 * 
 */
package com.inspur.b_reflect;

/**
 * ClassName: AdminDao
 * Function: TODO ADD FUNCTION
 * @author: xuzheng
 * date: 2019-5-30 ÏÂÎç4:34:59
 */
public class AdminDao extends BaseDao<Admin> {

}
  • AccountDao.java
/**
 * 
 */
package com.inspur.b_reflect;

/**
 * ClassName: AccountDao
 * Function: TODO ADD FUNCTION
 * @author: xuzheng
 * date: 2019-5-30 ÏÂÎç4:35:59
 */
public class AccountDao extends BaseDao<Account> {

}
  • BaseDao.java
/**
 * 
 */
package com.inspur.b_reflect;

import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.sql.SQLException;
import java.util.List;

import org.apache.commons.dbutils.handlers.BeanHandler;
import org.apache.commons.dbutils.handlers.BeanListHandler;

/**
 * ClassName: BaseDao
 * Function: TODO ADD FUNCTION
 * @author: xuzheng
 * date: 2019-5-30 ÏÂÎç2:48:47
 */
public class BaseDao<T> {
	private Class clazz;
	private String tableName;
	public BaseDao(){
		Type type = this.getClass().getGenericSuperclass();
		ParameterizedType pt = (ParameterizedType)type;
		Type[] types = pt.getActualTypeArguments();
		clazz = (Class)types[0];
		tableName = clazz.getSimpleName();
		System.out.println(tableName);
	}
	public T findById(int id) {
		String sql = "select * from "+ tableName + " where id=?";
		try {
			return JdbcUtils.getQueryRunner().query(sql, new BeanHandler<T>(clazz), id);
		} catch (SQLException e) {
			throw new RuntimeException(e);
		}
	}
	
	public List<T> getAll() {
		String sql = "select * from "+ tableName;
		try {
			return JdbcUtils.getQueryRunner().query(sql, new BeanListHandler<T>(clazz));
		} catch (SQLException e) {
			throw new RuntimeException(e);
		}
	}
}
  • JdbcUtils.java
/**
 * 
 */
package com.inspur.b_reflect;

import javax.sql.DataSource;

import org.apache.commons.dbutils.QueryRunner;

import com.mchange.v2.c3p0.ComboPooledDataSource;

/**
 * ClassName: JdbcUtils
 * Function: TODO ADD FUNCTION
 * @author: xuzheng
 * date: 2019-5-30 ĎÂÎç4:06:11
 */
public class JdbcUtils {
	private static DataSource dataSource;
	static{
		dataSource = new ComboPooledDataSource();
	}
	
	public static DataSource getDataSource(){
		return dataSource;
	}
	
	public static QueryRunner getQueryRunner(){
		return new QueryRunner(dataSource);
	}
}

三、注解

(1) 基本概念

  • 注解与注释
    注解,告诉编译器如何运行程序!
    注释, 给程序员阅读,对编译、运行没有影响;
  • 注解作用
    告诉编译器如何运行程序;
    简化(取代)配置文件 【案例后再看】
  • 常用的注解
  • Demo.java
	// 重写父类的方法
	@Override
	public String toString() {
		return super.toString();
	}
	
	// 抑制编译器警告
	@SuppressWarnings({"unused","unchecked"})
	private void save() {
		List list = null;
	}
	
	// 标记方法以及过时
	@Deprecated
	private void save1() {
	}

(2) 自定义注解

通过自定义注解,可以给类、字段、方法上添加描述信息!

a. 注解基本写法

  • Author.java
/**
 * 自定义注解  (描述一个作者)
 * @author xuzheng
 *
 */
public @interface Author {
	/**
	 * 注解属性
	 * 	  1. 修饰为默认或public
	 *    2. 不能有主体
	 */
	String name();
	int age();
}
  • 调用
@Author(name = "Jet", age = 30)
public void save() {
}

b. 带默认值的注解

  • Author.java
/**
 * 自定义注解  (描述一个作者)
 * @author xuzheng
 *
 */
public @interface Author {
	/**
	 * 注解属性
	 * 	  1. 修饰为默认或public
	 *    2. 不能有主体
	 */
	String name();
	int age() default 30; // 带默认值的注解;使用的时候就可以不写此属性值
}
  • 调用
@Author(name = "Jet")
public void save() {
}

c. 默认名称的注解

  • 注解属性名称为value,这就是默认名称
    • Author.java
/**
 * 自定义注解  (描述一个作者)
 * @author xuzheng
 *
 */
public @interface Author {
	// 如果注解名称为value,使用时候可以省略名称,直接给值
	// (且注解只有一个属性时候才可以省略名称)
	String value();
}
  • 调用
@Author("Jet")
@Author(value = "Jet")
  • 注解属性类型为数组
    • Author.java
/**
 * 自定义注解  (描述一个作者)
 * @author xuzheng
 *
 */
public @interface Author {
	String[] value() default {"test1","test2"};
}
  • 调用
@Author{"",""}public void save() {
}

(3) 元注解

元注解,表示注解的注解!

  • 1. 指定注解的可用范围
@Target({TYPE,FIELD,METHOD,PARAMETER,CONSTRUCTOR,LOCAL_VARIABLE})
//TYPE,     类
//FIELD,     字段
//METHOD,  方法
//PARAMETER,   参数
//CONSTRUCTOR, 构造器
//LOCAL_VARIABLE  局部变量
  • 2. 指定注解的声明周期
@Retention(RetentionPolicy.SOURCE)    //注解只在源码级别有效
@Retention(RetentionPolicy.CLASS)     //注解在字节码即别有效  默认值
@Retention(RetentionPolicy.RUNTIME)   //注解在运行时期有效

(4) 注解反射

  • Demo.java
@Id
@Author(remark = "保存信息!!!", age = 19)
public void save() throws Exception {
	// 获取注解信息: name/age/remark
	// 1. 先获取代表方法的Method类型;
	Class clazz = App_2.class;
	Method m = clazz.getMethod("save");
	// 2. 再获取方法上的注解
	Author author = m.getAnnotation(Author.class);
	// 获取输出注解信息
	System.out.println(author.authorName());
	System.out.println(author.age());
	System.out.println(author.remark());
}
  • Author.java
/**
 * 自定义注解  (描述一个作者)
 * @author xuzheng
 *
 */
// 元注解 - 1. 定义注解的可用范围
@Target({TYPE,FIELD , METHOD, PARAMETER, CONSTRUCTOR, LOCAL_VARIABLE})
//@Target({METHOD,FIELD,TYPE})   指定只能在方法、字段、类上用;

// 元注解 - 2. 指定注解的声明周期
@Retention(RetentionPolicy.RUNTIME)   // 字节码级别有效
public @interface Author {
	String authorName() default "Jet";
	int age() default 30;	
	String remark();
}

你可能感兴趣的:(Java)