0
点赞
收藏
分享

微信扫一扫

java高级

code_balance 2022-05-05 阅读 43

1.注解 Annotation

Annotation是从JDK5.0开始引入的新技术。

Annotation的作用:

  • 不是程序本身,可以对程序作出解释。
  • 可以被其它程序(比如,编译器等)读取

内置注解:
@Override
@Deprecated
@SuppressWarnings

1.1 自定义注解

使用**@interface自定义注解**时,自动继承了java.lang.annotation.Annotation接口

要点:

  • @interface用来声明一个注解

格式为:
public @interface 注解名(定义体)

  • 其中的每一个方法实际上是声明了一个配置参数。

方法的名称就是参数的名称;
返回值类型就是参数的类型(返回值类型只能是基本类型、Class、String、enum);
可以通过default来声明参数的默认值(-1表示不存在);
如果只有一个参数成员,一般参数名为value。

1.2 元注解

元注解的作用就是负责注解其它注解。Java定义了4个标准的meta-annotation类型,它们被用来提供对其它annotation类型作说明。

  • @Target:用于描述注解的使用范围(PACKAGRE、TYPE、CONSTRUCTOR、FIELD、METHOD、LOCAL_VARIABLE、PARAMETER)
  • @Retention:表示需要什么级别保存该注解信息,用于描述注解的生命周期(SOURCE、CLASS、RUNTIME)
  • @Documented
  • @Inherited

1.3 反射机制读取注解

2.Java动态性之—反射机制 reflection

动态语言:
程序运行时,可以改变程序结构或变量类型。典型的语言:python、ruby、javascript等。

C、C++、Java不是动态语言,但是Java可以称之为“准动态语言”,具有一定的动态性,可以利用反射机制、字节码操作获得类似动态语言的特性。

反射机制:

  • 指的是可以在运行时加载、探知、使用编译期间完全未知的类。
  • 程序在运行状态中,可以动态加载一个只有名称的类,对于任意一个已加载的类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够(动态地)调用它的任意一个方法和属性。
//获得Class类对象
//1. Class.forName()
Class c = Class.forName("包名+类名");
//2. (类名/基本数据类型).class
//3. (对象).getClass()
  • **加载完类之后,在堆内存中,就产生了一个Class类型的对象(一个类只有一个Class对象),这个对象就包含了完整的类的结构信息。我们可以通过这个对象看到类的结构。**这个对象就像一面镜子,透过这个镜子看到类的结构,所以,将之形象地称为:反射。

利用反射可以动态地操作类的构造器、方法和属性。

2.1 反射机制的性能问题

  • setAccessible:启用和禁用访问安全检查的开关。值为true则指示反射的对象在使用时应该取消Java语言访问检查;值为false则指示反射的对象应该实施Java语言访问检查。

禁止访问安全检查,可以提高反射的运行速度。
(使用反射调用方法耗时大概是普通方法调用耗时的30倍,而禁用访问安全检查后,这个时间会缩短大概4倍。)

3.动态编译

通过JavaCompile实现动态编译:

public static int complieFile(String sourceFile) {
    //动态编译
    JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();
    int result = compiler.run(null, null, null, sourceFile);
    System.out.println(result == 0 ? "编译成功" : "编译失败");
    return result;
}
compiler.run():
//1.第一个参数:为java编译器提供参数
//2.第二个参数:得到java编译器的输出信息
//3.第三个参数:接收编译器的错误信息
//4.第四个参数:可变参数(是一个String数组)能传入一个或多个Java源文件
//返回值:0表示编译成功;非0表示编译失败

动态运行编译好的类:

  • 通过Runtime.getRuntime() 运行启动新的进程运行
Runtime run = Runtime.getRuntime();
Process process = run.exec("java -cp" + dir + "" + classFile);
  • 通过反射运行编译好的类
//通过反射运行程序
public static void runJavaClassByReflect(String dir, String classFile) throws Exception {
    try {
        URL[] urls = new URL[] {new URL("file:/" + dir)};
        URLClassLoader loader = new URLClassLoader(urls);
        Class c = loader.loadClass(classFile);
        //调用加载类的main方法
        //m.invoke()
        //第一个参数:需调用的对象
        //第二个参数:方法的参数
        c.getMethod("main", String[].class).invoke(null, (Object) new String[]{});
    } catch (Exception e) {
        e.printStackTrace();
    }
}

4.脚本引擎执行javascript代码 — Rhino引擎

JAVA脚本引擎是从JDK6.0之后添加的功能。

脚本引擎介绍:

  • 使得Java应用程序可以通过一套固定的接口与各种脚本引擎交互,从而达到在Java平台上调用各种脚本语言(js、python、ruby、groovy…)的目的;
  • 可以把一些复杂易变的业务逻辑交给脚本语言处理,这又大大提高了开发效率。

获得脚本引擎对象的方法:

ScriptEngineManager manager = new ScriptEngineManager();
ScriptEngine engine = manager.getEngineByName("javascript");

5.JAVA字节码操作

JAVA动态性的两种常见实现方式:

  • 字节码操作
  • 反射

运行时操作字节码可以让我们实现:

  • 动态生成新的类
  • 动态改变某个类的结构(添加/删除/修改 新的属性/方法)

优势:

  • 比反射开销小,性能高
  • JAVAasist性能高于反射,低于ASM

常见的字节码操作类库:

  1. BCEL(Byte Code Engineering Library):是Java classworking广泛使用的一种框架,它可以让你深入JVM汇编语言进行类操作的细节。BCEL与Javassist有不同的处理字节码方法,BCEL在实际的JVM指令层次上进行操作(BCEL拥有丰富的JVM指令级支持),而Javassist所强调的是源代码级别的工作。
  2. ASM:是一个轻量级java字节码操作框架,直接涉及到JVM底层的操作和指令。
  3. CGLB(Code Generation Library):是一个强大的,高性能、高质量的Code生成类库,基于ASM实现。
  4. Javassist:是一个开源的分析、编辑和创建Java字节码的类库。性能较ASM差,跟cglib差不多,但是使用简单。很多开源框架都在使用它。(详细API可看主页)

反编译工具:XJAD — 将生成的class文件反编译成java文件

举报

相关推荐

0 条评论