zoukankan      html  css  js  c++  java
  • java中的泛型,注解

    泛型

    泛型是JDK1.5以后才有的, 可以在编译时期进行类型检查,且可以避免频繁类型转化!

            // 运行时期异常 
    	@Test
    	public void testGeneric() throws Exception {
    		// 集合的声明
    		List list = new ArrayList();
    		list.add("China");
    		list.add(1);
    		
    		// 集合的使用
    		String str = (String) list.get(1);
    		
    	}
    	
    	// 使用泛型
    	@Test
    	public void testGeneric2() throws Exception {
    		// 声明泛型集合的时候指定元素的类型
    		List<String> list = new ArrayList<String>();
    		list.add("China");
                    //list.add(1);// 编译时期报错
    		
    		String str = list.get(1); 
    	}
    

    泛型擦除,泛型只在编译时期有效,编译后的字节码文件中不存在有泛型信息!

            /*
    	 * 泛型擦除实例 
    	 */
    	public void save(List<Person> p){
    	}
    	public void save(List<Dept> d){    // 报错: 与上面方法编译后一样
    	}
    	*/
    

    泛型写法

            // 泛型写法
    	@Test
    	public void testGeneric3() throws Exception {
    		// 声明泛型集合,集合两端类型必须一致
    		List<Object> list = new ArrayList<Object>();
    		List<String> list1 = new ArrayList<String>();
    		List list2 = new ArrayList<String>();
    		List<Integer> list3 = new ArrayList();
    		
    		// 错误
    		//List<Object> list4 = new ArrayList<String>();
    		// 错误: 泛型类型必须是引用类型,不能为基本类型
    		List<int> list5 = new ArrayList<int>();
    	}
    

    泛型方法/泛型类/泛型接口

    作用:
    1. 设计公用的类、方法,对公用的业务实现进行抽取!
    2. 使程序更灵活!

    1. 泛型方法

    public class GenericDemo {
    
    	// 定义泛型方法
    	public <K,T> T save(T t,K k) {
    		return null;
    	}
    	
    	// 测试方法
    	@Test
    	public void testMethod() throws Exception {
    		// 使用泛型方法:  在使用泛型方法的时候,确定泛型类型
    		save(1.0f, 1);
    	}
    }
    

    2. 泛型类

    public class GenericDemo<T> {
    
    	// 定义泛型方法
    	public <K> T save(T t,K k) {
    		return null;
    	}
    	
    	public void update(T t) {
    
    	}
    	
    	// 测试方法
    	@Test
    	public void testMethod() throws Exception {
    		
    		// 泛型类:  在创建爱泛型类对象的时候,确定类型
    		GenericDemo<String> demo = new GenericDemo<String>();
    		demo.save("test", 1);
    	}
    }
    

    3. 泛型接口

    public interface IBaseDao<T> {
    	void save(T t );
    	void update(T t );
    }
    
    //泛型接口类型确定: 实现泛型接口的类也是抽象,那么类型在具体的实现中确定或创建泛型类的时候确定
    public class BaseDao<T> implements IBaseDao<T> {
    }
    //泛型接口类型确定: 在业务实现类中直接确定接口的类型
    public class PersonDao implements IBaseDao<Person>{
    }
    

    泛型关键字

    泛型中:
    ? 指定只是接收值
    extends 元素的类型必须继承自指定的类
    super 元素的类型必须是指定的类的父类

    1. 关键字 ?

    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("");// 报错
    	}
    }
    

    2. 关键字 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);
    	}
    }
    

    3. 关键字 super [下限]

    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);
    	}
    }
    

    泛型的反射

    • 反射泛型涉及API:
    1. ParameterizedType 参数化类型的表示
    2. Type 接口,任何类型默认的接口!包括: 引用类型、原始类型、参数化类型
    List<String>   list   =  new   ArrayList<String>();
    泛型集合:       list
    集合元素定义:   new   ArrayList<String>();  中的String
    参数化类型:     ParameterizedType  即:“ArrayList<String> ” 为参数化类型
    

    反射泛型案例

    public class AdminDao extends BaseDao<Admin> {}
    public class AccountDao extends BaseDao<Account> {}
    
    /**
     * 所有dao的公用的方法,都在这里实现
     */
    public class BaseDao<T>{
    	
    	// 保存当前运行类的参数化类型中的实际的类型
    	private Class clazz;
    	// 表名
    	private String tableName;
    	
    	// 构造函数: 1. 获取当前运行类的参数化类型; 2. 获取参数化类型中实际类型的定义(class)
    	public BaseDao(){
    		//  this  表示当前运行类  (AccountDao/AdminDao)
    		//  this.getClass()  当前运行类的字节码(AccountDao.class/AdminDao.class)
    		//  this.getClass().getGenericSuperclass();  当前运行类的父类,即为BaseDao<Account>
    		//                                           其实就是“参数化类型”, ParameterizedType   
    		Type type = this.getClass().getGenericSuperclass();
    		// 强制转换为“参数化类型”  【BaseDao<Account>】
    		ParameterizedType pt = (ParameterizedType) type;
    		// 获取参数化类型中,实际类型的定义  【new Type[]{Account.class}】
    		Type types[] =  pt.getActualTypeArguments();
    		// 获取数据的第一个元素:Accout.class
    		clazz = (Class) types[0];
    		// 表名  (与类名一样,只要获取类名就可以)
    		tableName = clazz.getSimpleName();
    	}
    	
    
    	/**
    	 * 主键查询
    	 * @param id	主键值
    	 * @return      返回封装后的对象
    	 */
    	public T findById(int id){
    		/*
    		 * 1. 知道封装的对象的类型
    		 * 2. 表名【表名与对象名称一样, 且主键都为id】
    		 * 
    		 * 即,
    		 *   ---》  得到当前运行类继承的父类  BaseDao<Account>
    		 *   ----》 得到Account.class
    		 */
    		
    		String sql = "select * from " + tableName + " where id=? ";
    		try {
    			return JdbcUtils.getQuerrRunner().query(sql, new BeanHandler<T>(clazz), id);
    		} catch (SQLException e) {
    			throw new RuntimeException(e);
    		}
    	}
    	
    	
    	/**
    	 * 查询全部
    	 * @return
    	 */
    	public List<T> getAll(){
    		String sql = "select * from " + tableName ;
    		try {
    			return JdbcUtils.getQuerrRunner().query(sql, new BeanListHandler<T>(clazz));
    		} catch (SQLException e) {
    			throw new RuntimeException(e);
    		}
    	}
    }
    

    反射

    • 反射,可以在运行时期动态创建对象;获取对象的属性、方法
    public class Admin {
    
    	// Field
    	private int id = 1000;
    	private String name = "匿名";
    	
    	// Constructor
    	public Admin(){
    		System.out.println("Admin.Admin()");
    	}
    	public Admin(String name){
    		System.out.println("Admin.Admin()" + name);
    	}
    	
    	// Method
    	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;
    	}
    	
    }
    
    // 反射技术
    public class App {
    
    	// 1. 创建对象
    	@Test
    	public void testInfo() throws Exception {
    		// 类全名
    		String className = "com.runbean_reflect.Admin";
    		// 得到类字节码
    		Class<?> clazz = Class.forName(className);
    		
    		// 创建对象1: 默认构造函数简写
    		//Admin admin = (Admin) clazz.newInstance();
    		
    		// 创建对象2: 通过带参数构造器创建对象
    		Constructor<?> constructor = clazz.getDeclaredConstructor(String.class);
    		Admin admin = (Admin) constructor.newInstance("Jack");
    		
    	}
    	@Test
    	//2. 获取属性名称、值
    	public void testField() throws Exception {
    		
    		// 类全名
    		String className = "com.runbean_reflect.Admin";
    		// 得到类字节码
    		Class<?> clazz = Class.forName(className);
    		// 对象
    		Admin admin =  (Admin) clazz.newInstance();
    		
    		// 获取所有的属性名称
    		Field[]  fs =  clazz.getDeclaredFields();
    		// 遍历:输出每一个属性名称、值
    		for (Field f : fs) {
    			// 设置强制访问
    			f.setAccessible(true);
    			// 名称
    			String name = f.getName();
    			// 值
    			Object value = f.get(admin);
    			
    			System.out.println(name + value);
    		}
    	}
    	
    	@Test
    	//3. 反射获取方法
    	public void testMethod() throws Exception {
    		
    		// 类全名
    		String className = "com.runbean_reflect.Admin";
    		// 得到类字节码
    		Class<?> clazz = Class.forName(className);
    		// 对象
    		Admin admin =  (Admin) clazz.newInstance();
    		
    		// 获取方法对象    public int getId() {
    		Method m = clazz.getDeclaredMethod("getId");
    		// 调用方法
    		Object r_value = m.invoke(admin);
    		
    		System.out.println(r_value);
    	}
    	
    }
    

    注解

    注解与注释,
    注解,告诉编译器如何运行程序!
    注释, 给程序员阅读,对编译、运行没有影响;

    注解作用,
    1. 告诉编译器如何运行程序;
    2. 简化(取代)配置文件

    自定义注解

    1. 注解基本写法

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

    2. 默认名称的注解

    public @interface Author {
    	// 如果注解名称为value,使用时候可以省略名称,直接给值
    	// (且注解只有一个属性时候才可以省略名称)
    	String value();
    }
    
    //使用
    @Author("runBean")
    @Author(value = "runBean")
    public void save() {
    
    }
    //注解属性类型为数组:
    public @interface Author {
    	String[] value() default {"test1","test2"};
    }
    //使用:
    @Author({“”,“”})
    public void save() {
    
    }
    

    元注解

    元注解,表示注解的注解!
    指定注解的可用范围:
    @Target({
    TYPE, 类
    FIELD, 字段
    METHOD, 方法
    PARAMETER, 参数
    CONSTRUCTOR, 构造器
    LOCAL_VARIABLE 局部变量
    })

    指定注解的声明周期
    @Retention(RetentionPolicy.SOURCE) 注解只在源码级别有效
    @Retention(RetentionPolicy.CLASS) 注解在字节码即别有效 默认值
    @Retention(RetentionPolicy.RUNTIME) 注解在运行时期有效

    1.注解的反射

    @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());
    	}
    

    注解:
    简化XML配置, 程序处理非常方便!
    不便于维护: 例如修改字段名,要重新编译

    XML
    便于维护! 需要些读取代码!

    关于作者:奔跑的五花肉

    本博客所有文章仅用于学习、研究和交流目的。

    博主的文章没有高度、深度和广度,只是凑字数。由于博主的水平不高,不足和错误之处在所难免,希望大家能够批评指出。

    博主是利用读书、参考、引用、抄袭、复制和粘贴等多种方式打造成自己的文章,请原谅博主成为一个无耻的文档搬运工!

  • 相关阅读:
    linux 运维 nginx服务器
    linux 运维,代理,acl控制访问
    shell脚本 awk工具
    shell脚本 sed工具
    shell脚本 字串截取 正则表达式
    Django ORM 反向查询
    Django model操作
    Form的is_valid校验规则及验证顺序
    Django 中的Form、ModelForm
    Django 中的Form表单认证
  • 原文地址:https://www.cnblogs.com/runbean/p/12591248.html
Copyright © 2011-2022 走看看