javabean、注解类、类加载器

来源:互联网 发布:jsp是不是javascript 编辑:程序博客网 时间:2024/05/28 11:28

关于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 {//为注解添加方法,默认值是greenString 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());//nullSystem.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 {@Overridepublic 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) */@Overrideprotected 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、类加载器、静态导入、可变参数、自动拆装箱。






1 0
原创粉丝点击