---------------------- ASP.Net+Android+IOS开发、.Net培训、期待与您交流! ----------------------
1.注解:相当于一个标记,javac编译器,开发工具和其他程序可以用反射来
了解是否有某种标记,从而做相应的操作。
@SuppressWarnings:警告
@Deprecated:过时
@SuppressWarnings:警告
@Deprecated:过时
@Override:重写
2.注解的应用
元注解@Retention--定义注解类的存在区域,有三种取值:RetentionPolicy.SOURCE、RetentionPolicy.CLASS、 RetentionPolicy.RUNTIME,分别对应java源文件、class文件、内存中的字节码。
元注解@Target:确定注解类可用范围,取值ElementType.METHOD···
3.自定义注解:
1.定义一个最简单的注解
2.把它加在某个类上
3.用反射进行测试类的定义上是否有注解
示例:
@Retention(RetentionPolicy.RUNTIME)//元注解
@Target({ElementType.METHOD,ElementType.TYPE})
@interface MyAnnotation
{}
@MyAnnotation
class AnnotationTest
{
public static void main(String[] args)
{
if(AnnotationTest.class.isAnnotationPresent(MyAnnotation.class))
{
MyAnnotation annotation = AnnotationTest.class.getAnnotation(MyAnnotation.class);
System.out.println(annotation);
}
}
}
4.类加载器:
Java虚拟机中可以安装多个类加载器,系统默认三个主要类加载器,每个类加载器负责加载特定位置的类: BootStrap , ExtClassLoader , AppClassLoader。
类加载器也是Java类,因为其他是java类的类加载器本身也要被类加载器加载,显然必须有第一个类加载器不是java类,这正是BootStrap。
Java虚拟机中的所有类加载器采用具有父子关系的树形结构进行组织,在实例化每个类加载器对象时,需要为其指定一个父级加载器对象或者默认采用系统类加载器为其父级类加载器。
每个类加载器加载类时,会先委托给其上级类加载器。
BootStrap加载JRE/lib/rt.jar
ExtClassLoader加载JRE/lib/ext/*.jar
AppClassLoader加载classpath指定的所有jar或目录
5.自定义类加载器的编写原理分析
编写自己的类加载器:
自定义的类加载器必须继承ClassLoader。
不用重写loadClass()方法,因为loadClass()这个方法的作用就是先让上一级的类加载器去加载类,如果上一级的类加载器加载不了就调用findClass()方法来加载类。所以我们只需重写findClass()方法即可。
在findClass()方法中会调用到defineClass()方法,defineClass()方法的作用是得到.class文件的内容将其转换成字节码。
示例:自定义解密类加载器类MyClassLoader:
package cn.it.cast;
import java.io.ByteArrayOutputStream;
import java.io.FileInputStream;
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{
String srcPath = args[0];
String destDir = args[1];
String fileName = srcPath.substring(srcPath.lastIndexOf('\\')+1);
String destPath = destDir+"\\"+fileName;
FileInputStream fis = new FileInputStream(srcPath);
FileOutputStream fos = new FileOutputStream(destPath);
cypher(fis,fos);
fis.close();
fos.close();
}
private static void cypher(InputStream ips,OutputStream ops)throws Exception{
int b = 0;
while((b=ips.read())!=-1){
ops.write(b ^ 0xff);
}
}
private String classDir;
@Override
protected Class<?> findClass(String name) throws ClassNotFoundException {
String classFileName = classDir + "\\" + name.substring(name.lastIndexOf('.')+1) + ".class";
try {
FileInputStream fis = new FileInputStream(classFileName);
ByteArrayOutputStream bos = new ByteArrayOutputStream();
cypher(fis,bos);
fis.close();
System.out.println("aaa");
byte[] bytes = bos.toByteArray();
return defineClass(null,bytes, 0, bytes.length);
} catch (Exception e) {
e.printStackTrace();
}
return super.findClass(name);
}
public MyClassLoader(){
}
public MyClassLoader(String classDir){
this.classDir = classDir;
}
}
6.java的动态代理类:
代理:要为已存在的多个具有相同接口的目标类的各个方法增加一些系统功能,从而编写一个与目标类具有
相同接口的代理类,代理类的每个方法调用目标类的相同方法,并在调用方法时加上系统功能的代码。
动态代理技术:
1)JVM可以在运行期动态生成出类的字节码,这种动态生成的类往往被用作代理类,即动态代理类。
2)JVM生成的动态代理类必须实现一个或多个接口,所以,JVM生成的动态类只能用作具有相同接口的目标类的代理。
3)CGLIB库可以动态生成一个类的子类,一个类的子类也可以用作该类的代理,所以,如果要为一个没有实现接口的类生成动态代理类,那么可以使用CGLIB库。
4)代理类的各个方法中通常除了要调用目标的相应方法和对外返回目标返回的结果外,还可以在代理方法中的如下四个位置加上系统功能代码: a:在调用目标方法之前 ; b:在调用目标方法之后 ; c:在调用目标方法前后 ; d:在处理目标方法异常的catch块中。
示例:创建一个实现Collection接口的动态代理类:
import java.util.*;
import java.lang.reflect.*;
class ProxyTest
{
public static void main(String[] args) throws Exception
{
Collection proxy = Proxy.newProxyInstance(
Collection.class.getClassLoader(),
new Class[]{Collection.class},
new InvocationHandler(){
ArrayList target = new ArrayList();
public Object invoke(Object proxy,Method method,Object[] args)throws Exception
{
Long beginTime = System.currentTimeMillis();
Object retVal = method.invoke(target,args);
Long endTime = System.currentTimeMillis();
System.out.println(method.getName()+" has the running time of "+(endTime-beginTime));
return retVal;
}
}
);
proxy.add("hlx");
proxy.add("qls");
proxy.add("sxfd");
System.out.println(proxy.size());
Iterator it = proxy.iterator();
while(it.hasNext())
{
System.out.println(it.next());
}
}
}