欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

Java的反射機制之類加載詳解

 更新時間:2023年09月19日 08:53:28   作者:_雨_  
這篇文章主要介紹了Java的反射機制之類加載詳解,反射機制是java實現(xiàn)動態(tài)語言的關(guān)鍵,也就是通過反射實現(xiàn)類動態(tài)加載,靜態(tài)加載是指在編譯時期確定要加載的類的類型,即通過class關(guān)鍵字和類名來獲取對應(yīng)類的類型,需要的朋友可以參考下

類加載

反射機制是java實現(xiàn)動態(tài)語言的關(guān)鍵,也就是通過反射實現(xiàn)類動態(tài)加載

動態(tài)加載和靜態(tài)加載

1.靜態(tài)加載:編譯時加載相關(guān)的類,如果沒有則報錯,依賴性太強

2.動態(tài)加載:運行時加載需要的類,如果運行時不用該類,即使不存在該類,則不報錯,降低了依賴性

動態(tài)加載和靜態(tài)加載的區(qū)別

靜態(tài)加載是指在編譯時期確定要加載的類的類型,即通過  class  關(guān)鍵字和類名來獲取對應(yīng)類的類型,

動態(tài)加載則是在運行時期根據(jù)需要動態(tài)獲取需要加載的類的類型,例如使用  Class.forName()  方法

類加載時機

1.當創(chuàng)建對象時 (new) //靜態(tài)加載

2.當子類被加載時,父類也加載 //靜態(tài)加載

3調(diào)用類中的靜態(tài)成員時 //靜態(tài)加載

4.通過反射 //動態(tài)加載

類加載的五個階段

類加載器是負責把類加載到Java虛擬機中的系統(tǒng)模塊,Java中的類加載過程可以分為三個階段:

那么為什么我們有說是三個階段呢,因為在第二個階段中鏈接階段,又分為了三個部分,分別是驗證準備和解析

1.加載階段:通過類的全限定名獲取其二進制字節(jié)流,將字節(jié)流轉(zhuǎn)換成方法區(qū)內(nèi)部數(shù)據(jù)結(jié)構(gòu),在內(nèi)存中生成一個代表類的  Class  對象并返回。

2.鏈接階段:包括驗證、準備和解析的過程。

  • 驗證:檢查類的二進制字節(jié)流是否符合Java虛擬機規(guī)范,并保證不會危害虛擬機自身的安全。
  • 準備:為類的靜態(tài)變量分配內(nèi)存,并設(shè)置默認初始值。

代碼演示:

package com.reflection.classload_;
/**
 * 我們說明一個類加載的鏈接階段-準備
 */
public class ClassLoad02 {
    public static void main(String[] args) {
    }
}
class A {
    //屬性-成員變量-字段
    //分析類加載的鏈接階段-準備 屬性是如何處理
    //1. n1 是實例屬性, 不是靜態(tài)變量,因此在準備階段,是不會分配內(nèi)存
    //2. n2 是靜態(tài)變量,分配內(nèi)存 n2 是默認初始化 0 ,而不是20
    //3. n3 是static final 是常量, 他和靜態(tài)變量不一樣, 因為一旦賦值就不變 n3 = 30
    public int n1 = 10;
    public static  int n2 = 20;
    public static final  int n3 = 30;
}
  • 解析:將類中的符號引用轉(zhuǎn)換成直接引用,這個過程包括方法和字段的解析。

3.初始化階段:

到初始化階段,才真正開始執(zhí)行類中定義的 Java 程序代碼,此階段是執(zhí)行<clinit>() 方法的過程。

<clinit>() 方法是由編譯器按語句在源文件中出現(xiàn)的順序,依次自動收集類中的所有靜態(tài)變量的賦值動作和靜態(tài)代碼塊中的語句,并進行合并。

虛擬機會保證一個類的 <clinit>()方法在多線程環(huán)境中被正確地加鎖、同步,如果多個線程同時去初始化一個類,那么只會有一個線程去執(zhí)行這個類的<clinit>()方法,其他線程都需要阻塞等待,直到活動線程執(zhí)行 <clinit>() 方法完畢 [debug源碼]

代碼演示:

package com.reflection.classload_;
/**
 * 演示類加載-初始化階段
 */
public class ClassLoad03 {
    public static void main(String[] args) throws ClassNotFoundException {
        //分析
        //1. 加載B類,并生成 B的class對象
        //2. 鏈接 num = 0
        //3. 初始化階段
        //    依次自動收集類中的所有靜態(tài)變量的賦值動作和靜態(tài)代碼塊中的語句,并合并
        /*
                clinit() {
                    System.out.println("B 靜態(tài)代碼塊被執(zhí)行");
                    //num = 300;
                    num = 100;
                }
                合并: num = 100
         */
        //new B();//類加載   如果是使用的是new B()一個對象,那么還會導致構(gòu)造器被執(zhí)行,如果使用的是類的靜態(tài)屬性,那么也會導致類的加載,但是不會導致構(gòu)造器被執(zhí)行
        //System.out.println(B.num);//100, 如果直接使用類的靜態(tài)屬性,也會導致類的加載
        //看看加載類的時候,是有同步機制控制
        /*
        protected Class<?> loadClass(String name, boolean resolve)
        throws ClassNotFoundException
        {
            //正因為有這個機制,才能保證某個類在內(nèi)存中, 只有一份Class對象
            synchronized (getClassLoadingLock(name)) {
            //....
            }
            }
         */
        B b = new B();
    }
}
class B {
    static {
        System.out.println("B 靜態(tài)代碼塊被執(zhí)行");
        num = 300;
    }
    static int num = 100;
    public B() {//構(gòu)造器
        System.out.println("B() 構(gòu)造器被執(zhí)行");
    }
}

獲取類的結(jié)構(gòu)信息

Java反射中可以使用以下方法來獲取類的結(jié)構(gòu)信息:

  • getDeclaredFields() :獲取類的所有屬性(Field),包括私有屬性。
  • getFields() :獲取類的所有公有屬性。
  • getDeclaredMethods() :獲取類的所有方法(Method),包括私有方法。
  • getMethods() :獲取類的所有公有方法。
  • getDeclaredConstructors() :獲取類的所有構(gòu)造器(Constructor),包括私有構(gòu)造器。
  • getConstructors() :獲取類的所有公有構(gòu)造器。
  • getDeclaredClasses() :獲取類的所有內(nèi)部類。
  • getClasses() :獲取類的所有公有內(nèi)部類。
  • getDeclaredAnnotations() :獲取類的所有注解。
  • getSuperclass() :獲取類的父類。
  • getInterfaces() :獲取類實現(xiàn)的接口。

除了上述方法之外,還有一些其他方法可以用于獲取類的結(jié)構(gòu)信息,如 getDeclaredField() 、 getMethod() 、 getConstructor() 等,這些方法可以用于獲取指定名稱的屬性、方法或者構(gòu)造器的信息。

代碼演示;

package com.reflection;
import org.testng.annotations.Test;
import java.lang.annotation.Annotation;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
/**
 * 演示如何通過反射獲取類的結(jié)構(gòu)信息
 */
public class ReflectionUtils {
    public static void main(String[] args) {
    }
    @Test
    public void api_02() throws ClassNotFoundException, NoSuchMethodException {
        //得到Class對象
        Class<?> personCls = Class.forName("com.reflection.Person");
        //getDeclaredFields:獲取本類中所有屬性
        //規(guī)定 說明: 默認修飾符 是0 , public  是1 ,private 是 2 ,protected 是 4 , static 是 8 ,final 是 16
        Field[] declaredFields = personCls.getDeclaredFields();
        for (Field declaredField : declaredFields) {
            System.out.println("本類中所有屬性=" + declaredField.getName()
                    + " 該屬性的修飾符值=" + declaredField.getModifiers()
                    + " 該屬性的類型=" + declaredField.getType());
        }
        //getDeclaredMethods:獲取本類中所有方法
        Method[] declaredMethods = personCls.getDeclaredMethods();
        for (Method declaredMethod : declaredMethods) {
            System.out.println("本類中所有方法=" + declaredMethod.getName()
                    + " 該方法的訪問修飾符值=" + declaredMethod.getModifiers()
                    + " 該方法返回類型" + declaredMethod.getReturnType());
            //輸出當前這個方法的形參數(shù)組情況
            Class<?>[] parameterTypes = declaredMethod.getParameterTypes();
            for (Class<?> parameterType : parameterTypes) {
                System.out.println("該方法的形參類型=" + parameterType);
            }
        }
        //getDeclaredConstructors:獲取本類中所有構(gòu)造器
        Constructor<?>[] declaredConstructors = personCls.getDeclaredConstructors();
        for (Constructor<?> declaredConstructor : declaredConstructors) {
            System.out.println("====================");
            System.out.println("本類中所有構(gòu)造器=" + declaredConstructor.getName());//這里老師只是輸出名
            Class<?>[] parameterTypes = declaredConstructor.getParameterTypes();
            for (Class<?> parameterType : parameterTypes) {
                System.out.println("該構(gòu)造器的形參類型=" + parameterType);
            }
        }
    }
    //第一組方法API
    @Test
    public void api_01() throws ClassNotFoundException, NoSuchMethodException {
        //得到Class對象
        Class<?> personCls = Class.forName("com.reflection.Person");
        //getName:獲取全類名
        System.out.println(personCls.getName());//com.reflection.Person
        //getSimpleName:獲取簡單類名
        System.out.println(personCls.getSimpleName());//Person
        //getFields:獲取所有public修飾的屬性,包含本類以及父類的
        Field[] fields = personCls.getFields();
        for (Field field : fields) {//增強for
            System.out.println("本類以及父類的屬性=" + field.getName());
        }
        //getDeclaredFields:獲取本類中所有屬性
        Field[] declaredFields = personCls.getDeclaredFields();
        for (Field declaredField : declaredFields) {
            System.out.println("本類中所有屬性=" + declaredField.getName());
        }
        //getMethods:獲取所有public修飾的方法,包含本類以及父類的
        Method[] methods = personCls.getMethods();
        for (Method method : methods) {
            System.out.println("本類以及父類的方法=" + method.getName());
        }
        //getDeclaredMethods:獲取本類中所有方法
        Method[] declaredMethods = personCls.getDeclaredMethods();
        for (Method declaredMethod : declaredMethods) {
            System.out.println("本類中所有方法=" + declaredMethod.getName());
        }
        //getConstructors: 獲取所有public修飾的構(gòu)造器,包含本類
        Constructor<?>[] constructors = personCls.getConstructors();
        for (Constructor<?> constructor : constructors) {
            System.out.println("本類的構(gòu)造器=" + constructor.getName());
        }
        //getDeclaredConstructors:獲取本類中所有構(gòu)造器
        Constructor<?>[] declaredConstructors = personCls.getDeclaredConstructors();
        for (Constructor<?> declaredConstructor : declaredConstructors) {
            System.out.println("本類中所有構(gòu)造器=" + declaredConstructor.getName());//這里老師只是輸出名
        }
        //getPackage:以Package形式返回 包信息
        System.out.println(personCls.getPackage());//com.reflection
        //getSuperClass:以Class形式返回父類信息
        Class<?> superclass = personCls.getSuperclass();
        System.out.println("父類的class對象=" + superclass);//
        //getInterfaces:以Class[]形式返回接口信息
        Class<?>[] interfaces = personCls.getInterfaces();
        for (Class<?> anInterface : interfaces) {
            System.out.println("接口信息=" + anInterface);
        }
        //getAnnotations:以Annotation[] 形式返回注解信息
        Annotation[] annotations = personCls.getAnnotations();
        for (Annotation annotation : annotations) {
            System.out.println("注解信息=" + annotation);//注解
        }
    }
}
class A {
    public String hobby;
    public void hi() {
    }
    public A() {
    }
    public A(String name) {
    }
}
interface IA {
}
interface IB {
}
@Deprecated
class Person extends A implements IA, IB {
    //屬性
    public String name;
    protected static int age; // 4 + 8 = 12
    String job;
    private double sal;
    //構(gòu)造器
    public Person() {
    }
    public Person(String name) {
    }
    //私有的
    private Person(String name, int age) {
    }
    //方法
    public void m1(String name, int age, double sal) {
    }
    protected String m2() {
        return null;
    }
    void m3() {
    }
    private void m4() {
    }
}

通過反射創(chuàng)建對象

1.方式一:調(diào)用類中的public修飾的無參構(gòu)造器

2.方式二:調(diào)用類中的指定構(gòu)造器

3.Class類相關(guān)方法

  • newlnstance : 調(diào)用類中的無參構(gòu)造器,獲取對應(yīng)類的對象
  • getConstructor(Class...clazz):根據(jù)參數(shù)列表,獲取對應(yīng)的public構(gòu)造器對象
  • getDecalaredConstructor(Class...clazz):根據(jù)參數(shù)列表,獲取對應(yīng)的所有構(gòu)造器對象

4.Constructor類相關(guān)方法

  • setAccessible:暴破
  • newlnstance(Object...obj):調(diào)用構(gòu)造器

應(yīng)用案例1

代碼演示:

package com.reflection;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
/**
 * 演示通過反射機制創(chuàng)建實例
 */
public class ReflecCreateInstance {
    public static void main(String[] args) throws ClassNotFoundException, IllegalAccessException, InstantiationException, NoSuchMethodException, InvocationTargetException {
        //1. 先獲取到User類的Class對象
        Class<?> userClass = Class.forName("com.reflection.User");
        //2. 通過public的無參構(gòu)造器創(chuàng)建實例
        Object o = userClass.newInstance();
        System.out.println(o);
        //3. 通過public的有參構(gòu)造器創(chuàng)建實例
        /*
            constructor 對象就是
            public User(String name) {//public的有參構(gòu)造器
                this.name = name;
            }
         */
        //3.1 先得到對應(yīng)構(gòu)造器
        Constructor<?> constructor = userClass.getConstructor(String.class);
        //3.2 創(chuàng)建實例,并傳入實參
        Object hsp = constructor.newInstance("hsp");
        System.out.println("hsp=" + hsp);
        //4. 通過非public的有參構(gòu)造器創(chuàng)建實例
        //4.1 得到private的構(gòu)造器對象
        Constructor<?> constructor1 = userClass.getDeclaredConstructor(int.class, String.class);
        //4.2 創(chuàng)建實例
        //暴破【暴力破解】 , 使用反射可以訪問private構(gòu)造器/方法/屬性, 反射面前,都是紙老虎
        constructor1.setAccessible(true);
        Object user2 = constructor1.newInstance(100, "張三豐");
        System.out.println("user2=" + user2);
    }
}
class User { //User類
    private int age = 10;
    private String name = "明天吃火鍋";
    public User() {//無參 public
    }
    public User(String name) {//public的有參構(gòu)造器
        this.name = name;
    }
    private User(int age, String name) {//private 有參構(gòu)造器
        this.age = age;
        this.name = name;
    }
    public String toString() {
        return "User [age=" + age + ", name=" + name + "]";
    }
}

訪問屬性

1.根據(jù)屬性名獲取Field對象

Field f = clazz對象.getDeclaredField(屬性名);

2.暴破 : fsetAccessible(true); //f 是Field

3.訪問 f.set(o,值); // o 表示對象

syso(f.get(o));//o 表示對象

4.注意: 如果是靜態(tài)屬性,則set和get中的參數(shù)o,可以寫成null

代碼演示:

注意訪問私有的屬性需要進行爆破設(shè)置這個屬性    name.setAccessible(true);

package com.reflection;
import java.lang.reflect.Field;
/**
 * 演示反射操作屬性
 */
public class ReflecAccessProperty {
    public static void main(String[] args) throws ClassNotFoundException, IllegalAccessException, InstantiationException, NoSuchFieldException {
        //1. 得到Student類對應(yīng)的 Class對象
        Class<?> stuClass = Class.forName("com.reflection.Student");
        //2. 創(chuàng)建對象
        Object o = stuClass.newInstance();//o 的運行類型就是Student
        System.out.println(o.getClass());//Student
        //3. 使用反射得到age 屬性對象
        Field age = stuClass.getField("age");
        age.set(o, 88);//通過反射來操作屬性
        System.out.println(o);//
        System.out.println(age.get(o));//返回age屬性的值
        //4. 使用反射操作name 屬性
        Field name = stuClass.getDeclaredField("name");
        //對name 進行暴破, 可以操作private 屬性
        name.setAccessible(true);
        //name.set(o, "Jack");
        name.set(null, "jack~");//因為name是static屬性,因此 o 也可以寫出null
        System.out.println(o);
        System.out.println(name.get(o)); //獲取屬性值
        System.out.println(name.get(null));//獲取屬性值, 要求name是static
    }
}
class Student {//類
    public int age;
    private static String name;
    public Student() {//構(gòu)造器
    }
    public String toString() {
        return "Student [age=" + age + ", name=" + name + "]";
    }
}

訪問方法

1.根據(jù)方法名和參數(shù)列表獲取Method方法對象:

  • Method m = clazz.getDeclaredMethod(方法名,XX.class);//得到本類的所有方法

2.獲取對象 : Object o=clazz.newlnstance():

3暴破: m.setAccessible(true);

4訪問 : Object returnValue = m.invoke(o,實參列表)://o 就是對象

5注意:如果是靜態(tài)方法,則invoke的參數(shù)o,可以寫成null!

本章習題

第一題

代碼演示:

要求:

1.定義PrivateTest類,有私有name屬性,并且屬性值為hellokitty 2.提供getName的公有方法 3創(chuàng)建PrivateTest的類,利用Class類得到私有的name屬性,修改私有的name屬性值并調(diào)用getName()的方法打印name屬性值

package com.homework;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
/*
1.定義PrivateTest類,有私有name屬性,并且屬性值為hellokitty
2.提供getName的公有方法
3創(chuàng)建PrivateTest的類,利用Class類得到私有的name屬性,修改私有的name屬性值并調(diào)用getName()的方法打印name屬性值
 */
public class Homework01 {
    public static void main(String[] args) throws ClassNotFoundException, NoSuchFieldException, IllegalAccessException, NoSuchMethodException, InvocationTargetException, InstantiationException {
        //得到class類對象
        Class<?> aClass = Class.forName("com.homework.PrivateTest");
        //創(chuàng)建對象實例
        Object o = aClass.newInstance();
        //得到所有的字段
        Field name = aClass.getDeclaredField("name");
        //因為name是private私有的 因此需要進行爆破
        name.setAccessible(true);
        //修改name的值
        name.set(o, "你好");
        //得到所有方法,因為這里方法是public的因此不需要使用爆破
        Method getName = aClass.getMethod("getName");
        Object invoke = getName.invoke(o);
        System.out.println("name的屬性值是=" + invoke);
    }
}
class PrivateTest {
    private String name = "helloKitty";
    public String getName() {
        return name;
    }
}

第二題

代碼演示:

要求:

利用Class類的forName方法得到File類的class 對象 在控制臺打印File類的所有構(gòu)造器 通過newlnstance的方法創(chuàng)建File對象,并創(chuàng)建E:\ mynew.txt文件 提示:創(chuàng)建文件的正常寫法如下:File file = new File("d:  aa.txt");file.createNewFile();

package com.homework;
import java.io.File;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
/*
利用Class類的forName方法得到File類的class 對象
在控制臺打印File類的所有構(gòu)造器
通過newlnstance的方法創(chuàng)建File對象,并創(chuàng)建E:\ mynew.txt文件
提示:創(chuàng)建文件的正常寫法如下:File file = new File("d:  aa.txt");file.createNewFile();
 */
public class Homework02 {
    public static void main(String[] args) throws ClassNotFoundException, InstantiationException, IllegalAccessException, NoSuchMethodException, InvocationTargetException {
        //得到File類 的class對象
        Class<?> aClass = Class.forName("java.io.File");
        //得到所有的構(gòu)造器,并輸出
        Constructor<?>[] declaredConstructors = aClass.getDeclaredConstructors();
        for (Constructor<?> declaredConstructor : declaredConstructors) {
            System.out.println(declaredConstructor);
        }
        //得到一個指定的構(gòu)造器
        Constructor<?> constructor = aClass.getConstructor(String.class);
        //指定文件創(chuàng)建的路徑
        String filePath = "d:\\mynew.txt";
        //創(chuàng)建文件對象
        /*
            此時o相當于執(zhí)行了這么一個步驟 File file = new File(filePath);
            此時o就是File對象的實例
         */
        Object o = constructor.newInstance(filePath);
        //得到createNewFile方法的對象
        /*
            通過反射,得到file類中的一個方法createNewFIle()方法的對象
         */
        Method createNewFile = aClass.getMethod("createNewFile");
        //最后使用反射調(diào)用方法,相當于執(zhí)行了file.createNewFIle();
        //只不過一個是使用反射的方式創(chuàng)建,一個是使用new 出來的File對象的實例進行創(chuàng)建,在反射中,萬物皆對象,因此可以使用這種方法創(chuàng)建
        createNewFile.invoke(o);
        //此時o的運行類型是Java.io.File 因為在反射中所有的編譯類型都是Object
        System.out.println(o.getClass());
        System.out.println("文件創(chuàng)建成功");
    }
}

到此這篇關(guān)于Java的反射機制之類加載詳解的文章就介紹到這了,更多相關(guān)Java的反射機制內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • java切分字符串的2種方法實例

    java切分字符串的2種方法實例

    在我們?nèi)粘9ぷ髦薪?jīng)常遇到截取字符串的需求,下面這篇文章主要給大家介紹了關(guān)于java切分字符串的2種方法,文中通過實例代碼介紹的非常詳細,需要的朋友可以參考下
    2022-06-06
  • Volatile關(guān)鍵字的使用案例

    Volatile關(guān)鍵字的使用案例

    這篇文章主要介紹了Volatile關(guān)鍵字的作用,Volatile關(guān)鍵字的作用主要有兩個,本文通過實例代碼給大家介紹的非常詳細,需要的朋友可以參考下
    2023-05-05
  • java中讀寫Properties屬性文件公用方法詳解

    java中讀寫Properties屬性文件公用方法詳解

    在項目開發(fā)中我們會將很多環(huán)境特定的變量定義到一個配置文件中,比如properties文件,把數(shù)據(jù)庫的用戶名和密碼存放到此屬性文件中。下面這篇文章就主要介紹了java中讀寫Properties屬性文件公用方法,需要的朋友可以參考借鑒。
    2017-01-01
  • 從Myeclipse 導入到eclipse中無法識別為 web項目 問題的解決步驟

    從Myeclipse 導入到eclipse中無法識別為 web項目 問題的解決步驟

    這篇文章主要介紹了從Myeclipse 導入到eclipse中無法識別為 web項目 問題的解決步驟,需要的朋友可以參考下
    2018-05-05
  • spring AOP定義AfterThrowing增加處理實例分析

    spring AOP定義AfterThrowing增加處理實例分析

    這篇文章主要介紹了spring AOP定義AfterThrowing增加處理,結(jié)合實例形式分析了spring面向切面AOP定義AfterThrowing相關(guān)實現(xiàn)步驟與操作技巧,需要的朋友可以參考下
    2020-01-01
  • idea工具欄如何添加快捷圖標的操作

    idea工具欄如何添加快捷圖標的操作

    這篇文章主要介紹了idea工具欄如何添加快捷圖標的操作,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2021-02-02
  • Java面試之線程通訊方式詳解

    Java面試之線程通訊方式詳解

    線程通信是指多個線程之間通過某種機制進行協(xié)調(diào)和交互,那為什么一個線程等待和通知機制就需要這么多的實現(xiàn)方式呢?別著急,下面小編來和大家仔細聊聊
    2023-08-08
  • Spring Boot應(yīng)用監(jiān)控的實戰(zhàn)教程

    Spring Boot應(yīng)用監(jiān)控的實戰(zhàn)教程

    Spring Boot 提供運行時的應(yīng)用監(jiān)控和管理功能,下面這篇文章主要給大家介紹了關(guān)于Spring Boot應(yīng)用監(jiān)控的相關(guān)資料,文中通過示例代碼介紹的非常詳細,需要的朋友可以參考借鑒,下面隨著小編來一起學習學習吧
    2018-05-05
  • PostgreSQL Docker部署+SpringBoot集成方式

    PostgreSQL Docker部署+SpringBoot集成方式

    本文介紹了如何在Docker中部署PostgreSQL和pgadmin,并通過SpringBoot集成PostgreSQL,主要步驟包括安裝PostgreSQL和pgadmin,配置防火墻,創(chuàng)建數(shù)據(jù)庫和表,以及在SpringBoot中配置數(shù)據(jù)源和實體類
    2024-12-12
  • Java利用poi實現(xiàn)word表格轉(zhuǎn)excel

    Java利用poi實現(xiàn)word表格轉(zhuǎn)excel

    這篇文章主要為大家詳細介紹了Java如何利用poi實現(xiàn)word表格轉(zhuǎn)excel,文中的示例代碼講解詳細,感興趣的小伙伴可以跟隨小編一起學習一下
    2025-03-03

最新評論