一.javaBean的特点
JavaBean是一种特殊的Java类,主要用于传递数据信息,这种java类中的方法主要用于访问私有的字段,且方法名符合某种命名规则。一个完整JavaBean在类的编写上需要遵守以下5项规定。
(1)如果类的成员变量的名字是xxx,那么为了更改或获取成员变量的值,在类中使用两个方法:getXxx(),用来获取属性xxx;setXxx(),用来修改属性xxx。
(2)对于boolean类型的成员变量,允许使用is代替get和set。
(3)类中方法的访问属性必须是public的。
(4)类中如果有构造方法,那么这个构造方法也是public的,并且是无参数的,可写可不写,默认有无参数的构造方法。
(5)关于实现serializable接口:实现serializable接口的作用是就是可以把对象存到字节流,然后可以恢复所以你想如果你的对象没实现序列化怎么才能进行网络传输呢,要网络传输就得转为字节流,所以在分布式应用中,你就得实现序列化,如果你不需要分布式应用,那就没那个必要实现序列化。
一个符合JavaBean特点的类可以当作普通类一样进行使用,但把它当JavaBean用肯定需要带来一些额外的好处,我们才会去了解和应用JavaBean!好处如下:
(1) 在Java EE开发中,经常要使用到JavaBean。很多环境就要求按JavaBean方式进行操作,别人都这么用和要求这么做,那你就没什么挑选的余地!
(2) JDK中提供了对JavaBean进行操作的一些API,这套API就称为内省。如果要你自己去通过getX方法来访问私有的x,怎么做,有一定难度吧?用内省这套api操作JavaBean比用普通类的方式更方便。
二.内省访问javaBean
内省对应的英文单词为IntroSpector,它主要用于对JavaBean进行操作,JavaBean是一种特殊的Java类,其中的某些方法符合某种命名规则,如果一个Java类中的一些方法符合某种命名规则,则可以把它当作JavaBean来使用。
内省访问JavaBean有两种方法:
(1) 通过Introspector类获得Bean对象的 BeanInfo,然后通过 BeanInfo 来获取属性的描述器( PropertyDescriptor ),通过这个属性描述器就可以获取某个属性对应的 getter/setter 方法,然后通过反射机制来调用这些方法。
(2) 使用BeanUtils工具包操作JavaBean。
实例:利用IntroSpector类对javaBean进行操作
package cn.pengpan.day2;
/*
* 需求:编写一个JavaBean类,并用IntroSpector类对其进行访问
* 此为javaBean类
* */
public class JavaBeanTest{
private String name;
private int age;
public JavaBeanTest(){}
public JavaBeanTest(String name,int age)
{
this.name=name;
this.age=age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
}
package cn.pengpan.day2;
/*
* 需求:通过内省操作,设置属性的值,并获得属性的值
* 思路:简单方式,先通过PropertyDescriptor的构造方法获得其对象,再通过getReadMethod,和getWriteMethod对属性进行操作;
* 复杂方式,通过IntroSpector类的getBeanInfo方法获得beaninfo对象,再利用beaninfo下的getPropertyDescriptor方法获取属性描述对象,最后利用迭代的方式选中需要的属性描述对象*/
import java.beans.*;
import java.lang.reflect.*;
public class BeanTest
{
public static void main(String[] args) throws Exception
{
JavaBeanTest jbTest=new JavaBeanTest();
String proName="name";
String proAge="age";
Object namevalue="javabeantest";
Object agevalue=56;
setProperty(jbTest, proName, namevalue);
setProperty(jbTest, proAge, agevalue);
//System.out.println(jbTest.getName());
//System.out.println(jbTest.getAge());
getProperty(jbTest, proAge);
getProperty(jbTest, proName);
System.out.println(jbTest.getName());
System.out.println(jbTest.getAge());
}
private static void getProperty(JavaBeanTest jbTest, String proAge)
throws IntrospectionException, IllegalAccessException,
InvocationTargetException {
/*PropertyDescriptor prod2=new PropertyDescriptor(proAge, jbTest.getClass());
Method meh2=prod2.getReadMethod();//获取对象的读取属性方法
meh2.invoke(jbTest);//利用invoke执行读取方法*/
Object obj=null;
BeanInfo bInfo=Introspector.getBeanInfo(jbTest.getClass());//利用IntroSpector的静态方法gerBeanInfo获取所需类的BeanInfo对象
PropertyDescriptor[] propertyDescriptors=bInfo.getPropertyDescriptors();//利用getPropertyDescriptors方法获取一个PropertyDescriptor类型的数组
for(PropertyDescriptor prod:propertyDescriptors)
{
if (prod.getName().equals(proAge))
{
Method meth=prod.getReadMethod();
obj=meth.invoke(jbTest);
}
}
}
private static void setProperty(JavaBeanTest jbTest, String proName,
Object namevalue) throws IntrospectionException,
IllegalAccessException, InvocationTargetException {
PropertyDescriptor prod1=new PropertyDescriptor(proName, jbTest.getClass());//用PropertyDescriptor的构造方法获得一个属性描述对象
Method meh1=prod1.getWriteMethod();//用属性描述对象的getwritemethod方法获取写入方法
meh1.invoke(jbTest,namevalue);//用Method类中的Invoke方法对指定属性执行写入方法
}
package cn.pengpan.day2;
/*
* 使用BeanUtils对javaBean进行操作
* */
import org.apache.commons.beanutils.BeanUtils;
public class BeanUtilsTest {
public static void main(String[] args) throws Exception {
JavaBeanTest jbTest=new JavaBeanTest();
BeanUtils.setProperty(jbTest, "name", "jfdjfk");
System.out.println(jbTest.getName());
}
}
一.注解的应用
注解是jdk1.5的新特性,相当于一种标记,编译器或者工具类根据此标记执行相应的动作处理代码,可以加在类,方法,成员变量,方法的参数,局部变量等上面,注解相当于一种标记,在程序中加了注解就等于为程序打上了某种标记,没加,则等于没有某种标记,以后,javac编译器,开发工具和其他程序可以用反射来了解你的类及各种元素上有无何种标记,看你有什么标记,就去干相应的事。
常见的注解符号:
@Override 表示当前方法是覆盖父类的方法;
@Deprecated 表示当前元素是不赞成使用的;
@SuppressWarnings 表示关闭一些不当的编译器警告信息。
元注解:即在注解类上加的注解@Target,@Retention,@Documented,@Inherited
@Target表示该注解用于什么地方,可能的 ElemenetType参数包括:
ElemenetType.CONSTRUCTOR 构造器声明
ElemenetType.FIELD 域声明(包括 enum实例)
ElemenetType.LOCAL_VARIABLE 局部变量声明
ElemenetType.METHOD 方法声明
ElemenetType.PACKAGE 包声明
ElemenetType.PARAMETER 参数声明
ElemenetType.TYPE 类,接口(包括注解类型)或enum声明
@Retention 表示在什么级别保存该注解信息。可选的 RetentionPolicy参数包括:
RetentionPolicy.SOURCE 注解将被编译器丢弃
RetentionPolicy.CLASS 注解在class文件中可用,但会被VM丢弃
RetentionPolicy.RUNTIME VM将在运行期也保留注释,因此可以通过反射机制读取注解的信息。
@Documented 将此注解包含在 javadoc中 ;
@Inherited 允许子类继承父类中的注解;
实例:练习注解的使用
package cn.pengpan.day2;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import cn.pengpan.day1.TrafficLamp;
/*
*
*
* 需求:练习注解的使用
* 思路:先要定义一个注解类Anno,用另一个类使用它,在利用反射获得注解
* */
@Retention(RetentionPolicy.RUNTIME)//设置保留策略为注解信息一直运行
@Target({ElementType.METHOD,ElementType.TYPE})//设置Target注释类型,确定AnnotationTest的作用位置
public @interface AnnotationTest {
String color() default "red";//设置一个color属性,并设定初始值
int age() default 56;//设置一个注解属性值age
String value();
int[] time() default {0,4,6,8,9};//设置一个数组类型的注解属性
TrafficLamp lamp() default TrafficLamp.Red;
}
package cn.pengpan.day2;
import java.lang.reflect.Method;
import java.lang.annotation.*;
import cn.pengpan.day1.TrafficLamp;
/*
* 此为应用注解类的类
* */
@AnnotationTest(color="red",time={5,6},value="jkljkjk")
public class UseAnno {
@SuppressWarnings("deprecation")//让main方法忽略过期方法提示
@AnnotationTest(value="bjhjkhjk")
public static void main(String[] args) throws Exception {
if (UseAnno.class.isAnnotationPresent(AnnotationTest.class)) //用此类的字节码判断此类是否存在指定的注解
{
AnnotationTest atTest=(AnnotationTest)UseAnno.class.getAnnotation(AnnotationTest.class);//若存在获取注解并输出
System.out.println(atTest.color());
System.out.println(atTest.value());
System.out.println(atTest.lamp().nextLamp().name());
}
Method mainMethod=UseAnno.class.getMethod("main", String[].class);//通过反射获取此类的main方法
Annotation[] annotations=mainMethod.getDeclaredAnnotations();//只返回了自定义的注解型的数组
for(Annotation ann:annotations)
System.out.println(ann.toString());
}
}