8、注解
三种常用的注解
- @SuppressWarnings("deprecation"):不提示编译警告
- @Deprecated:给自己编写的方法添加过时警告。
- @Override:强制表明下面的方法是覆盖。
下面是常用注解和自定义注解的演示代码
1、定义注解
package cn.itcast.day2;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import cn.itcast.day1.EnumTest;
/**
* 添加元注解,限定注解的生命周期和目标位置
* “@Retention”元注解有三种取值,
* RetetionPolicy.SOURCE:Java原文件;
* RetetionPolicy.CLASS:class文件;(默认)
* RetetionPolicy.RUNTIME:内存中的字节码。
*
* “@Target()”指定此注解使用的位置。
* ElementType.METHOD:方法
* ElementType.TYPE:类、接口、枚举等
* */
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.METHOD,ElementType.TYPE})
public @interface MyAnnotation {
/**
* 为注解增加属性
*
* */
//可以设置默认属性,使用的时候可以不指定此属性的值。
String color() default "blue";
//如果只有一个value,使用的时候可以不写“value=”
String value();
//数组类型的属性,如果数组只有一个元素,可以省略{}
int[] arrayAttr() default {3,4,5};
EnumTest.TrafficLamp lamp() default EnumTest.TrafficLamp.RED;
MetaAnnotation annotationAttr() default @MetaAnnotation("lwp");
}
2、使用方法
package cn.itcast.day2;
@MyAnnotation(annotationAttr=@MetaAnnotation("zzz"),color="red",value="abc",arrayAttr=1)
public class AnnotationTest {
/**
* 注解:
* 1,@SuppressWarnings("deprecation"):不提示编译警告
* 2,@Deprecated:给自己编写的方法添加过时警告。
* 3,@Override:强制表明下面的方法是覆盖。
*
* @param args
*/
@SuppressWarnings("deprecation")
@MyAnnotation("xyz")
public static void main(String[] args) {
System.runFinalizersOnExit(true);
//检查是否存在指定的注解
if(AnnotationTest.class.isAnnotationPresent(MyAnnotation.class)){
MyAnnotation annotation = (MyAnnotation) AnnotationTest.class.getAnnotation(MyAnnotation.class);
System.out.println(annotation.color());
System.out.println(annotation.value());
System.out.println(annotation.arrayAttr());
System.out.println(annotation.lamp().nextLamp().name());
System.out.println(annotation.annotationAttr().value());
};
}
@Deprecated
public static void sayHello(){
System.out.println("Hello World!");
}
@Override
public boolean equals(Object obj) {
return super.equals(obj);
}
}
/*//定义注解类
@interface A
{
}*/
9、泛型
泛型用于告诉编译器,编译完毕后将除去泛型标记。
一、术语(以ArrayList<E>为例):
1,整个ArrayList<E> 称为泛型类型
2,其中的E称为类型变量或类型参数
3,整个ArrayList<Integer>称为参数化的类型
4,其中的Integer成为类型参数的实例或实际类型参数
5,其中的<>念作:typeof
6,ArrayList称为原始类型
二、兼容性
1,参数化类型可以引用一个原始类型的对象,编译报告警告。
Collection<String> c = new Vector();
2,原始类型可以引用一个参数化类型的对象,编译报告警告。
Collection c = new Vector<String>();
三、参数化类型不考虑类型参数的继承关系。
错误:Vector<String> v = new Vector<Object>();
错误:Vector<Object> v = new Vector<String>();
四、在创建数组实例时,数组的元素不能使用参数化类型。
错误:Vector<Integer> vectorList[] = new Vector<Integer>[10];
五、? 通配符
使用?通配符可以引用其他各种参数化的类型,?通配符定义的变量主要用作引用,可以调用与参数化无关的方法,不可调用与参数化有关的方法。
通配符的扩展: <? extends Number>表示任意Number类的子类,上界限定。
<? super Integer>表示任意Integer的父类,下界限定。
可以用 & 限定多个边界。
在JSP页面中也经常要对Set或Map集合进行迭代。
六、只有引用类型才能作为泛型的实际参数。
七、泛型方法:
在返回值类型前定义泛型。调用泛型方法时实际传递的参数类型或返回值的类型推断:
1、当某个类型变量只在整个参数列表中的所有参数和返回值中的一处被应用了,那么根据调用方法的实际应用类型来确定。
例如:swap(new String[3],3,4) → static <E> void swap(E[] a,int i,int j)
2、当某个类型变量在整个参数列表中的所有参数和返回值中的多处被应用了,如果调用方法时多处的实际应用类型都对应同一种类型来确定。
例如:add(3,5) → static <T> T add(T a,T b)
3、当某个类型变量在整个参数列表中的所有参数和返回值中的多处被应用了,如果调用方法时这多处的实际应用类型对应到了不同的类型,且没有使用返回值,这时候取多个参数中的最大交集类型。
例如:fill(new Integer[3],3.5f) → static <T> void fill(T[] a,T v)
实际对应类型是Number,编译没有问题,只是运行时出问题。
4、当某个类型变量在整个参数列表中的所有参数和返回值中的多处被应用了,如果调用方法时这多处的实际应用类型对应到了不同的类型,并且使用返回值,这时候优先考虑返回值的类型。
例如:int x = (3,3.5f) → static <T> T add(T a,T b)
实际对应类型是Integer,编译时将报错,将变量x的类型改为Number则没有了错误。
5、参数类型的类型推断具有传递性,
下面第一种情况推断实际参数类型为Object,编译没有问题;而第二种情况则根据参数化的Vector类实例将类型变量直接确定为String类型,编译将出现问题。
copy(new Integer[5],new String[5]) → statci <T> void copy(T[] a,T[] b)
copy(new Vector<String>(),new Integer[5]) → static <T> void copy(Collection<T> a,T[] b)
package cn.itcast.day2;
import java.lang.reflect.Method;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
import java.util.Vector;
import cn.itcast.day1.ReflectPoint;
public class GenericTest {
public static void main(String[] args) throws Exception{
// TODO Auto-generated method stub
ArrayList<String> collection = new ArrayList<String>();
// collection.add(1);
// collection.add(1L);
collection.add("只能加入字符串");
String str = collection.get(0);
System.out.println(str);
ArrayList<Integer> collection1 = new ArrayList<Integer>();
System.out.println(collection.getClass() == collection1.getClass());
//绕过编译器,可以添加不同于泛型规定的类型
// collection1.add("abc");
collection1.getClass().getMethod("add", Object.class).invoke(collection1, "abc");
System.out.println(collection1.get(0));
//泛型的综合练习:对HashMap集合进行迭代
HashMap<String,Integer> maps = new HashMap<String,Integer>();
maps.put("name1", 21);
maps.put("name2", 22);
maps.put("name3", 20);
Set<Map.Entry<String,Integer>> entrySet = maps.entrySet();
for (Map.Entry<String, Integer> entry : entrySet) {
System.out.println(entry.getKey()+" : "+entry.getValue());
}
swap(new String[]{"a","b","c"}, 0, 1);
//自定义泛型类:GenericDao
GenericDao<ReflectPoint> dao = new GenericDao<ReflectPoint>();
dao.add(new ReflectPoint(3,3));
//String s Vector<E>findById(1);
//通过反射获得泛型的实际类型参数
//Vector<Date> v1 = new Vector<Date>();
Method applyMethod = GenericTest.class.getMethod("applyVector", Vector.class);
Type[] types = applyMethod.getGenericParameterTypes();
ParameterizedType pType = (ParameterizedType)types[0];
System.out.println(pType.getRawType());//原始类型
System.out.println(pType.getActualTypeArguments()[0]);//实际类型
}
public static void applyVector(Vector<Date> v1){
}
//交换数组中两个元素的位置
private static <T> void swap(T[] a,int i,int j){
T tmp = a[j];
a[i] = a[j];
a[j] = tmp;
}
}
自定义泛型类
package cn.itcast.day2;
import java.util.Set;
/**
*泛型类
*/
public class GenericDao<E> {
/**
* Dao:Data Access Object
* CRUD:数据库的“增删改查”
*/
public void add(E x){
}
public E findById(int id){
return null;
}
public void delete(E obj){
}
public void delete(int id){
}
public void update(E obj){
}
public E findByUserName(String name){
return null;
}
public Set<E> findByConditions(String where){
return null;
}
}