2006-8-25 学习总结
1、类 Class<T>
Class
类的实例表示正在运行的 Java 应用程序中的类和接口。枚举是一种类,注释是一种接口。每个数组属于被映射为 Class 对象的一个类,所有具有相同元素类型和维数的数组都共享该 Class
对象。基本的 Java 类型(boolean
、byte
、char
、short
、int
、long
、float
和 double
)和关键字 void
也表示为 Class
对象。
Class
没有公共构造方法。Class
对象是在加载类时由 Java 虚拟机以及通过调用类加载器中的 defineClass
方法自动构造的。
以下示例使用 Class
对象来显示对象的类名:
void printClassName(Object obj)
{
System.out.println("The class of " + obj +" is " + obj.getClass().getName());
}
说明:类可以申明一个对象,即明一个具体的事物,平时申明对象的类也是一个事物,因此有一种类来申明这些类,这个类的名字就叫Class,他是所有类最高级别。
2、类加载器
Java编译后的java字节码class文件怎么加载到内存中的呢,其实他们是通过一个继承了ClassLoader类的java类加载到内存中的,然后这些加载类最后是通过一个本地c编写的加载器(Bootstrap)加载入内存中的,Bootstrap加载rt.jar这个包,而由这个加载器加载的调用.getClassLoader返回NULL。常用到的类加载器有AppClassLoader它用于加在classpath下的类,ExtClassLoader装<JAVA_HOME>/jre/lib/ext目录下的jar包,而AppClassLoader是ExtClassLoader的子类,所以AppClassLoader不能装载ExtClassLoader下的类。(注意:ClassLoader是委托父级类装载器加载的,一个类加载器在加载字节码时首先不是自己加载,而是找他的父加载器加载,如果父加载器可以加载那么就由父加载器加载,这就是junit的为什么不能放到<JAVA_HOME>/jre/lib/ext下的原因)。
Important: don't install the junit.jar into the extension directory of your JDK installation. If you do so the test class on the files system will not be found.(引用)
类 ClassLoader:
类加载器是负责加载类的对象。ClassLoader 类是一个抽象类。
ClassLoader 类使用委托模型来搜索类和资源。每个 ClassLoader 实例都有一个相关的父类加载器。需要查找类或资源时,ClassLoader 实例会在试图亲自查找类或资源之前,将搜索类或资源的任务委托给其父类加载器。虚拟机的内置类加载器(称为 "bootstrap class loader")本身没有父类加载器,但是可以将它用作 ClassLoader 实例的父类加载器。
findClass: protected Class<?> findClass(String name)
loadClass:
protected
Class<?>
loadClass(
String name, boolean resolve)
使用指定的
二进制名称来加载类。此方法的默认实现将按以下顺序搜索类:
2. 在父类加载器上调用
loadClass 方法。如果父类加载器为 null,则使用虚拟机的内置类加载器。
4、AOP:
AOP是OOP的延续,是Aspect Oriented Programming的缩写,意思是面向方面编程。面向对象将应用程序分解成各个层次的对象,而AOP将程序分解成各个方面 或者说 关注点。这使得可以模块化诸如事务管理等这些横切多个对象的关注点。
5、Java单元测试——JUnit
JUnit就是一个测试Java程序的类,同时他提供了Java程序员一个写测试代码的规范。
JUnit是由 Erich Gamma 和 Kent Beck 编写的一个回归测试框架(regression testing framework)。用于Java开发人员编写单元测试之用。
回归测试就是你不断地对所编写的代码进行测试:编写一些,测试一些,调试一些,然后循环这一过程。
所谓框架就是Erich Gamma 和 Kent Beck 定下了一些条条框框,你编写的测试代码必须遵循这个条条框框:继承某个类,实现某个接口。其实也就是我们前面所说的规范。
6、注意:在抛出异常时,子类抛出异常只能是父类抛出异常的子类。
7、加密,自定义类装载器加载并运行
Tag:java 加密 (引用)
以MyClassLoader.java为例,先加密Test.class文件,再用自定义类装载器加载并运行。
import java.io.*;
import java.lang.reflect.*;
public class MyClassLoader extends ClassLoader
{
private String path = null;
public MyClassLoader(String path) throws Exception//检查文件是否存在
{
File f = new File(path);
if(!f.isDirectory())
{
throw new RuntimeException(path + " is not a directory");
}
this.path = path;
}
public Class findClass(String name) //throws Exception //为什么不能抛出
{
try
{
byte[] datas = loadClassData(name);
return defineClass(name, datas, 0, datas.length);
}
catch(Exception e)
{
return null;
}
}
private byte[] loadClassData(String name) throws Exception
{
File f = new File(path, name + ".class");//不用检查目录最后是否有目录分割符
FileInputStream fis = new FileInputStream(f);
ByteArrayOutputStream bas = new ByteArrayOutputStream();
cypher(fis,bas);
byte [] datas = bas.toByteArray();
bas.close();
fis.close();
return datas;
}
public static void cypher(InputStream istream,OutputStream ostream) throws Exception
{
//下面这段代码可能遇到255的字节,当成byte就成了-1
/*byte b = 0;
while((b = (byte)istream.read()) != -1)
{
ostream.write(b ^ 0xff);
}*/
int b = 0;
while((b = istream.read()) != -1)
{
ostream.write(((byte)b) ^ 0xff);
}
}
public static void main(String [] args) throws Exception
{
//下面省略了错误检查
if(!args[0].endsWith("class"))
{
ClassLoader loader = new MyClassLoader(args[1]);
Class cls = loader.loadClass(args[0]);
//Method m = cls.getMethod("test",null);//在jdk1.5中报警告,为什么?
Method m = cls.getMethod("test");
//m.invoke(cls.newInstance(),null);
m.invoke(cls.newInstance());
//((Test)cls.newInstance()).test();
return;
}
else
{
FileInputStream fis = new FileInputStream(args[0]);
File f = new File(args[1], new File(args[0]).getName());//不用检查目录最后是否有目录分割符
FileOutputStream fos = new FileOutputStream(f);
cypher(fis,fos);
fis.close();
fos.close();
}
}
}
测试类:
package cn.itcast;
public class Test extends java.util.Date
{
public String toString()
{
return "xixihehe";
}
}