黑马程序员-java基础加强(二)

---------------------- ASP.Net+Unity开发.Net培训、期待与您交流! ----------------------


JavaBean内省:
JavaBean是一种特殊的java类,主要用于传递信息,这种java类中的方法主要用于访问私有的字段,且方法名称符合某种命名规则。
2.如果要在两个模块之间传递多个信息,可以将这些信息封装到一个JavaBean中,这种JavaBean的实例对象通常称之为值对象(Value Object)。
这些信息在类中用私有字段来存储,如果读取或设置这些字段的值,则需要通过一些相应的方法来访问。

JavaBean命名规则:
如果方法表明属性部分的第二个字母为小写,则属性名的第一个字母也改成小写。
例如:
setId()的属性名为id。
如果方法表明属性部分的第二个字母为大写,则属性名的第一个字母也改成大写。
例如:
getCPU的属性名为CPU。

PropertyDescriptor类:描述JavaBean的一个类。一些重要方法:
1.Class<?> getPropertyType(),获得属性的Class对象 
2.Method getReadMethod() ,获得读取属性的方法
3.Method getWriteMethod(), 获得设置属性值得方法
4.void setReadMethod(Method readMethod) ,设置应该用于读取属性值的方法
5.void setWriteMethod(Method writeMethod),设置应该用于写入属性值的方法  
例子:

//JavaBean

<span style="font-family:KaiTi_GB2312;font-size:18px;">class Point
{
	private  int x;
	private  int y;
	public Point(int x,int y) 
	{
		this.x = x;
		this.y = y;
	}
	
	public int getX() {
		return this.x;
	}
	
	public void setX(int x) {
		this.x = x;
	}
	
	public int getY() {
		return this.y;
	}
	
	public void setY(int y) {
		this.y = y;
	}	
}

public class test
{
	public static void main(String[] args) throws Exception
	{
		Point point = new Point(3, 4);
		String propertyName = "x";
		PropertyDescriptor pDescriptor = new PropertyDescriptor(propertyName, point.getClass());
		//获得读取属性名为propertyName 的属性值得方法
		Method method = pDescriptor.getReadMethod();
		//执行该方法,获得属性值
		Object retVal = method.invoke(point, null);
		System.out.println(retVal);
		//获得设置属性名为propertyName 的属性值得方法
		method = pDescriptor.getWriteMethod();
		//执行方法,设置属性值
		method.invoke(point, 5);
		//再次获得读取该属性值的方法
		method = pDescriptor.getReadMethod();
		retVal = method.invoke(point, null);
		System.out.println(retVal);
	}	
}</span>

BeanUtils:操作JavaBean的工具包。
重要方法:
1.BeanUtils.getProperty(Object bean, String name),获取相应属性名为name的属性的值
2.BeanUtils.setProperty(Object bean,String name, Object value),设置对应属性名的属性值。
例子:
public class test
{
     public static void main(String[] args) throws Exception
    {
         Point point = new Point(3, 4);
         String propertyName = "x";
         System.out.println(BeanUtils.getProperty(point, propertyName));
         BeanUtils.setProperty(point, propertyName, 4);
         System.out.println(BeanUtils.getProperty(point, propertyName));
    }
}

注解:

注解相当于一种标记,在程序中加上了注解,就相当于为程序打上了某种标记,java编译器,开发工具包和其他程序可以用反射来了解类及各种元素上有无标记,如有,就采取相应的操作。标记可以加载包,类,方法,字段,方法的参数以及局部变量上。

注解也是一种类,定义方式为: @interface 注解名

例如:

<span style="font-family:KaiTi_GB2312;font-size:18px;">@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.METHOD,ElementType.TYPE})
public @interface AnnotationTest 
{
	
}


@AnnotationTest
public class test
{
	public static void main(String[] args) throws Exception
	{
		if(test.class.isAnnotationPresent(AnnotationTest.class))
		{
			AnnotationTest annotationTest = (AnnotationTest)test.class.getAnnotation(AnnotationTest.class);
			System.out.println(annotationTest);
		}
	}	
}</span>

注解@Retention指示注释类型的注释要保留多久。它有三种取值:RetentionPolicy.SOURCE,RetentionPolicy.CLASS,RetentionPolicy.RUNTIME.
它的默认值是RetentionPolicy.CLASS。
RetentionPolicy.SOURCE:编译器要丢弃的注释。
RetentionPolicy.CLASS:编译器将把注释记录在类文件中,但在运行时 VM 不需要保留注释。
RetentionPolicy.RUNTIME:编译器将把注释记录在类文件中,在运行时 VM 将保留注释,因此可以反射性地读取。

@Target:指示注释类型所适用的程序元素的种类。其中的枚举常量为:
ANNOTATION_TYPE , 注释类型声明
CONSTRUCTOR,构造方法声明
FIELD,字段声明(包括枚举常量) 
LOCAL_VARIABLE,局部变量声明 
METHOD, 方法声明
PARAMETER , 包声明
PARAMETER,参数声明
TYPE, 类、接口(包括注释类型)或枚举声明

注:java.lang.reflect.Type是 Java 编程语言中所有类型的公共高级接口。它们包括原始类型、参数化类型、数组类型、类型变量和基本类型。

为注解增加各种属性:
能为注解增加各种属性是注解功能如此强大的原因。
注解有一个特殊的方法,即String value()。如果只有value属性需要设置,则用这个属性的时候可以不加属性名。
若有其他属性,可以将其他属性设置为缺省属性。
注解可以有数组属性,并设置相应的缺省值。
注解中可以有注解属性。
例如:

<span style="font-family:KaiTi_GB2312;font-size:18px;">public @interface MetaAnnotation 
{
	String value();
}

@Retention(RetentionPolicy.RUNTIME)//在编译时保留注释注释
@Target({ElementType.METHOD,ElementType.TYPE})
public @interface AnnotationTest 
{
	String color() default "red";
	String value();
	int[] arr() default {1,2,3,4};
	MetaAnnotation metaAnnotation() default @MetaAnnotation("meta");
}

@AnnotationTest(color="red",value="value",arr= {1,2,3},metaAnnotation=@MetaAnnotation("metaAgain"))
public class test
{
	public static void main(String[] args) throws Exception
	{
		if(test.class.isAnnotationPresent(AnnotationTest.class))//如果存在AnnotationTest注释
		{
			AnnotationTest annotationTest = (AnnotationTest)test.class.getAnnotation(AnnotationTest.class);//获得该注释对象
			System.out.println(annotationTest.value());		//打印对象中的value属性值
			for(int i=0; i<annotationTest.arr().length; i++)	//打印对象中的数组
				System.out.println(annotationTest.arr()[i]);
			System.out.println(annotationTest.metaAnnotation().value()); //打印对象中的注解属性的值。
		}
	}	
}</span>

泛型:
泛型规定了一个集合中只能存储同一个类型的对象,这样会更安全。
泛型是提供给javac编译器使用的,可以限定集合中输入的类型,让编译器挡住源程序中的非法输入,编译器编译带类型说明的集合时会去掉‘类型’信息,是程序运行效率不收影响,对于参数化的泛型类型,getClass()方法的返回值和原始类型完全一样。由于编译生成的字节码会去掉泛型的类型信息,只要能跳过编译器,就可以往某个泛型集合中加入其它类型的数据,例如:用反射得到集合,再调用其add方法即可。
例子:往泛型为Integer的集合中添加一个字符串:
List<Integer> list = new ArrayList<Integer>();
list.getClass().getMethod("add", Object.class).invoke(list, "abc"); //这里拿到方法已经去掉了泛型的类型信息,故可以加入一个String对象。
System.out.println(list);

泛型的通配符扩展应用:
使用?通配符可以引用其他各种参数化的类型,?通配符定义的变量主要用作引用,可以调用与参数化无关的方法,不能调用与参数化有关的方法。
例如打印任意泛型类型的Collection集合中的所有元素的方法:
public static void printObject(Collection<?> collection)
{
      System.out.println(collection.size());
      for(Object obj:collection)
      {
        System.out.println(obj);
      }
}

限定通配符的上边界:
正确:Vector<?extends Number> x = new Vector<Integer>(); //只能用Number或Number的子类作为泛型类型。
错误:Vector<?extends Number> x = new Vector<String>();

限定通配符的下边界:
正确:Vector<?super Integer> x = new Vector<Number>();  //只能用Integer或Integer的父类作为泛型类型。
错误:Vector<?super Integer> x = new Vector<byte>();

注:限定通配符总是包括自己。

1.编写一个泛型方法,自动将Object类型的对象转换成其他类型。
private static <T> T autoConvert(Object obj)
{
    return (T)obj;
}


2.定义一个方法,可以将任意类型的数组中的所有元素填充为想对应类型的某个对象。
private static <T> void fillArray(T[] arr,T obj)
{
     for(int i=0; i<arr.length; i++)
     {
       arr[i] = obj;
     }
}

自定义泛型:
java中的泛型类型类似于c++中的模板,但是这种相似性进限于表面,java语言中的泛型基本上是完全在编译器中实现,
用于编译器执行类型检查和类型判断,然后生成普通的非泛型的字节码,这种实现技术称之为擦出(erasure),这是因为
扩展虚拟机指令集来支持泛型被认为是无法接受的,所以java泛型采用了可以完全在编译器中实现擦出方法。

通过反射获得泛型的实际类型参数:
直接通过变量是办法知道泛型的实际类型的,因为编译器在生成相应的字节码会去掉泛型的类型信息。
但却可以得到一个方法的参数的泛型的实例类型,注意到Method类中有一个方法:Type[] getGenericParameterTypes(),它按照声明顺序返回 Type 对象的数组,
这些对象描述了此 Method 对象所表示的方法的形参类型。
Type 是 Java 编程语言中所有类型的公共高级接口,它有一个子接口ParameterizedType,它声明了三个方法:
1.Type[] getActualTypeArguments(),返回表示此类型实际类型参数的 Type 对象的数组。 
2.Type getOwnerType(),返回 Type 对象,表示此类型是其成员之一的类型。
3.Type getRawType() ,返回 Type 对象,表示声明此类型的类或接口。

public static void main(String[] args) throws Exception
{
     //得到描述applyVector方法的Method对象。
     Method method = test.class.getDeclaredMethod("applyVector", Vector.class);
     //获得形参类型数组
     java.lang.reflect.Type[] types = method.getGenericParameterTypes();
     //打印第一个形参类型:java.util.Vector<java.util.Date>
     System.out.println(types[0]);
     //获得第一个形参的ParameterizedType对象。
     ParameterizedType p = (ParameterizedType)types[0];
     //打印声明此形参的类或接口。
     System.out.println(p.getRawType());
    //获得此形参实际类型参数的数组并打印第一个。
     System.out.println(p.getActualTypeArguments()[0]);
}

private static void applyVector(Vector<Date> v1)
{

}


---------------------- ASP.Net+Unity开发.Net培训、期待与您交流! ----------------------详细请查看:www.itheima.com

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值