Java基础---Java---基础加强---内省的简单运用、注解的定义与反射调用、 自定义注解及其应用、泛型及泛型的高级应用、泛型集合的综合


内省的简单运用:

JavaBean是一种特殊的Java类,主要用于传递数据信息,这种java类中的方法主要用于访问私有的字段,且方法名符合某种命名规则。

采用遍历BeanInfo的所有属性方式来查找和设置某个RefectPoint对象的x属性。在程序中把一个类当作JavaBean来看,就是调用IntroSpector.getBeanInfo方法, 得到的BeanInfo对象封装了把这个类当作JavaBean看的结果信息。


import java.beans.BeanInfo;
import java.beans.IntrospectionException;
import java.beans.Introspector;
import java.beans.PropertyDescriptor;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.sql.Date;
import java.util.Map;


import org.apache.commons.beanutils.BeanUtils;
import org.apache.commons.beanutils.PropertyUtils;


/**
 * 内省的简单运用。
 * @author hjl
 *
 */
public class IntroSpectorTest {


	public static void main(String[] args) throws Exception {
	
		ReflectPoint pt1=new ReflectPoint(3, 5);
		String propertyName="x";
		//"x"--->"X"-->"getX"--->"MethodGexX"-->
		Object retVal = getProperty(pt1, propertyName);
		System.out.println(retVal);
		
		Object value =7;
		setProperties(pt1, propertyName, value);
		
		System.out.println(BeanUtils.getProperty(pt1,"x").getClass());
		
		BeanUtils.setProperty(pt1, "x", "9");
		
		System.out.println(pt1.getX());
		
		//java7新特性
		/*
		Map<K, V> map=(name:"hjl",age:18);
		BeanUtils.setProperty(map, "name", "lhm");
		*/
		BeanUtils.setProperty(pt1,"birthday.time", "111");
		
		System.out.println(BeanUtils.getProperty(pt1, "birthday.time"));
		
		PropertyUtils.setProperty(pt1,"x", 9);
		System.out.println(PropertyUtils.getProperty(pt1, "x").getClass());
	}


	private static void setProperties(Object pt1, String propertyName,
			Object value) throws IntrospectionException,
			IllegalAccessException, InvocationTargetException {
		PropertyDescriptor pd2=new  PropertyDescriptor(propertyName, pt1.getClass());
		Method methodSetX=pd2.getWriteMethod();//得到属性的get方法。
		methodSetX.invoke(pt1,value);
	}


	private static Object getProperty(Object pt1, String propertyName)
			throws IntrospectionException, IllegalAccessException,
			InvocationTargetException {
//		PropertyDescriptor pd=new  PropertyDescriptor(propertyName, pt1.getClass());
//		Method methodGetX=pd.getReadMethod();//得到属性的get方法。
//		Object retVal=methodGetX.invoke(pt1);
//		return retVal;
		
		BeanInfo beanInfo=Introspector.getBeanInfo(pt1.getClass());
		PropertyDescriptor[] pds=beanInfo.getPropertyDescriptors();
		Object retVal=null;
		for(PropertyDescriptor pd:pds){
			if(pd.getName().equals(propertyName)){
				Method methodGetX=pd.getReadMethod();
				retVal=methodGetX.invoke(pt1);
				break;
			}
		}
		
		return retVal;
	}
}


注解:
通过System.runFinalizersOnExit(true);的编译警告引出@SuppressWarnings("deprecation") 
@Deprecated
直接在刚才的类中增加一个方法,并加上@Deprecated标注,在另外一个类中调用这个方法。
@Override
public boolean equals(Reflect other)方法与HashSet结合讲解
总结:
注解相当于一种标记,在程序中加了注解就等于为程序打上了某种标记,没加,则等于没有某种标记,以后,javac编译器,开发工具和其他程序可以用反射来了解你的类及各种元素上有无何种标记,看你有什么标记,就去干相应的事。标记可以加在包,类,字段,方法,方法的参数以及局部变量上。
看java.lang包,可看到JDK中提供的最基本的annotation。 



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




//元注解
//元数据
//元信息
@Retention(RetentionPolicy.RUNTIME)//注解的注解,是为这个注解服务的。
//这个让注解保留在运行阶段
@Target({ElementType.METHOD,ElementType.TYPE})
public @interface Annotation {


	String color() default "blue";
	String value();
	int [] arrayAttr() default {3,4,4};
	EnumTest.TrafficLamp lamp() default EnumTest.TrafficLamp.Red; 
	MetaAnnotation annotationAttr() default @MetaAnnotation("ssh");
}

自定义注解及其应用:

/**
 * 
 * @author hjl
 *
 */
@Annotation(annotationAttr=@MetaAnnotation("ssID"), color="red",value="haha",arrayAttr=1)
public class AnnotationTest {


	@SuppressWarnings("deprecation")
	//@Annotation("haha")
	public static void main(String[] args) throws Exception {
		System.runFinalizersOnExit(true);
		//对一个类进行检查,利用反射
		if(AnnotationTest.class.isAnnotationPresent(Annotation.class)){
			Annotation annotation=(Annotation) AnnotationTest.class.getAnnotation(Annotation.class);
			//为什么用type,因为type中包含了class,type中有许多class
			//这个类的实例对象是通过反射找到的。
			System.out.println(annotation);
			System.out.println(annotation.color());
			System.out.println(annotation.arrayAttr().length);
			System.out.println(annotation.lamp().nextLamp());
			System.out.println(annotation.annotationAttr().value());
		}
	}
	
	//对于那些过时的方法,我们可以进它进行注解,以便编译器还能编译
	@Deprecated //表示过时
	public static void sayHello(){
		System.out.println("hello,world!");
	}
}


泛型:
泛型中的通配符,?
使用?通配符可以引用其他各种参数化的类型,?通配符定义的主要用作引用,可以引用调用与参数化无关的方法,不能调用与参数化有关的方法。
泛型的实例又是一个带参数化的类型。

在定义泛型的时候,也可以限定类型,同时可以定义多个接口。
用下面的代码说明对异常如何采用泛型:

private static <T extends Exception> sayHello() throws T
{
try{
}catch(T|e){
throw(T)e;
}

}


import java.lang.reflect.Constructor;
import java.lang.reflect.Method;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
import java.util.Vector;


import day01.ReflectPoint;


public class GenericTest {


	/**
	 * @param args
	 */
	public static void main(String[] args) throws Exception {
		// TODO Auto-generated method stub
		ArrayList collection1 = new ArrayList();
		collection1.add(1);
		collection1.add(1L);
		collection1.add("abc");
		//int i = (Integer)collection1.get(1);
		
		ArrayList<String> collection2 = new ArrayList<String>();
		//collection2.add(1);
		//collection2.add(1L);
		collection2.add("abc");
		String element = collection2.get(0);	
		
		//new String(new StringBuffer("abc"));
		Constructor<String> constructor1 = String.class.getConstructor(StringBuffer.class);
		String str2 = constructor1.newInstance(/*"abc"*/new StringBuffer("abc"));
		System.out.println(str2.charAt(2));		
		
		ArrayList<Integer> collection3 = new ArrayList<Integer>();
		System.out.println(collection3.getClass() == collection2.getClass());
		//collection3.add("abc");
		collection3.getClass().getMethod("add", Object.class).invoke(collection3, "abc");
		System.out.println(collection3.get(0));
		
		printCollection(collection3);
		
		//Class<Number> x = String.class.asSubclass(Number.class);
		Class<?> y;
		Class<String> x ;//Class.forName("java.lang.String");
		
		HashMap<String,Integer> maps = new HashMap<String, Integer>();
		maps.put("zxx", 28);
		maps.put("lhm", 35);
		maps.put("flx", 33);
		
		Set<Map.Entry<String,Integer>> entrySet = maps.entrySet();
		for(Map.Entry<String, Integer> entry : entrySet){
			System.out.println(entry.getKey() + ":" + entry.getValue());
		}
		
		add(3,5);
		Number x1 = add(3.5,3);//前面为什么是Number,因为float,int的交集是Number
		Object x2 = add(3,"abc");
		
		swap(new String[]{"abc","xyz","itcast"},1,2);
		//swap(new int[]{1,3,5,4,5},3,4);//泛型的类型,只能是引用类型,不能是基本类型
		//只有引用类型才能作为泛型方法的实际参数。这是基于自动装箱,拆箱的功能,
		//本身如果就是基本类型的话,本身如果要的就是这种基本类型的话,如果装箱的话,就是多此一举了
		Object obj = "abc";
		String x3 = autoConvert(obj);
		
		copy1(new Vector<String>(),new String[10]);
		copy2(new Date[10],new String[10]);		
		//copy1(new Vector<Date>(),new String[10]);//类型摧断具有传播性
		
		GenericDao<ReflectPoint> dao = new GenericDao<ReflectPoint>();
		dao.add(new ReflectPoint(3,3));		
		//String s = dao.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 fillArray(T[] a,T obj){
		for(int i=0;i<a.length;i++){
			a[i] = obj;//定义一个方法,可以将任意类型的数组中的所有元素填充为相应类型的某个对象。
		}
	}
	private static <T> T autoConvert(Object obj){
		return (T)obj;//定义一个泛型方法,自动将Object类型的对象转变成其他类型。
	}
	private static <T> void swap(T[] a,int i,int j){
		T tmp = a[i];
		a[i] = a[j];
		a[j] = tmp;
	}
	
	private static <T> T add(T x,T y){
		//声明了一个新的类型,T x,T y是把T这种类型的变量与另一个T类型的变量进行相加
		//返回的结果还是T这种类型的结果。在返回值之前,我们用<>来说明这种类型
		return null;
	}
	
	public static void printCollection(Collection<?> collection){
		//collection.add(1);
		System.out.println(collection.size());
		for(Object obj : collection){
			System.out.println(obj);
		}
	}
	
	public static <T> void printCollection2(Collection<T> collection){
		//collection.add(1);
		System.out.println(collection.size());
		for(Object obj : collection){
			System.out.println(obj);
		}


	}
	
	
	public static <T> void copy1(Collection<T> dest,T[] src){
		//定义一个方法,把任意参数类型的集合中的数据安全地复制到相应类型的数组中。
		for(int i=0;i<src.length;i++){
			dest.add(src[i]);
		}
	}
	
	public static <T> void copy2(T[] dest,T[] src){
		//定义一个方法,把任意参数类型的一个数组中数据安全复制到相应类型的另一个数组中。
	}	
}


普通方法,构造方法和静态方法都可以定义泛型。
也可以用类型变量表示异常,称为参数化的异常,可以用于throws列表中,但是不能用于catch子句中。
import java.util.Set;


//dao data access object--->crud
public class GenericDao<E>  {
	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 static <E> void update2(E obj){
		
	}
	
	public E findByUserName(String name){
		return null;
	}
	public Set<E> findByConditions(String where){
		return null;
	}
}

你可能感兴趣的:(注解的定义与反射调用,自定义注解及其应用,内省的简单运用)