Java——動態創建Class(不寫入文件,直接從內存中創建class)


原文:https://blog.csdn.net/zhao_xinhu/article/details/82499062#commentsedit

參考:https://www.cnblogs.com/xinruyi/p/9413007.html

package com.java.test.dynamicpojo;

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.lang.reflect.Method;
import java.net.URI;
import java.util.Arrays;

import javax.tools.FileObject;
import javax.tools.ForwardingJavaFileManager;
import javax.tools.JavaCompiler;
import javax.tools.JavaFileManager;
import javax.tools.JavaFileObject;
import javax.tools.SimpleJavaFileObject;
import javax.tools.StandardJavaFileManager;
import javax.tools.ToolProvider;

public class DynamicPOJO {
        private static String classString = "public class Student{        "
                + "       private String  studentId;                      "
                + "       public String getStudentId(){                   "
                + "           return studentId;                           "
                + "       }                                               "
                + "       public void setStudentId(String studentId){     "
                + "           this.studentId = studentId;                 "
                + "       }                                               "
                + "}                                                      ";

        private static void createStudent() throws Exception {
            JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();
            StandardJavaFileManager standardFileManager = compiler.getStandardFileManager(null, null, null);
            ClassJavaFileManager classJavaFileManager = new ClassJavaFileManager(standardFileManager);
            StringObject stringObject = new StringObject(new URI("Student.java"), JavaFileObject.Kind.SOURCE, classString);
            JavaCompiler.CompilationTask task = compiler.getTask(null, classJavaFileManager, null, null, null,
                    Arrays.asList(stringObject));
            if (task.call()) {
                ClassJavaFileObject javaFileObject = classJavaFileManager.getClassJavaFileObject();
                ClassLoader classLoader = new MyClassLoader(javaFileObject);
                Object student = classLoader.loadClass("Student").newInstance();
                System.out.println("student-->"+student);//student對象
                Method setStudentId = student.getClass().getMethod("setStudentId",String.class);//獲取set方法
                Object obj1 = setStudentId.invoke(student, "tom");//使用對象賦值
                System.out.println("-->setStudentId-->"+setStudentId.toString()+"-->"+obj1);
                Method getStudentId = student.getClass().getMethod("getStudentId");//獲取get方法
                Object obj2 = getStudentId.invoke(student);//使用對象取值
                System.out.println("-->getStudentId-->"+getStudentId.toString()+"-->"+obj2);
                
            }
        }

        /**    *自定義fileManager    */ 
        static class ClassJavaFileManager extends ForwardingJavaFileManager{
            private ClassJavaFileObject classJavaFileObject;
            public ClassJavaFileManager(JavaFileManager fileManager) {
                super(fileManager);
            } 
            public ClassJavaFileObject getClassJavaFileObject() { 
                return classJavaFileObject;
            }  
            /**這個方法一定要自定義 */
            @Override  
            public JavaFileObject getJavaFileForOutput(Location location, String className,
                    JavaFileObject.Kind kind, FileObject sibling) throws IOException {
                return (classJavaFileObject = new ClassJavaFileObject(className,kind)); 
            }
        }  
        
        /**存儲源文件*/  
        static class StringObject extends SimpleJavaFileObject{
            private String content;
            public StringObject(URI uri, Kind kind, String content) { 
                super(uri, kind);
                this.content = content;
            }   
            //使JavaCompiler可以從content獲取java源碼
            @Override 
            public CharSequence getCharContent(boolean ignoreEncodingErrors) throws IOException {
                return this.content;  
            }  
        }   
        
        /**class文件(不需要存到文件中)*/
        static class ClassJavaFileObject extends SimpleJavaFileObject{
            ByteArrayOutputStream outputStream; 
            
            public ClassJavaFileObject(String className, Kind kind) { 
                super(URI.create(className + kind.extension), kind);   
                this.outputStream = new ByteArrayOutputStream(); 
            } 
            @Override      
            public OutputStream openOutputStream() throws IOException {  
                return this.outputStream;   
            }
            //獲取輸出流為byte[]數組
            public byte[] getBytes(){      
                return this.outputStream.toByteArray();    
            }   
        }   
        
        /**自定義classloader*/
        static class MyClassLoader extends ClassLoader{ 
            private ClassJavaFileObject stringObject;  
            public MyClassLoader(ClassJavaFileObject stringObject){    
                this.stringObject = stringObject;  
            }      
            @Override
            protected Class<?> findClass(String name) throws ClassNotFoundException {
                byte[] bytes = this.stringObject.getBytes(); 
                return defineClass(name,bytes,0,bytes.length);  
            }
        }

        
        public static void main(String[] args) throws Exception {
            createStudent();
        }
        
}

 

今天聽到一個給屬性賦值的方法比invoke效率高,記錄一下

//			java.lang.reflect.Field name = clazz.getField("name");//不能訪問私有,getField用於返回一個指定名稱的屬性,但是這個屬性必須是公有的
//			name.set(obj, "tom");//set方法不能給私有屬性賦值
			
			java.lang.reflect.Field name = clazz.getDeclaredField("name");//getDeclaredField方法可以得到私有屬性
			name.setAccessible(true);//若想使用set方法給屬性賦值,需要設置accessible為true
			name.set(obj, "tom");

  

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM