标签 - 基础

算法 基础 加密    2016-03-02 20:35:30    877    0    0

Base64 是什么?

Base64是一种数据表示方法,它使用64个可打印字符来表示二进制数据,所以才叫做Base64。

Base64 能做什么?

Base64一般用于处理文本数据,表示、传输、存储。比如MIME中的email,以及在xml中存储复杂数据。
编码
将普通数据转换成符合Base64标准的数据的过程。
解码
将Base64标准的数据转换成普通数据的过程。

Base64 的原理?

64个可打印字符

52个字母:大写字母+小写字母
10个数字:0~9
两个特殊字符:+ 和 /
以上就够64个了,但是有时候还会用一个“=”,等号的作用是填充,后面会讲到。

Base64字符对照表:

数值 字符 数值 字符 数值 字符 数值 字符
0 A 16 Q 32 g 48 w
1 B 17 R 33 h 49 x
2 C 18 S 34 i 50 y
3 D 19 T 35 j 51 z
4 E 20 U 36 k 52 0
5 F 21 V 37 l 53 1
6 G 22 W 38 m 54 2
7 H 23 X 39 n 55 3
8 I 24 Y 40 o 56 4
9 J 25 Z 41 p 57 5
10 K 26 a 42 q 58 6
11 L 27 b 43 r 59 7
12 M 28 c 44 s 60 8
13 N 29 d 45 t 61 9
14 O 30 e 46 u 62 +
15 P 31
java 基础    2016-02-10 10:26:37    602    0    0

long和double类型

在java中,long和double类型的数据都占8个字节长度,即64位。对于long和double类型的读写操作,java并不能保证其原子性。下面的内容来自Java Language Specification:

For the purposes of the Java programming language memory model, a single write to a non-volatile long or double value is treated as two separate writes: one to each 32-bit half. This can result in a situation where a thread sees the first 32 bits of a 64-bit value from one write, and the second 32 bits from another write.
Writes and reads of volatile long and double values are always atomic.
Writes to and reads of references are always atomic, regardless of whether they are implemented as 32-bit or 64-bit values.
Some implementations may find it convenient to divide a single write action on a 64-bit long or double value into two write actions on adjacent 32-bit values. For efficiency’s sake, this behavior is implementation-specific; an implementation of the Java Virtual Machine is free to pe

java 基础    2016-02-06 19:06:38    3859    0    0

Thread.setContextClassLoader(ClassLoader cl)

在Java中提供了对于线程设置ContextClassLoader的方法,关于上下文类加载器,下面摘抄的内容将的比较明白:

线程上下文类加载器(context class loader)是从 JDK 1.2 开始引入的。类 java.lang.Thread中的方法 getContextClassLoader()和 setContextClassLoader(ClassLoader cl)用来获取和设置线程的上下文类加载器。如果没有通过 setContextClassLoader(ClassLoader cl)方法进行设置的话,线程将继承其父线程的上下文类加载器。Java 应用运行的初始线程的上下文类加载器是系统类加载器。在线程中运行的代码可以通过此类加载器来加载类和资源。
前面提到的类加载器的代理模式并不能解决 Java 应用开发中会遇到的类加载器的全部问题。Java 提供了很多服务提供者接口(Service Provider Interface,SPI),允许第三方为这些接口提供实现。常见的 SPI 有 JDBC、JCE、JNDI、JAXP 和 JBI 等。这些 SPI 的接口由 Java 核心库来提供,如 JAXP 的 SPI 接口定义包含在 javax.xml.parsers包中。这些 SPI 的实现代码很可能是作为 Java 应用所依赖的 jar 包被包含进来,可以通过类路径(CLASSPATH)来找到,如实现了 JAXP SPI 的 Apache Xerces所包含的 jar 包。SPI 接口中的代码经常需要加载具体的实现类。如 JAXP 中的 javax.xml.parsers.DocumentBuilderFactory类中的 newInstance()方法用来生成一个新的 DocumentBuilderFactory的实例。这里的实例的真正的类是继承自 javax.xml.parsers.DocumentBuilderFactory,由 SPI 的实现所提供的。如在 Apache Xerces 中,实现的类是 org.apa

java 基础 compilerAPI    2016-02-05 13:54:08    707    0    0

思考:如果允许用户输入java代码,然后在程序中编译执行,该如何做?

其实这可以通过扩展Java Compiler API来实现。

问题引入

假设我们要实现一个计算器,给定两个参数,根据不同的算法计算结果,而算法的实现是允许用户手动输入的,用户输入的算法不同,计算结果也不同。

实现思路

  1. 首先我们需要定义一个算法接口Function,它提供一个calculate(int x,int y)方法,返回x和y的计算结果。
  2. 用户通过手动输入代码来提供Function接口的具体实现类
  3. 用户输入完成之后,程序自动加载用户输入的代码并执行,然后将执行结果输出

具体实现

Function接口

首先我们需要定义一个Function接口,代码如下:

public interface Function {
    public int calculate(int x, int y); //为了简单,这里参数与返回值都是int类型
}

动态加载

java程序执行之前,需要将java源代码编译成class文件,然后将class文件通过ClassLoader加载到JVM虚拟机,然后创建对应类对象才能执行。同样道理,用户输入的字符串也需要经过编译,加载才能运行。所以我们也需要两步:1.编译代码 2.通过ClassLoader加载实现类

编译字符串源码

动态编译需要使用Java Compiler API,我们首先自定义一个编译器,实现编译字符串源码的功能。
下面是一个完整实现:
public Class<?> compile(String classFullName, String sourceCode) throws Exception方法需要两个参数,第一个是完整的类名,第二个是对应的源码。该方法执行了两个过程:1.编译2.loadClass,返回值为对应的Class实例
过程中需要自定义ClassLoader:ClassLoaderImpl,自定义JavaObjectFile:JavaObjectFileImpl,自定义FileManager:FileManagerImpl

package com.
java 基础 compilerAPI    2016-02-04 16:59:09    1351    0    0

问题引入

在研究Dubbo源码的时候发现了Dubbo提供的Adaptive机制是通过动态生成java代码,然后编译返回Class类实例的方式实现的,研究发现使用的是java提供的compiler API,于是决定先研究下这个API,以实现动态编译java类并返回java Class实例功能。

Java Compiler API(编译框架)

JSR199提出了Java Compiler API来提供一种编译java代码的标准方式。java compiler API存在于javax.tools包中。它允许客户端通过程序定位并执行编译器,从而实现动态编译java代码。

使用介绍

编译java类文件

定义一个需要被动态编译的类:

public class HelloWorld {
    public void print() {
        System.out.println("hello world!");
    }
}

通过JavaCompiler进行编译:

public static void main(String[] args) throws FileNotFoundException {
        // 获取系统的java编译器
        JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();
        // 指定要编译的java文件
        String fileToCompile = "D:/eclipse_workspace/compile/src/main/java/com/medusar/compile/HelloWorld.java";
        // 执行编译方法
        int compilationResult = compiler.run(null, null, null, fileToCompile);
        // 返回0表示编译成功
        if (compilationResult == 0) {
            System.out.pr