关于Java基础的文章,我觉得写得还可以,以前发在了我其它的博客了,肯定是原创,现在再分享给大家出来。
---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
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示例
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"); } }
如下,改写的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工具包是针对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行代码了,感觉棒棒哒。
假如我的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);
PropertyUtils工具类用法跟BeanUtils基本一样。
区别:
1)BeanUtils会对JavaBean的属性的类型进行转换,如属性本身是integer,会转换为String。
2)PropertyUtils以属性本身的类型进行操作。
注解可以用于创建文档,跟踪代码中的依赖性,甚至执行基本编译时检查。
在程序中加了注解就等于为程序打上了某种标记,没加,则等于没有某种标记。
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。
Retention有三种取值
RetentionPolicy.SOURCE----java源文件时期,编译器要丢弃的注释。
RetentionPolicy.CLASS--- 编译器将把注释记录在类文件中,但在运行时 VM 不需要保留注释。(默认)
RetentionPolicy.RUNTIME----编译器将把注释记录在类文件中,在运行时 VM 将保留注释,因此可以反射性地读取。
//运行时检测注释 @Retention(RetentionPolicy.RUNTIME) public @interface IAnncation { }
用于注解类的使用位置
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 })
类加载器说简单一点就是加载类的工具。
一般来说,Java 虚拟机使用 Java 类的方式如下:
Java 源程序(.java 文件)在经过 Java 编译器编译之后就被转换成 Java 字节代码(.class 文件)。
类加载器负责读取 Java 字节代码,并转换成 java.lang.Class类的一个实例。每个这样的实例用来表示一个 Java 类。
通过此实例的 newInstance()方法就可以创建出该类的一个对象。
将.class文件中的内容变为字节码加载进内存。
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 } }
每个类加载器只能加载特定位置的类,对于不在它指定位置的类,可以委托给其他的类加载器去加载。
具体是:
比如一个默认的java应用类应该由AppClassLoader加载,
首先并不加载,而是委托给它的爸爸:ExtClassLoader,但是Ext也不加载,因为它还有爸爸,再次委托给BootStap
BootStap没有爸爸了,就找自己指定的目录--rt.jar包下没有,再让它的儿子ExtClassLoader去找,ext目录下也没有,再让它孙子AppClassLoader去找。
找到了,就加载,找不到就报异常,不会再往下找了(因为从这里开始的)
①,继承抽象类ClassLoader
②,覆写其中的findClass(String name)方法
③,返回defineClass()方法。比如:return defineClass(null, buf, 0, buf.length);
a,要加密的类
package cn.jinfulin.day2.ClassLoader; import java.util.Date; public class Sercert extends Date { @Override public String toString() { return "我是加密文件"; } }
/* * 简单加密算法 */ private static void cypher(InputStream in,OutputStream out)throws Exception { int b = -1; while((b = in.read())!= -1){ out.write(b ^ 0xff); } }
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); }
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、类加载器、静态导入、可变参数、自动拆装箱。
原文:http://blog.csdn.net/jinfulin/article/details/44967593