黑马程序员——高新技术总结
来源:互联网 发布:巨龙之巢网络波动 编辑:程序博客网 时间:2024/06/07 22:38
------- android培训、java培训、期待与您交流! ----------
反射
Class类
class类是对对象的抽象,而Class是对class的抽象,或者说类是对对象的共性的描述,而Class又是对类的共性的描述,但它本身又是一个类,它的具体实例是内存中某个类的字节码。
得到类的字节码的方式有三种:
- 对象.getClass()
- 类名.class
- Class.forName("完整类名“)
Class.forName()的作用:如果有要获得的字节码存在于内存中就直接返回,如果不存在,则通过类加载器将其 .clas文件加载后返回。
九种预定义的Class实例对象:表示八个基本类型和void。这些类对象由 Java 虚拟机创建,与其表示的基本类型同名,即boolean、byte、char、short、int、long、float 和double。
数组的Class实例对象:类型[ ].class,可以用isArray()方法判断一个Class实例是否为数组。
String str = "abc"; Class cls1 = str.getClass(); Class cls2 = String.class; Class cls3 = Class.forName("java.lang.String"); System.out.println(cls1 == cls2); System.out.println(cls1 == cls3); System.out.println(cls1.isPrimitive()); System.out.println(int.class.isPrimitive()); System.out.println(Integer.class.isPrimitive()); System.out.println(Integer.TYPE.isPrimitive()); System.out.println(int[].class.isArray());
总之,反射就是把java类中的各种成分映射成java类。一个类中的每个成员都可以用相应的反射API类的一个实例对象来表示,通过调用Class类的方法可以得到这些实例对象,得到这些对象后有什么用?怎么用?是学习和应用的要点。
部分反射API
Construtcor类
得到某个类的所有构造方法:
Constructor[] constructors=String.class.getConstructors();Constructor[] constructors=String.class.getDeclaredConstructors();//包括私有的得到某个类的某个构造方法:会用到参数类型的Class对象Constructor constructor1 = String.class.getConstructor(StringBuffer.class);
创建实例对象:参数要用获得构造方法时指定的类型。
普通方式:String str = new String(new StringBuffer("abc")); 反射方式:String str1 =(String) constructor1.newInstance(new StringBuffer("abc"));
Class也提供了newInstance,其内部是利用Constructor的newInstance的无参方法。
Field类
类的成员变量,它的具体实例代表的的是类中某个字段的定义,而非具体的变量。
public class ReflectPoint{ private int x; public int y; public String str1 = "Master"; public String str2 = "Basketball"; public String str3 = "itcast"; public ReflectPoint(int x ,int y){ super(); this.x=x; this.y = y; } }
访问private成员变量:
//暴力反射,用getDeclaredField()取出包括私有在内的所有变量 Field fieldX =ref.getClass().getDeclaredField("x"); //将私有变量设为可访问的 fieldX.setAccessible(true); System.out.println(fieldX.get(ref));
综合应用案例:将RefectPoint中的所有String成员变量的值中的“a”,替换成“w”
private static void changeStringValue(Object obj) throws Exception { Field [] fields = obj.getClass().getFields(); for(Field field:fields){ if(field.getType()==String.class){//字节码的比较用==更精确 String str =(String) field.get(obj); String str1 = str.replace('a','w'); field.set(obj, str1); } } }
类加载器
类加载器特点
- 类加载器是加载类的工具,它的作用是将硬盘上的.class文件加进内存,并对之进行一些处理。
- java虚拟机中可安装多个类加载器,系统默认三个主要的类加载器,每个类加载器负责加载特定的类:
- BootStrap
- xitClassLoader
- AppClassLoader
- 类加载器也是java类,因为其他是java类的类加载器也要被类加载器加载,显然必须有第一个类加载器不是java类, 这正是:BootStrap,它是由C++编写的。
- java虚拟机中的所有类加载器采用具有 父子关系 的 树形结构 进行组织,在实例化每个类加载器对象时,需要为其指定一个父级类加载器对象,或者默认采用系统类加载器为其父级类加载器。
System.out.println(ClassLoaderTest.class.getClassLoader().getClass().getName()); System.out.println(System.class.getClassLoader());
体系结构
|---Bootstrap ClassLoader ->JRE/lib/rt.jar
|---Extension ClassLoader ->JRE/lib/ext/*.jar
|---ApplicationClassLoader ->ClassPath指定的所有jar或目录。
|--MyClassLoader ->指定的特殊目录
|--itcastClassLoader->指定的特殊目录
ClassLoader loader=ClassLoaderTest.class.getClassLoader(); while(loader!=null){ System.out.println(loader.getClass().getName()); loader=loader.getParent(); } System.out.println(loader);
委托机制
委托机制的过程
- 类加载器的选择:当java虚拟机要加载一个类时,到底派出那个类加载器去加载?
- 首先当前线程的类加载器去加载线程中的第一个类。
- 如果类A中引用了B类,java虚拟机将使用类A的加载器来加载类B
- 还可以直接调用ClassLoader.loadClass()方法来指定某个类加载器去加载某个类。
- 类加载器怎样加载:每个类加载器加载类时,又先委托给器上级类加载器。当所有祖宗类加载器没有加载到类,回到发起者类加载器,还加载不了,则抛出ClassNotFoundException,不再去找发起者类加载器的儿子,因为没有getChild方法。
注意:需要说明一下 Java 虚拟机是如何判定两个 Java 类是相同的。Java 虚拟机不仅要看类的全名是否相同,还要看加载此类的类加载器是否一样。只有两者都相同的情况,才认为两个类是相同的。即便是同样的字节代码,被不同的类加载器加载之后所得到的类,也是不同的。
编写自己的类加载器
知识点
- 自定义的类加载器必须继承ClassLoader。
- loadClass方法与findClass方法:只需重新findClass方法,就会跳出委托机制。
- defineClass方法。
编写步骤
- 编写一个队文件内容进行监督加密的程序
- 编写一个自己的类加载器,可实现对加密的类进行撞在和解码。
- 编写一个程序调用类加载器加载类,在源程序中不能用该类定义引用变量,因为编程器无法识别这个类。程序中可以除了使用ClassLoader.load方法外,还可以使用使用设置线程的上下文加载器或者系统加载器,然后再使用Class.forName.
代码部分
要加载的测试类代码
注意:这里最好继承一个类,以便于获取其实例时,定义父类的引用,而不是它自己的引用。
编写自己的类加载器代码
import java.io.ByteArrayOutputStream;import java.io.FileInputStream;import java.io.FileNotFoundException;import java.io.FileOutputStream;import java.io.InputStream;import java.io.OutputStream;public class MyClassLoader extends ClassLoader {public static void main(String[] args)throws Exception {// TODO Auto-generated method stubString srcPath = args[0];String destDir = args[1];FileInputStream fis = new FileInputStream(srcPath);String destFileName =srcPath.substring(srcPath.lastIndexOf('\\')+1);String destPath = destDir+"\\"+destFileName;FileOutputStream fos = new FileOutputStream(destPath);cypher(fis, fos);System.out.println("xxxxx");fis.close();fos.close();}private String classDir;@Overrideprotected Class<?> findClass(String name) throws ClassNotFoundException {// TODO Auto-generated method stubString classFileName = classDir+"\\"+name+".class";try {FileInputStream fis = new FileInputStream(classFileName);ByteArrayOutputStream bos = new ByteArrayOutputStream();cypher(fis,bos);byte[] b = bos.toByteArray();return defineClass(b, 0, b.length);} catch (Exception e) {// TODO Auto-generated catch blocke.printStackTrace();}System.out.println("aaaa");return super.findClass(name);}public MyClassLoader(){}public MyClassLoader(String classDir){this.classDir = classDir;}public static void cypher(InputStream ips,OutputStream ops) throws Exception{int b = -1;while((b=ips.read())!=-1){ops.write(b^0xff);}//这时候不用关闭,谁创建资源,谁关闭资源。}}调用自己写的类加载器
Class clazz = new MyClassLoader("itcastlib").loadClass("ClassLoaderAttachments"); Date d = (Date)clazz.newInstance(); System.out.println(d.toString());
JavaBean内省与beanutils工具包
JavaBean
JavaBean是一种特殊的Java类,主要用于传递数据信息,这种java类中的方法主要用于访问私有的字段,且方法名符合某种命名规则。
特点
JavaBean的属性是根据其中的setter和getter方法来确定的,而不是根据其中的成员变量。去掉set和get前缀,剩余部分就是属性名。如果剩余部分的第二个字母是小写的,则把剩余部分的首字母改成小的。JavaBean必须有一个不带参数的构造方法。
用途
如果要在两个模块之间传递多个信息,可以将这些信息封装到一个JavaBean中,这种JavaBean的实例对象通常称之为值对象(Value Object,简称VO)。这些信息在类中用私有字段来存储,如果读取或设置这些字段的值,则需要通过一些相应的方法来访问。
好处
一个符合JavaBean特点的类可以当作普通类一样进行使用,但如果把它当做JavaBean,那么就可以调用JDK提供的对专门对JavaBean进行操作的API,以实现对一些对普通类来说比较复杂的功能。
对JavaBean的简单内省操作
用java.beans包中的PropertyDescriptor类把ReflectPoint当做JavaBean进行操作。
public static void setProperty(Object pt1, String propertyName,Object value) throws IntrospectionException,IllegalAccessException, InvocationTargetException { PropertyDescriptor dp1 = new PropertyDescriptor(propertyName,pt1.getClass()); Method methodSetX = dp1.getWriteMethod(); methodSetX.invoke(pt1,value); }
public static Object getProperty(Object pt1, String propertyName) throws IntrospectionException, IllegalAccessException,InvocationTargetException { PropertyDescriptor dp = new PropertyDescriptor(propertyName,pt1.getClass()); Method methodGetX = dp.getReadMethod(); Object retVal = methodGetX.invoke(pt1); return retVal; }
ReflectPoint pt1 = new ReflectPoint(1,1); String propertyName = "x"; Object retVal = getProperty(pt1, propertyName); System.out.println("getX:"+retVal); Object value = 7; setProperty(pt1, propertyName, value); System.out.println("setX:"+pt1.getX());
public static Object getProperty(Object pt1, String propertyName) throws IntrospectionException, IllegalAccessException,InvocationTargetException { BeanInfo beanInfo = Introspector.getBeanInfo(pt1.getClass()); PropertyDescriptor[] dps = beanInfo.getPropertyDescriptors(); Object retVal = null; for(PropertyDescriptor dp:dps) { if(dp.getName().equals(propertyName)){ retVal = dp.getReadMethod().invoke(pt1); break; } } return retVal;
BeanUtils工具包
里边的BeanUtil和PropertyUtils类使用示例如下:
ReflectPoint pt1 = new ReflectPoint(1,1);BeanUtils.setProperty(pt1, "x", 25);System.out.println(BeanUtils.getProperty(pt1, "x").getClass().getName());//BeanUtils可以实现属性链操作BeanUtils.setProperty(pt1, "date.time", "111");//time不一定在类中存在,只是说明date有getTime和setTime方法。System.out.println(BeanUtils.getProperty(pt1, "date.time")); PropertyUtils.setProperty(pt1, "x", 160); System.out.println(PropertyUtils.getProperty(pt1, "x").getClass().getName());
------- android培训、java培训、期待与您交流! ----------
- 黑马程序员——高新技术总结
- 黑马程序员---高新技术总结
- 黑马程序员——高新技术
- 黑马程序员——高新技术
- 黑马程序员——高新技术
- 黑马程序员—高新技术1
- 黑马程序员—高新技术2
- 黑马程序员—java高新技术
- 黑马程序员——JAVA高新技术总结(一)
- 黑马程序员——JAVA高新技术总结(二)
- 黑马程序员-Java基础总结15——高新技术Day01
- 黑马程序员——Java高新技术总结(二)
- 黑马程序员——JAVA高新技术总结(一)
- 黑马程序员——JAVA高新技术总结(二)
- 黑马程序员_张孝祥—高新技术学习总结(十)
- 黑马程序员—Java高新技术总结(一)
- 黑马程序员_高新技术总结
- 黑马程序员——Java高新技术
- NFS服务器配置---ARM-Linux挂载
- Android v21.1.0虚拟机上下左右按键
- squid_linux代理服务器
- 情景模式模拟
- 三分法——求解凸性函数的极值问题
- 黑马程序员——高新技术总结
- 打造超强ubuntu下的C++ IDE
- Linux系统Sudo命令的使用说明
- Hadoop使用常见问题以及解决方法
- Valid signing identity not found解决办法(原有IDP私钥丢失)
- Weka链接SQLServer2005数据库
- Android无法访问本地服务器(localhost)的解决方案
- java.lang.UnsupportedClassVersionError: Bad version number in .class file
- 亲,你的硬件负载均衡器真的均衡了吗?