2009-07-23 7 views
3

eval은 "악"이라고 알고 있지만 사용자가 악용 할 수 없도록 사용하고 있습니다.자바에서 문자열로부터 객체를 만드는 법 (문자열을 평가하는 방법)?

"new Integer (5)"라는 문자열이 있다고 가정 해 보겠습니다. 변수를 설정할 수있는 뭔가를하고 싶습니다. 새로운 Integer (5)에 foo라고 가정 해 봅시다. 예를 들어

Integer foo; 
String bar = "new Integer(5)" 
*magic happens* 
System.out.println(foo) -> 5 

나는 둘러 보았고 몇 가지 옵션이있는 것 같습니다. ToolProvider의 getSystemJavaCompiler() 메소드가 이것을 할 수 있습니까? 아니면 BeanShell을 사용해야합니까? 아니면 다른 것이 있습니까? 이 파일은 문자열이 아니라 파일입니다.

+2

나는 사용자가 '악용하다'라는 두려움은 주요한 악이 아니라고 생각한다. 대부분의 경우 eval을 남용하는 프로그래머입니다. Java와 같은 강력한 형식의 언어에서는 eval이 유지 보수 프로그래머를 혼란에 빠뜨립니다. – Josiah

+0

왜 이것을하고 싶습니까? 이것이 유용 할 실제 상황이 없다고 생각할 수 있습니다. XY 문제가있는 것 같아요. – Raedwald

답변

3

은 내가 Integer class 값을 설정하는 생성자의 String, 제공된 문자열을 가정 소요

1

는 숫자 만 텍스트를 포함 등으로 Beanshell, JRuby를, 자이 썬과 같은 스크립트 언어를 사용합니다.

Integer foo; 

public void setFoo(String str) { 
    if(isInt(str)) { 
    foo = new Integer(str.trim()); 
    } 
} 

// Returns a boolean based on if the provided string contains only numbers 
private boolean isInt(String str) { 
    boolean isInt = true; 

    try { 
    Integer.parseInt(str.trim()); 
    } catch (NumberFormatException nfe) { 
    isInt = false; 
    } 

    return isInt; 
} 

// Get the value as an int rather than Integer 
public int getIntValue(String str) { 
    return Integer.parseInt(str.trim()); 
} 
+0

예를 들어 일반 솔루션을 찾고 있는데 – swampsjohn

+0

Java는 강력한 형식의 언어입니다.하지만 대부분의 항목은 생성자 매개 변수에 대해 String을 사용할 수 있습니다. 왜 자바를 직접 사용하지 않고 내용이 자바 언어 인 문자열을 제공하겠습니까? –

0

자바는 정적으로 입력 된 언어이므로 사용자가 그렇게 할 수 있다고 생각하지 않습니다.

+0

글쎄, 할 수 있지만 런타임에 자바 컴파일러 (또는 유사)를 호출 한 다음 결과 바이트 코드 파일을 동적으로로드하는 작업이 필요합니다. –

3

Janino과 같은 것을 사용해야합니다.

2

이런 종류의 일은 가능하지만이 작업만큼 간단한 작업에는 굉장히 비쌉니다. 이 예제에서는 Class.forName()을 사용하여 "Integer"를 클래스에 매핑하고 Java 리플렉션을 사용하여 생성자를 호출합니다.

3

javax.tools를 사용하여 대부분의 방법을 사용할 수 있습니다. 이 코드는 오히려 길고 정확하게 이것을 수행하는 가장 효율적이거나 이식 가능한 방법은 아니지만 아이디어를 얻어야합니다.

import javax.tools.*; 
import java.util.*; 
import java.io.*; 
import java.lang.reflect.*; 

public class Test { 
    public static void main(String[] args) throws Exception { 
    JavaCompiler compiler = ToolProvider.getSystemJavaCompiler(); 
    JavaFileObject fileObj = 
     new StringJavaFileObject("public class InterpTest { public static void test() { System.out.println(\"Hello World\"); } }"); 
    List<JavaFileObject> tasks = new ArrayList<JavaFileObject>(); 
    tasks.add(fileObj); 

    JavaFileManager defFileMgr = compiler.getStandardFileManager(null, null, null); 
    MemoryJavaFileManager fileMgr = new MemoryJavaFileManager(defFileMgr); 
    compiler.getTask(null, fileMgr, null, null, null, tasks).call(); 

    ClassLoader loader = new ByteArrayClassLoader(); 
    Class clazz = loader.loadClass("InterpTest"); 
    Method method = clazz.getMethod("test"); 
    method.invoke(null); 
    } 

    public static class StringJavaFileObject extends SimpleJavaFileObject { 
    protected String str; 

    public StringJavaFileObject(String str) { 
     super(java.net.URI.create("file:///InterpTest.java"), JavaFileObject.Kind.SOURCE); 
     this.str = str; 
    } 

    @Override 
    public CharSequence getCharContent(boolean ignoreEncErrors) { 
     return str; 
    } 
    } 

    public static class MemoryJavaFileObject extends SimpleJavaFileObject { 
    public static ByteArrayOutputStream out = new ByteArrayOutputStream(); 

    public MemoryJavaFileObject(String uri, JavaFileObject.Kind kind) { 
     super(java.net.URI.create(uri), kind); 
    } 

    @Override 
    public OutputStream openOutputStream() { 
     return out; 
    } 
    } 

    public static class ByteArrayClassLoader extends ClassLoader { 
    public Class findClass(String name) { 
     byte[] bytes = MemoryJavaFileObject.out.toByteArray(); 
     return super.defineClass(name, bytes, 0, bytes.length); 
    } 
    } 

    public static class MemoryJavaFileManager implements JavaFileManager { 
    protected JavaFileManager parent; 

    public JavaFileObject getJavaFileForOutput(JavaFileManager.Location location, String className, JavaFileObject.Kind kind, FileObject sibling) throws IOException { 
     return new MemoryJavaFileObject("file:///InterpTest.class", kind); 
    } 

    public MemoryJavaFileManager(JavaFileManager parent) { this.parent = parent; } 
    public void close() throws IOException { parent.close(); } 
    public void flush() throws IOException { parent.flush(); } 
    public ClassLoader getClassLoader(JavaFileManager.Location location) { return parent.getClassLoader(location); } 
    public FileObject getFileForInput(JavaFileManager.Location location, String packageName, String relName) throws IOException { return parent.getFileForInput(location, packageName, relName); } 
    public FileObject getFileForOutput(JavaFileManager.Location location, String packageName, String relName, FileObject sibling) throws IOException { return parent.getFileForOutput(location, packageName, relName, sibling); } 
    public JavaFileObject getJavaFileForInput(JavaFileManager.Location location, String className, JavaFileObject.Kind kind) throws IOException { return parent.getJavaFileForInput(location, className, kind); } 
    public boolean handleOption(String current, Iterator<String> remaining) { return parent.handleOption(current, remaining); } 
    public boolean hasLocation(JavaFileManager.Location location) { return parent.hasLocation(location); } 
    public String inferBinaryName(JavaFileManager.Location location, JavaFileObject file) { return parent.inferBinaryName(location, file); } 
    public boolean isSameFile(FileObject a, FileObject b) { return parent.isSameFile(a, b); } 
    public Iterable<JavaFileObject> list(JavaFileManager.Location location, String packageName, Set<JavaFileObject.Kind> kinds, boolean recurse) throws IOException { return parent.list(location, packageName, kinds, recurse); } 
    public int isSupportedOption(String option) { return parent.isSupportedOption(option); } 
    } 
} 
0

Java Scripting API을 사용할 수 있습니다. 기본 언어는 JavaScript이지만 모든 언어를 연결할 수 있습니다. 자바 1.6 필요합니다.

관련 문제