码迷,mamicode.com
首页 > 编程语言 > 详细

JDK1.5的新特性:javabean、注解类、类加载器

时间:2015-04-09 23:48:32      阅读:261      评论:0      收藏:0      [点我收藏+]

标签:

关于Java基础的文章,我觉得写得还可以,以前发在了我其它的博客了,肯定是原创,现在再分享给大家出来。

---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------



 一、javaBean


一、概述

JavaBean是符合某种规范的Java组件,也就是Java类。 
它必须满足如下规范: 

1)必须有一个零参数的默认构造函数 

2)必须有get和set方法,类的字段必须通过get和set 方法来访问。 

   (get方法无参,set方法有参) 

比如下面的一个类就是一个JavaBean类

package cn.jinfulin.day2.javabean;

/**
 * @author 金福林
 *
 */
public class UserBean {

	private String name;
	private String password;

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}

	public String getPassword() {
		return password;
	}

	public void setPassword(String password) {
		this.password = password;
	}
}



二、内省

那么javabean类如何操作呢,这里就要说一下java内省机制了。

JDK提供了对JavaBean进行一些操作的API,这套API就是内省。

内省(Introspector)是Java语言对Bean类属性、事件的一种缺省处理方法。

例如类A中有属性name,那我们可以通过getName,setName来得到其值或者设置新的值。


通过内省调用JavaBean示例


1、通过PropertyDescriptor调用,

相对简单一些</p><p>PropertyDescriptor 描述 JavaBean类,通过一对存储器方法导出的一个属性。


package cn.jinfulin.day2.javabean;

import java.beans.IntrospectionException;
import java.beans.PropertyDescriptor;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;

/**
 * @author 金福林
 *
 */
public class IntroBean {
	public static void main (String[] args) throws Exception{

	String propertyName = "name";
	Object user = new UserBean();
	
	setMethod(propertyName, user);
	
	getMethod(propertyName, user);
	}

	private static void getMethod(String propertyName, Object user)
			throws IntrospectionException, IllegalAccessException,
			IllegalArgumentException, InvocationTargetException {
		PropertyDescriptor pd = new PropertyDescriptor(propertyName, user.getClass());
		Method MethodGetName = pd.getReadMethod();
		MethodGetName.invoke(user, null);
	}


	private static void setMethod(String propertyName, Object obj) throws Exception{
		//PropertyDescriptor 描述 Java Bean 通过一对存储器方法导出的一个属性。 
		PropertyDescriptor pd = new PropertyDescriptor(propertyName,obj.getClass());
		Method MethodSetName = pd.getWriteMethod();
		MethodSetName.invoke(obj, "jinfulin");
	}

}

2,通过Introspector类调用,相对复杂一些

如下,改写的setMethod方法

private static Object setMethod(String propertyName, Object obj) throws Exception{

		BeanInfo bean = Introspector.getBeanInfo(obj.getClass());
		PropertyDescriptor[] pds = bean.getPropertyDescriptors();
		Object returnvalue = null;
		for (PropertyDescriptor pd : pds) {
			if (pd.getName()==propertyName) {
				Method methodGetX = pd.getReadMethod();
				returnvalue = methodGetX.invoke(obj);
			}
			
		}
		return returnvalue;
	}


三、BeanUntils工具包

1,概述

BeanUntils工具包是针对javabean的操作属性的工具类,使用比较广泛。

它并不是sun公司开发的而是阿帕奇公司开发的第三方工具包,需要单独下载才能使用。

导入jar包的方法比较简单,就不详细说了,但是要记的不仅要导入BeanUntils工具包,还要导入logging包

	public static void main(String[] args) throws Exception{
		UserBean bean = new UserBean();
		BeanUtils.setProperty(bean, "name", 12);//set方法
		BeanUtils.getProperty(bean, "name");//get方法
		
	}
此时再调用Javabean的set和get方法,一下子就变得只剩下2行代码了,感觉棒棒哒。


2,对于JavaBean中的属性是对象的操作  

假如我的javaBean类返回的是对象,而这个对象还拥有get和set方法(比如date对象有getTime()和setTime()方法)

比如

	private Date birthday;
	public Date getBirthday() {
		return birthday;
	}

	public void setBirthday(Date birthday) {
		this.birthday = birthday;
	}

那么此时调用就可以多层调用

BeanUtils.setProperty(bean, "birthday.time", 12);


3,PropertyUtils工具类

PropertyUtils工具类用法跟BeanUtils基本一样。

区别:
        1)BeanUtils会对JavaBean的属性的类型进行转换,如属性本身是integer,会转换为String。
        2)PropertyUtils以属性本身的类型进行操作。



 二、注解类


一,概述

注解可以用于创建文档,跟踪代码中的依赖性,甚至执行基本编译时检查。

在程序中加了注解就等于为程序打上了某种标记,没加,则等于没有某种标记。



二、lang包中三个常用注解类

1,Override----表示一个方法声明打算重写超类中的另一个方法声明。

2,Deprecated----过时的

3,SuppressWarnings----忽略警告信息(不提示过时信息)


三、注解中反射的调用

	public static void main(String[] args) {
		//如果指定类型的注释存在于此元素上,则返回 true,否则返回 false。
		if (AnnotationTest.class.isAnnotationPresent(IAnncation.class)) {
			//如果存在该元素的指定类型的注释,则返回这些注释,否则返回 null。
			IAnncation anno = AnnotationTest.class.getAnnotation(IAnncation.class);
			System.out.println(anno);
		}

	}

四、元注解:注解的注解

上面那个反射的例子直接执行是肯定不能成功的,因为我们还没有写注解类,也没有更改元注解的内容。

元注解就是在定义注解类的时候加注解,元注解通常包括两个,即Retention和Target。

1,Retention

Retention有三种取值

RetentionPolicy.SOURCE----java源文件时期,编译器要丢弃的注释。

RetentionPolicy.CLASS--- 编译器将把注释记录在类文件中,但在运行时 VM 不需要保留注释。(默认)

RetentionPolicy.RUNTIME----编译器将把注释记录在类文件中,在运行时 VM 将保留注释,因此可以反射性地读取。


//运行时检测注释
@Retention(RetentionPolicy.RUNTIME)
public @interface IAnncation {
}

2,Target

用于注解类的使用位置

ElementType.TYPE------ 类、接口(包括注释类型)或枚举声明可以使用该注解

ElementType.METHOD-----方法中可以使用该注解

ElementType.ANNOTATION_TYPE ------注释类型声明 

CONSTRUCTOR ------构造方法声明 

FIELD -------字段声明(包括枚举常量) 

LOCAL_VARIABLE------局部变量声明 

PACKAGE ------- 包声明 

PARAMETER --------参数声明 

@Target({ElementType.TYPE,ElementType.METHOD,ElementType.ANNOTATION_TYPE})
public @interface IAnncation {
}


五、为注释增加属性

     如果只有一个value名称的属性或其他属性缺省,则可@注解名(”属性值”);

     如果有多个或不缺省或者需重新赋值,则@注解名(属性名=”属性值”,…)。


//运行时检测注释
@Retention(RetentionPolicy.RUNTIME)
//注释可以放在的位置,这里表示在方法可类中均可
@Target({ElementType.TYPE,ElementType.METHOD,ElementType.ANNOTATION_TYPE})
public @interface IAnncation {
	//为注解添加方法,默认值是green
	String color() default "green";
	//当有且只有value属性时候,=号可以省略
	String value() default "默认";
	//一个数组方法,如果只有一值,大括号可以省略
	int[] arr() default {1,2}; 
	
	//调用时比如
	//@IAnncation(color = "red",arr = {2,2,3})
}

调用

@IAnncation(color = "red", arr = { 2, 2, 3 })


 三、类加载器


1,概述

类加载器说简单一点就是加载类的工具。

一般来说,Java 虚拟机使用 Java 类的方式如下:

Java 源程序(.java 文件)在经过 Java 编译器编译之后就被转换成 Java 字节代码(.class 文件)。

类加载器负责读取 Java 字节代码,并转换成 java.lang.Class类的一个实例。每个这样的实例用来表示一个 Java 类。

通过此实例的 newInstance()方法就可以创建出该类的一个对象。

2、类加载器作用:

将.class文件中的内容变为字节码加载进内存。

3,类加载器的结构

Java 中的类加载器大致可以分成两类,一类是系统提供的,另外一类则是由 Java 应用开发人员编写的。

系统提供的类加载器主要有下面三个:

引导类加载器(BootStrap):它用来加载 Java 的核心库,是用原生代码来实现的,并不继承自 java.lang.ClassLoader。

扩展类加载器(ExtClassLoader):它用来加载 Java 的扩展库。Java 虚拟机的实现会提供一个扩展库目录。该类加载器在此目录里面查找并加载 Java 类。

统类加载器(AppClassLoader):它根据 Java 应用的类路径(CLASSPATH)来加载 Java 类。一般来说,Java 应用的类都是由它来完成加载的。

可以通过 ClassLoader.getSystemClassLoader()来获取它。



技术分享


public class ClassLoaderTest {

	public static void main(String[] args) {
		System.out.println(System.class.getClassLoader());//null
		System.out.println(ClassLoaderTest.class.getClassLoader().getClass()
				.getName());//AppClassLoader
	}

}


4,类加载器的委托机制

每个类加载器只能加载特定位置的类,对于不在它指定位置的类,可以委托给其他的类加载器去加载。

具体是:

比如一个默认的java应用类应该由AppClassLoader加载,

首先并不加载,而是委托给它的爸爸:ExtClassLoader,但是Ext也不加载,因为它还有爸爸,再次委托给BootStap

BootStap没有爸爸了,就找自己指定的目录--rt.jar包下没有,再让它的儿子ExtClassLoader去找,ext目录下也没有,再让它孙子AppClassLoader去找。

找到了,就加载,找不到就报异常,不会再往下找了(因为从这里开始的)


5,自定义类加载器

1,步骤

①,继承抽象类ClassLoader

②,覆写其中的findClass(String name)方法

 ③,返回defineClass()方法。比如:return defineClass(null, buf, 0, buf.length);



2,使用自定义加载器加密类实例

a,要加密的类

package cn.jinfulin.day2.ClassLoader;

import java.util.Date;

public class Sercert extends Date {
	@Override
	public String toString() {
		return "我是加密文件";
		
	}
}

b,加密算法(只使用简单的0,1转换,这样既可以做加密算法,也可以做解密算法)

	/*
	 * 简单加密算法
	 */
	private static void cypher(InputStream in,OutputStream out)throws Exception {
			int b = -1;
			while((b = in.read())!= -1){
				out.write(b ^ 0xff);
			}
	}

c,开始加密文件

	public static void main(String[] args) {

		String srcPath = "C:\\Users\\金福林\\workspace\\staticimport\\bin\\cn\\jinfulin\\day2\\ClassLoader\\Sercert.class";
		String DestFileName = srcPath.substring(srcPath.lastIndexOf("\\") + 1);
		String destPath= "F:\\test\\" + DestFileName;
		FileInputStream in = new FileInputStream(srcPath);
		FileOutputStream out = new FileOutputStream(destPath);
		cypher(in,out);
//		System.out.println(new Sercert().toString());
		
		Class clazz = new ClassLoaderTest().loadClass("Sercert.class");
		Object obj = clazz.newInstance();
		System.out.println(obj);

	}

d,用加密后的class类替换bin目录下的class类,此时再执行就会报错,证明加密成功。


e,自定义类加载器,用于解密文件(继承ClassLoader,覆写findClass()方法)

public class ClassLoaderTest  extends ClassLoader{

	public static void main(String[] args) throws Exception {
		
		Class clazz = new ClassLoaderTest().loadClass("Sercert.class");
		Object obj = clazz.newInstance();
		System.out.println(obj);

	}


	/*
	 * 自定义类加载器,用于解密类
	 * @see java.lang.ClassLoader#findClass(java.lang.String)
	 */
	@Override
	protected Class<?> findClass(String name) throws ClassNotFoundException {
		String classFileName = "f:\\test\\" + name;
		InputStream ips=null;  
        try {  
            ips=new FileInputStream(classFileName);  
            ByteArrayOutputStream bos=new ByteArrayOutputStream();//定义字节数组流  
            cypher(ips,bos);//解密  
            ips.close();  
            byte[] buf=bos.toByteArray();//取出字节数组流中的数据  
            return defineClass(null, buf,0,buf.length);//加载进内存  
              
        } catch (Exception e) {  
            e.printStackTrace();  
        }  
        return null;  
			
	}





 四、最后

到这里JDK1.5的新特性总算写完了,最后再来回顾一下jdk1,5d新特性有:泛型、枚举、增强型for循环、反射、注解类、javabean、类加载器、静态导入、可变参数、自动拆装箱。






JDK1.5的新特性:javabean、注解类、类加载器

标签:

原文地址:http://blog.csdn.net/jinfulin/article/details/44967593

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!