在普通的Java类中,如果需要获取一个文件,可以通过字节码文件获取,也可以通过类加载器获取,通过字节码文件Class对象获取文件可以有两种方式,一种是获取到一个文件的输入流,然后以流的方式来操作该文件,一种是获取该文件的路径,然后通过File对象来操作该文件,通过类加载器来获取文件跟字节码文件对象获取文件是一样的,只不过他们两种方式相对的路径不一样,字节码文件对象获取文件时是相对于自身的路径而言的,而类加载器获取文件时是相对于类路径而言的:

一、假如我要在Test.java中获取类路径(classes文件夹)下的db.properties文件,这时候可以考虑用类加载器来获取,因为类加载器获取文件的路径默认是类路径下:

java有没有类似eval的方法_字节码

================================类加载器获取==============================

1.获取文件的流再通过Properties对象来操作properties文件:

InputStream in = Test.class.getClassLoader().getResourceAsStream("db.properties");
		Properties props = new Properties();
		props.load(in);
		String name = props.getProperty("name");
		System.out.println(name);



2.获取文件的路径再通过File对象操作文件:

String path = Test.class.getClassLoader().getResource("db.properties").getPath();

File file = new File(path);


一、假如我要在Test.java中获取跟Test.java文件在相同路径下的db.properties文件,这时候可以考虑用字节码文件对象来获取,因为字节码文件对象获取文件的路径默认是它自己所在的路径下:

java有没有类似eval的方法_Test_02


1.获取文件路径再通过File对象操作文件:

String path = Test.class.getResource("db.properties").getPath();
		System.out.println("path:"+path);
		File file = new File(path);
		System.out.println("file.getPath():"+file.getPath());



2.获取文件的流:

InputStream in = Test.class.getResourceAsStream("db.properties");
		Properties props = new Properties();
		props.load(in);
		String name = props.getProperty("name");
		System.out.println(name);


三、知识补充:

加入我要获取的文件在Test.java文件所在目录的下一级目录呢?怎么获取?如图所示:

java有没有类似eval的方法_java有没有类似eval的方法_03

答:加入Test.java在cn.itcast.servlet目录下,而你要获取的db.properties文件在cn.itcast.servlet.resource文件夹下,这种情况,你可以这么获取:

1.通过字节码文件对象获取:

获取方式跟上面的字节码文件对象获取文件的方式一样,但是getResource()或getResourceAsStream()方法里面,要写成"resource/db.properties"

2.通过类加载器获取:

获取方式跟上面的类加载器获取的方式一样,但是getResource()或getResourceAsStream()方法里面,要写成"cn/itcast/servlet/resource/db.properties"



下面是用Java实现了js中的eval函数的简单功能,打印一句话 "Hello ***":

import java.io.IOException;
import java.lang.reflect.Method;
import java.net.URI;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

import javax.tools.JavaCompiler;
import javax.tools.JavaFileObject;
import javax.tools.SimpleJavaFileObject;
import javax.tools.StandardJavaFileManager;
import javax.tools.ToolProvider;

public class JavaCompilerTest {

	/*
	 从java6版本开始,已经支持动态编译了,你可以在运行期直接编译.java文件,执行.class文件,并且能够获得相关的输入输出,
	 甚至还能监听相关的事件。
	 java的动态编译提供了多种渠道,比如,可以动态编译一个字符串,也可以是文本文件,也可以是编译过的字节码文件(.class文件),
	 甚至可以是存放在数据库中的明文代码或字节码,只要是符合java规范的就都可以在运行期动态加载,其实现方式就是实现JavaFileObject
	 接口,重写getCharContent、openInputStream、openOutputStream,或者实现JDK
	 已经提供的两个SimpleJavaFileObject、ForwardingJavaFileObject。下面我演示一下,如何动态编译一个字符串
	 */
	/**
	 * Java动态编译演示
	 */
	public static void main(String[] args) throws Exception {
		//Java源代码
		String sourceStr = "public class Hello{public String sayHello(String name){return \"Hello,\"+name;}}";
		//类及文件名
		String clsName = "Hello";
		//方法名  
		String methodName = "sayHello";
		/**
		 * 当前编译器:注意,如果是用的jdk1.6的版本(建议使用jdk1.7,1.7是没有任何问题的),ToolProvider.getSystemJavaCompiler()拿到的对象将会为null,
		 * 原因是需要加载的Tools.jar不在jdk安装目录的jre目录下,需要手动将lib目录下的该jar包拷贝到jre下去,详情请参考:
		 * 
		 */
		JavaCompiler cmp = ToolProvider.getSystemJavaCompiler();
		//Java标准文件管理器
		StandardJavaFileManager fm = cmp.getStandardFileManager(null, null, null);
		//Java文件对象
		JavaFileObject jfo = new StringJavaObject(clsName, sourceStr);
		//编译参数,类似于javac <options> 中的options 
		List<String> optionsList = new ArrayList<String>();
		//编译文件的存放地方,注意:此处是为Eclipse工具特设的
		optionsList.addAll(Arrays.asList(new String[]{"-d", "./bin"}));
		//要编译的单元
		List<JavaFileObject> jfos = Arrays.asList(new JavaFileObject[]{jfo});
		//设置编译环境
		JavaCompiler.CompilationTask task = cmp.getTask(null, fm, null, optionsList, null, jfos);
		//编译成功
		if(task.call()){
			//生成对象
			Object obj = Class.forName(clsName).newInstance();
			Class<? extends Object> cls = obj.getClass();
			//调用sayHello方法
			Method m = cls.getMethod(methodName, String.class);
			String str = (String) m.invoke(obj, "royise");
			System.out.println(str);
		}
	}

}

class StringJavaObject extends SimpleJavaFileObject {
	/**
	 * 源代码
	 */
	private String content = "";
	
	/**
	 * 遵循Java规范的类名及文件
	 */
	public StringJavaObject(String javaFileName, String content){
		super(_createStringJavaObjectUri(javaFileName), Kind.SOURCE);
		this.content = content;
	}
	
	/**
	 * 产生一个URL资源路径
	 */
	private static URI _createStringJavaObjectUri(String javaFileName) {
		//注意此处未设置包名
		return URI.create("String:///" + javaFileName + Kind.SOURCE.extension);
	}

	/**
	 * 文本文件代码
	 */
	@Override
	public CharSequence getCharContent(boolean ignoreEncodingErrors)
			throws IOException {
		return content;
	}
}