黑马程序员--<Java 1.5新特性下>泛型与注解

--------------android培训java培训、学习型技术博客、期待与您交流! --------------

 

一、泛型(Generic)

泛型:就是指在对象建立时不指定类中属性的具体类型,而由外部在声明及实例化对象时指定具体的类型。

      由于添加的元素类型不同,所以元素类型会进行自动提示为Object,所以取出集合中的元素时需要强转,但是类型各异,所以就会产生ClassCastException(类型转换异常),为了避免该种潜在威胁,就出现了一种安全机制--泛型。

泛型只是编译时的概念,是功编译器进行语法检查用的。主要目的有两个方面:

    1、努力将运行时异常转换成编译时错误,减少运行时异常数量。

    2、解决模板编程的问题。

       泛型采用的是<>标记,在程序中,只要用到了带有<>的类或者接口,就要明确传入的具体引用数据类型 ,其实<>就是一个用于接收具体引用数据类型的参数范围,如ArrayList中存入的元素时String,定义格式为: List<String> list = new ArrayList<String>();。

泛型的原理:

     1、泛型的擦除:由于泛型是从jdk1.5开始的,所以为了兼容前面的类加载器,所以编译后的字节码是不存在泛型的概念的。

      2、泛型的补偿机制:泛型已经擦除,所以就产生了一种补偿机制,使用元素的getClass方法,得到类型后,就不需要强转了。

泛型是实现是在编译时期检查类型,当类型检查完成后,就进行泛型擦除,然后再进行泛型补偿,达到将运行时异常转化为编译时异常,与减少强转的目的。

 

类型参数中的通配符约束

<?>允许所有泛型的引用调用,参数未指定泛型默认为<?>

<? extends 类名>只允许该类及其子类的引用调用

<? super 类名>只允许该类以及其父类的引用调用

<? extends 接口名>只允许该接口以及该接口的实现类的引用调用

 

泛型方法中的通配符约束

<?>允许所有泛型的引用调用

<? extends 类名>只允许该类及其子类的引用调用

<? extends 接口名>只允许该接口以及该接口的实现类的引用调用

<? extends 接口名&类名>只允许泛型为继承该类又实现该接口的类

 

泛型类中的通配符约束与泛型方法相同

编写泛型类需要注意的地方:

1、静态方法中不能使用类的泛型,因为泛型类中的泛型在创建类的对象是被替换为确定类型。静态方法可以通过类名直接访问,还没有传入参数,因此会报错。

2、不能再Catch字句中使用泛型,因为编译时,如果try字句抛出的是已检查一次,编译器无法确定Catch中能不能捕获该异常。

 泛型方法定义示例

package cn.itheima.blog7;

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

public class GenericMethodDefine {

	/**
	 * 自定义泛型方法演示(下限,上限等)
	 */
	public static void main(String[] args) {
		//创建三个对象数组
		Number[] a1 = new Number[2];
		Double[] a2 = new Double[2];
		String[] a3 = new String[2];
		
		//创建两个集合
		List<Number> l1= new ArrayList<Number>();
		List<String> l2 = new ArrayList<String>();
		
		//将数组中的数据添加到集合中
		array2List(a1, l1);
		array2List(a2, l1);
		array2List(a3, l2);
	}
	 //Number及其子类
	public static <T extends Number> void array2List(T[] a, List<T> l){
		for(T o : a){
			l.add(o);
		}
		System.out.println(l);
	}
	//既是Number子类又是Comparable的实现类
	/*public static <T extends Number & Comparable> void array2List(List<T> l, T[] a){
		for(T o : a){
			l.add(o);
		}
	}*/

	//Comparable的实现类
	public static <T extends Comparable> void array2List(T[] a, List<T> l){
		for(T o : a){
			l.add(o);
		}
		System.out.println(l);
	}
}


 

二、注解(Annotation)

 

注解:相当于一个标记,加上了注解等于为程序加入了某种标记,开发工具和其他程序通过反射来了解类及个元素上有无标记,有标记就做该标记对应的操作。

注解的位置:加在包、类,字段,方法,方法的参数以及局部变量上

1、java.lang包中最基本的三种注解

        @Override:主要用在方法覆盖时使用,用于保证方法覆盖的正确性。当子类覆盖方法不正确时,就会报错。

        @Deprecated:用来声明一个不建议使用的方法,如果在程序中使用了该方法,则在编译时将出现过时警告,在Eclipse中会划线。随着Jdk的升级,许多方法会过时,但是为了顾及以前用该方法开发的项目,又不能删除该方法,但是又不建议使用,因此就会使用该注解。

        @SuppressWarning:用来压制警告。在前面的泛型中,若一个类声明时没有指明泛型,则肯定在编译时产生警告,用了@SuppressWarning就不会显示这些警告。

@SuppressWarning中的关键字

 

2、自定义Annotation

      定义格式:

    [public] @interface  名称{

       数据类型 变量名称();

   }

    在程序中只要使用了@interface声明Annotation,那么此Annotation实际上相当于实现了lang包下的Annotation接口

向Annotation中设置内容,即为注解添加属性

     Annotation中设置内容类似接口中函数的定义,如添加一个name属性,类型为String,可写为[public] String name();,其中的public为默认值,就像接口默认为public abstract。也可以为设置的内容添加默认值,格式为[public] String name default 默认值。

     自定义时,参数类型是有范围的, 八种基本数据类型,String,Class,枚举,注解及前面五种类型的数组。下面演示自定义简单注解及其使用:

package cn.itheima.blog7;

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

enum Weekday{
	SUN,MON,TUE,WEN,THU,FRI,SAT;
}

/*
 * 演示String,基本数据,数组,class
 */
//@Retention的使用
@Retention(RetentionPolicy.RUNTIME)

//@Tatget的使用
@Target(value = ElementType.METHOD)
@interface  ItheimaAnnotation {
	String name();
	int length();
	Class clazz();
	
}

/*
 * 演示数组,枚举,注解的使用,并设定默认值
 */
@interface  ItheimaAnnotation_2{
	//当数组中的值为一个时,可以不用花括号包装
	int[] arrayAttr() default {1}/*1*/;
	Weekday value();
	SuppressWarnings warning() default @SuppressWarnings("deprecation");
}
package cn.itheima.blog7;

public class ItheimaAnnotationDemo {

	/**
	 * 演示自定义Annotation的使用
	 */
	public static void main(String[] args) {
		show();
	}
	
	@ItheimaAnnotation(name = "heima", length = 5, clazz = String.class)
	//当属性为value,且其他属性有默认值时,可以省略value=不写,直接传入数值
	@ItheimaAnnotation_2(Weekday.FRI)
	public static void show(){
		
	}

}

 

3RetentionRetentionPolicy
在注解中,可以使用Retention定义一个注解的保存范围,Retention的定义中有一个value属性,类型为RetentionPolicyRetentionPolicy中包含的范围有三种
1SOURCE:此注解类型的信息指挥保存在.java文件中,编译之后不保存。
2CLASS:此类型的注解保存在.java.class文件中,此类使用时,信息不回加载到虚拟机中,如果注解在声明时未指定范围,默认为此范围。
3RUNTIME:此类型的注解保存在.java.class文件中,也会加载到虚拟机。

4Target注解,用来指定注解使用的位置
1public static final ElementType PACKAGE:只能用在包声明
2public static final ElementTypeFIELD:只能用在字段声明(包括枚举常量)上
3public static final ElementTypeANNOTATION_TYPE:只能用在注释类型声明上
4public static final ElementTypeCONSIRUCTOR:只能用在构造器声明上
5public static final ElementTypeMETHOD只能用在方法声明上
6public static final ElementTypePARAMETER只能用在参数声明上
7public static final ElementTypeTYPE只能用在类、接口、或枚举声明上
8public static final ElementType LOCAL_VARIABLE只能用在局部变量声明上

5、通过反射取得Annotation
步骤:
     (1)取得运用注解的类
     (2)取得类中运用注解的部分,如方法
     (3)取得注解内容

    结合前面自定义注解演示反射取得Annotation

package cn.itheima.blog7;

import java.lang.reflect.Method;

public class ReflectAnnotation {

	/**
	 * @param args
	 * @throws Exception 
	 * 获取Annotation指定属性的值
	 */
	public static void main(String[] args) throws Exception {
		//得到运用注释的类
		Class c = Class.forName("cn.itheima.blog7.ItheimaAnnotationDemo");
		//得到类中运用注解的方法
		Method method = c.getMethod("show");
		//若指定的注释类型运用在此方法上
		if(method.isAnnotationPresent(ItheimaAnnotation.class)){
			//获取注释类型对象
			ItheimaAnnotation ia = method.getAnnotation(ItheimaAnnotation.class);
			//取值
			String name = ia.name();
			System.out.println(name);
		}
	}

}


 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值