Artikel ini membawakan anda pengetahuan yang berkaitan tentang java Ia terutamanya memperkenalkan prinsip mekanisme refleksi dan isu berkaitan beberapa kaedah pemerolehan kelas dan senario aplikasi saya harap ia akan membantu semua orang.
Kajian yang disyorkan: "tutorial pembelajaran java"
Rakan yang sedang belajar Java mungkin pernah mendengar tentang Java反射机制
, tetapi mereka biasa dengannya Agak asing Artikel ini terutamanya menumpukan pada memikirkan beberapa Java反射机制
soalan yang sering ditanya dalam temu bual, dan kemudian menerangkannya melalui 理论知识
digabungkan dengan 代码实例
dan 应用场景
untuk mendalami pemahaman saya tentang. Java反射机制
dan saya faham, dan saya harap ia dapat membantu rakan yang memerlukan~
(1) Mekanisme refleksi Java (Java Reflection
) ialah keupayaan 动态(运行时)访问、检测 & 修改它本身
dalam bahasa Java Fungsi utamanya ialah 动态(运行时)获取类的完整结构信息 & 调用对象的方法
~
Untuk meletakkannya dengan lebih mudah, program Java mencipta objek pantulan kelas (secara dinamik) pada masa jalan, dan kemudian melaksanakan operasi berkaitan pada kelas, seperti:
PS: Tetapi sejujurnya, ia masih agak sukar untuk difahami jika anda melihat secara langsung pada definisi rasmi. Mari kita bercakap mengenainya dengan cara yang lebih popular~
(2) Dalam keadaan biasa, kami menggunakan Untuk kelas tertentu, semua orang akan mengetahui kelas ini dan untuk kegunaannya Anda boleh terus mencipta objek melalui new
instantiasi, dan kemudian menggunakan objek ini kendalikan kelas ini kepunyaan 正射
~
(3) Walau bagaimanapun, 反射
tidak tahu kelas yang hendak dimulakan pada mulanya dan tidak boleh menggunakan new
untuk membuat instantiate dan mencipta objek. Ini terutamanya dicapai melalui API pantulan yang disediakan oleh JDK Hanya pada masa jalan anda tahu kelas yang anda ingin kendalikan, dan anda boleh mendapatkan struktur lengkap kelas dan memanggil kaedah yang sepadan >~反射
Kodnya adalah seperti berikut:
package com.justin.java.lang;import java.lang.reflect.Constructor;import java.lang.reflect.Method;/** * @program: Jdk1.8 Test * @description: 正射、反射简单调用示例 * @author: JustinQin * @create: 2021/8/22 13:23 * @version: v1.0.0 **/public class Student { private int id; public void setId(int id) { this.id = id; } public int getId() { return id; } public static void main(String[] args) throws Exception{ //一、正射调用过程 Student student = new Student(); student.setId(1); System.out.println("正射调用过程Student id:" + student.getId()); //二、反射调用过程 Class clz = Class.forName("com.justin.java.lang.Student"); Constructor studentConstructor = clz.getConstructor(); Object studentObj = studentConstructor.newInstance(); Method setIdMethod = clz.getMethod("setId", int.class); setIdMethod.invoke(studentObj, 2); Method getIdMethod = clz.getMethod("getId"); System.out.println("正射调用过程Student id:" + getIdMethod.invoke(studentObj)); }}
Hasil output:
正射调用过程Student id:1反射调用过程Student id:2
Anda boleh melihat proses panggilan pantulan dalam contoh di atas untuk mendapatkan kelas, proses utamanya ialah: 反射对象
Class
Class
berdasarkan Constructor
objek contoh Constructor
newInstance
反射对象
Selepas mendapat kelas, anda boleh mengendalikan kelas~ Contohnya, proses memanggil kaedah. kelas dalam contoh di atas ialah: 反射对象
Class
objek contoh Method
Method
objek memanggil kaedah kelas tertentu invoke
Seperti yang dinyatakan dalam perkara sebelumnya, kita memperoleh objek contoh dalam contoh di atas Class
kami menggunakan 反向调用过程
Kaedah ini digunakan untuk mendapatkan Class.forName("类的全局定名")
objek contoh kelas Selain ini, terdapat dua kaedah lain yang biasa digunakan, yang akan diterangkan di bawah~Class
<.> 2. Mendapatkan Kelas dalam mekanisme refleksi Java Tiga cara dan perbezaannya?
2.1 Beberapa cara untuk mendapatkan Kelas
(1) Dapatkan objek contoh Tiga cara biasa ialah: : java.lang.Class
MyClass.class
diperoleh melalui Class.forName("类的全局定名")
Diperolehi melalui new MyClass().getClass()
, JVM akan menggunakan pemuat kelas untuk memuatkan kelas ke dalam memori, tetapi MyClass.class
tidak akan melakukan sebarang kerja permulaan kelasClassLoader
dan mengembalikan objek java.lang.Class
, begitu juga, kelas akan JVM dimuatkan ke dalam ingatan, dan akan melakukan pemulaan statik kelas (4)通过 PS: 这3种方式,最终在JVM堆区对应类的 创建一个实体类,分别在实体类中创建类的 (1)实体类: (2)单元测试类: 逐个执行单元,得出测试结果为: 通过 而 讲了这么多,除了知道基本原理和基本使用之外,更重要的还是要知道它的一些比较实际的 Java中主要有23种设计模式,其中工厂模式就是其中一种,而简单工厂模式,顾名思义,也是属于工厂模式中的一种,只不过比较简单。简单工厂模式也可以叫做静态方法模式(因为工厂类一般都是在内部定义了一个静态方法)。 简单工厂模式通过创建一个对应的工厂类,将 实现简单工程模式的核心是创建一个 实现例子: 步骤1:创建抽象产品类 步骤2:创建具体产品类: 步骤3:创建简单工厂类 步骤4:调用简单工厂类 (1)简单工厂模式弊端 这两点弊端从前面的例子 (2)简单工厂模式的优化思路 (3)简单工厂模式的优化步骤 步骤2:调用工厂类 优化结果: 使用 (1)再次优化背景 简单工厂模式的工厂类采用 (2)再次优化实现思路 通过 (3)再次优化实现步骤 再次优化步骤1:相关优化与第一次优化保持不变~ 再次优化步骤2:配置 注意:将 再次优化步骤3:修改调用工厂类 运行结果: 什么?还是不太理解? 更通俗一点的说代理模式,就是想做某件事( 代理模式又分为静态代理、动态代理,往下介绍~ (1) 动态代理 (1) 动态代理最常用的是 JDK 原生动态代理 JDK 原生动态代理,主要利用了 通过 例子: 用户接口类 目标对象类 动态代理类 动态代理单元测试类 单元测试执行结果 cglib动态代理 JDK原生动态代理中,获取代理示例对象过程中,获取目标对象的类加载器,通过 相信很多小伙伴都知道 创建测试库表及数据 Java MySQL JDBC连接七大步骤~ 执行结果: Java Oracle JDBC连接七大步骤~ PS:上面通过Java JDBC连接数据库并进行操作,这里的连接是单一连接,直接通过DriverManager.getConnection这种Java原生的数据库连接方式建立的连接,现在实际的Java Spring项目当中,都是通过配置mybatis的数据库连接池来实现的,不过原理都是一样的,加载驱动也是利用了 数据库连接池配置 数据库配置信息 一、Java反射机制是什么? 1、Java反射机制( 2、更通俗点的说,我们使用某个类,都会知道这个类,以及要用它来做什么,可以直接通过 3、而 2. Tiga cara untuk mendapatkan mekanisme pantulan Kelas dalam Java dan perbezaannya? 1 Dapatkan , JVM akan menggunakan Begitu juga, kelas akan dimuatkan ke dalam memori oleh JVM, dan , kaedah ini menggunakan bagi kelas yang sepadan dalam kawasan timbunan JVM semuanya milik yang sama, iaitu ialah, 3. Apakah senario aplikasi mekanisme pantulan Java? Pengoptimuman corak kilang mudah dalam tutorial java"Class.forName("类的全局定名")
dan mengembalikan objek java.lang.Class
new MyClass().getClass()
获取,这种方式使用了new
进行实例化操作,因此静态初始化和非静态初始化工作都会进行,getClass
方法属于顶级Object
类中的方法,任何子类对象都可以调用,哪个子类调用,就返回那个子类的java.lang.Class
对象java.lang.Class
对象都属于同一个,也就是内存地址相同,进行==
双等号比较结果为true
,原因是JVM类加载过程中使用的是同一个ClassLoader
类加载器加载某个类,不论加载多少次,生成到堆区的java.lang.Class
对象始终只有一个,除非自定义类加载器,破坏JVM的双亲委派机制,使得同一个类被不同类加载器加载,JVM才会把它当做两个不同的java.lang.Class
对象2.2 代码演示几种方式的区别
静态代码块
、动态代码块
、有参构造方法
、无参构造方法
,方便测试几种方式的区别及内存地址是否相同~public class MyClass {
private static final String staticStr = "Hi";
private static int staticInt = 2021;
private String id;
static {
System.out.println("静态代码块:staticStr=" + staticStr + ",staticInt=" + staticInt);
}
{
System.out.println("动态代码块~");
}
public MyClass() {
System.out.println("无参构造方法~");
}
public MyClass(String id) {
System.out.println("有参构造方法~");
this.id = id;
}
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
@Override
public String toString() {
return "MyClass{" +
"id='" + id + '\'' +
'}';
}}
通过@Test
注解对三种方式分别进行单元测试,再对这三种方式的组合进行单元测试~package com.justin.java.lang;import org.junit.Test;/**
* @program: Jdk1.8Test
* @description: Java反射机制中获取类的Class实例对象的常见三种方式及区别对比
* @author: JustinQin
* @create: 2021/8/22 15:04
* @version: v1.0.0
**/public class MyClassTest {
@Test
public void test1() {
System.out.println("一、MyClass.class方式=========");
Class> class1 = MyClass.class;
}
@Test
public void test2() throws ClassNotFoundException {
System.out.println("二、Class.forName方式=========");
Class class2 = Class.forName("com.justin.java.lang.MyClass");
}
@Test
public void test3() {
System.out.println("三、new MyClass().getClass方式=========");
Class class3 = new MyClass().getClass();
}
@Test
public void test12() throws ClassNotFoundException {
System.out.println("一、MyClass.class方式=========");
Class> class1 = MyClass.class;
System.out.println("二、Class.forName方式=========");
Class class2 = Class.forName("com.justin.java.lang.MyClass");
}
@Test
public void test13() {
System.out.println("一、MyClass.class方式=========");
Class> class1 = MyClass.class;
System.out.println("三、new MyClass().getClass方式=========");
Class class3 = new MyClass().getClass();
}
@Test
public void test23() throws ClassNotFoundException {
System.out.println("二、Class.forName方式=========");
Class class2 = Class.forName("com.justin.java.lang.MyClass");
System.out.println("三、new MyClass().getClass方式=========");
Class class3 = new MyClass().getClass();
}
@Test
public void test() throws ClassNotFoundException {
System.out.println("四、三种方式内存地址比较=========");
Class> class1 = MyClass.class;
Class class2 = Class.forName("com.justin.java.lang.MyClass");
Class class3 = new MyClass().getClass();
System.out.println("比较结果=========");
System.out.println("MyClass.class和Class.forName内存地址比较是否相同:" + (class1 == class2));
System.out.println("MyClass.class和new MyClass().getClass内存地址比较是否相同:" + (class1 == class3));
System.out.println("Class.forName和new MyClass().getClass内存地址比较是否相同:" + (class2 == class3));
}}
* test1()方法
一、MyClass.class方式=========* test2()方法
二、Class.forName方式=========静态代码块:staticStr=Hi,staticInt=2021* test3()方法
三、new MyClass().getClass方式=========静态代码块:staticStr=Hi,staticInt=2021动态代码块~无参构造方法~* test12()方法
一、MyClass.class方式=========二、Class.forName方式=========静态代码块:staticStr=Hi,staticInt=2021* test13()方法
一、MyClass.class方式=========三、new MyClass().getClass方式=========静态代码块:staticStr=Hi,staticInt=2021动态代码块~无参构造方法~* test23()方法
二、Class.forName方式=========静态代码块:staticStr=Hi,staticInt=2021三、new MyClass().getClass方式=========动态代码块~无参构造方法~* test()方法
四、三种方式内存地址比较=========静态代码块:staticStr=Hi,staticInt=2021动态代码块~无参构造方法~比较结果=========MyClass.class和Class.forName内存地址比较是否相同:trueMyClass.class和new MyClass().getClass内存地址比较是否相同:trueClass.forName和new MyClass().getClass内存地址比较是否相同:true
test1
、test2
、test3
的测试结果验证了2.1 三种方式及区别
中黄色标记部分的区别说明,即:
MyClass.class
不会做任何类的初始化工作Class.forName
会进行类的静态初始化工作new MyClass().getClass
静态初始化和非静态初始化工作都会进行内存地址相同
的test23
组合得到的测试结果,说明静态代码块只会被加载一次
~应用场景
,往下介绍~三、Java反射机制的应用场景有哪些?
3.1 应用场景
工厂模式
中的简单工厂模式优化代理模式
中的动态代理方式实现Java JDBC
数据库操作3.2 简单工厂模式优化
3.2.1 什么是简单工厂模式?
从现实生活角度来理解的话,工厂是专门负责生产产品的,同样在设计模式中,简单工厂模式我们可以理解为专门负责生产对象的一个类,称为“工厂类”。3.2.2 简单工厂模式有什么用?
类实例化的操作
与使用对象的操作
进行分开,让使用者不用知道具体参数就可以实例化出所需要的具体产品
类,从而避免了在客户端代码中显式指定,实现了解耦。即使用者可直接消费产品而不需要知道其生产的细节~3.2.3 如何实现简单工程模式?
工厂类
,并且在内部定义了一个静态方法,传入不同的参数标识
通过switch
进行分组,通过new
实例化创建不同的子类对象返回~public interface Product {
public abstract void show();}
public class ProductA implements Product {
@Override
public void show() {
System.out.println("生产了产品A");
}}public class ProductB implements Product {
@Override
public void show() {
System.out.println("生产了产品B");
}}public class ProductC implements Product {
@Override
public void show() {
System.out.println("生产了产品C");
}}
public class SimpleFactory {
/**
* 实现简单工厂模式
* @param pName 产品标识
* @return 返回具体的产品
*/
public static Product createProduct(String pName){
switch (pName){
case "A":
return new ProductA();
case "B":
return new ProductB();
case "C":
return new ProductC();
default:
return null;
}
}}
public class SimpleFactoryTest {
public static void main(String[] args) {
try {
SimpleFactory.createProduct("A").show();
} catch (NullPointerException e) {
System.out.println("没有A这款产品,无法生产~");
}
try {
SimpleFactory.createProduct("B").show();
} catch (NullPointerException e) {
System.out.println("没有B这款产品,无法生产~");
}
try {
SimpleFactory.createProduct("C").show();
} catch (NullPointerException e) {
System.out.println("没有C这款产品,无法生产~");
}
try {
SimpleFactory.createProduct("D").show();
} catch (NullPointerException e) {
System.out.println("没有D这款产品,无法生产~");
}
}}
3.2.4 简单工厂模式优化
SimpleFactory
工厂类的实现,可以看出简单工厂模式
中对工厂类SimpleFactory
的维护成本有点大,因为实际中可能会很频繁的去更新具体产品类
,每一次变更都需要去修改工厂类,此时就可以利用Java反射机制
对简单工厂模式进行优化~
采用Java反射机制,通过传入子类全局定名(包名+类名)
动态的创建不同的子类对象实例
,从而使得在不增加产品接口子类和修改工厂类的逻辑的情况下还能实现了工厂类对子类实例对象的统一创建~
步骤1:创建工厂类
采用Java反射机制对工厂类进行优化,主要是将className
即子类全局定名(包名+类名)
作为入参,通过Class.forName
方式获取类的java.lang.Class
实例对象,再通过Class
实例对象的getInstance
方法获取到具体子类的实例对象~public class Factory {
public static Product getInstance(String className) {
Product realProduct = null;
try {
Class pClass = Class.forName(className);
realProduct = (Product) pClass.newInstance();
} catch (Exception e) {
e.printStackTrace();
}
return realProduct;
}}
public class FactoryTest {
public static void main(String[] args) {
try {
Product productA = Factory.getInstance("com.justin.java.lang.ProductA");
productA.show();
} catch (NullPointerException e) {
System.out.println("没有A这款产品,无法生产~");
}
try {
Product productB = Factory.getInstance("com.justin.java.lang.ProductB");
productB.show();
} catch (NullPointerException e) {
System.out.println("没有B这款产品,无法生产~");
}
try {
Product productC = Factory.getInstance("com.justin.java.lang.ProductC");
productC.show();
} catch (NullPointerException e) {
System.out.println("没有C这款产品,无法生产~");
}
try {
Product productD = Factory.getInstance("com.justin.java.lang.ProductD");
productD.show();
} catch (Exception e) {
System.out.println("没有D这款产品,无法生产~");
}
}}
Java反射机制
优化简单工厂模式后,可以看到,不论具体产品类
更新多频繁,都不需要再修改工厂类
,从而解决了普通简单工厂模式操作成本高
和系统复杂性高
的问题~3.2.5 简单工厂模式再次优化
Java反射机制
进行优化后,此时的仍然存在这样一个问题,子类的全局定名(包名+类名)
是写死的,但是实际上开发者在写代码时是很难提前预知所有的子类的全局定名(包名+类名)
的,因此需要进行二次优化~配置文件
方式,统一定义类名对应全局定名(包名+类名)
,将配置文件存放到资源目录下,程序运行时通过ClassLoader
类加载器动态获取到配置文件
中定义的子类的全局定名~类名对应全局定名(包名+类名)
创建属性配置文件Product.properties
//产品抽象类Product相关子类的全局定名(包名+类名)定义ProductA = com.justin.java.lang.ProductAProductB = com.justin.java.lang.ProductBProductC = com.justin.java.lang.ProductC
Product.properties
需要存放在src/main/resources
资源目录下,若资源目录不存在则需要手动创建~public class FactoryTest {
@Test
public void test() throws IOException {
ClassLoader classLoader = this.getClass().getClassLoader();
Properties prop = new Properties();
prop.load(classLoader.getResourceAsStream("Product.properties"));
String className = "";
try {
className = prop.getProperty("ProductA");
Product productA = Factory.getInstance(className);
productA.show();
} catch (NullPointerException e) {
System.out.println("没有A这款产品,无法生产~");
}
try {
className = prop.getProperty("ProductB");
Product productA = Factory.getInstance(className);
productA.show();
} catch (NullPointerException e) {
System.out.println("没有B这款产品,无法生产~");
}
try {
className = prop.getProperty("ProductC");
Product productA = Factory.getInstance(className);
productA.show();
} catch (NullPointerException e) {
System.out.println("没有C这款产品,无法生产~");
}
}}
生产了产品A生产了产品B生产了产品C
3.3 代理模式中的动态代理实现
3.3.1 什么是代理模式?
代理(Proxy)模式
是一种设计模式
,通过代理对象
来访问目标对象
,还可以在不修改目标对象
的情况下,对代理对象
进行拓展,增强目标对象
的功能~买火车票
),自己
能买(直接去火车站
买),却委托别人去买(没空还是代理点
买吧),还可以让别人帮自己做其他事(订好酒店)~3.3.2 什么是静态代理?
静态代理
属于代理模式
的一种代理方式,需要代理对象
和目标对象
实现相同的接口
(2)静态代理
的代理类是由程序员编写源码,编译后即可获取到代理类的class字节码文件,也就是在程序运行前
就已经得到实际的代理类class字节码文件了3.3.2 什么是动态代理?
动态代理
也属于代理模式
的一种代理方式,不过只需要目标对象
实现接口,代理对象
不需要实现接口~
(2)动态代理
的代理类编译后是没有class字节码文件的,而是在运行时利用Java反射机制
动态的生成代理类的class字节码文件~JDK原生动态代理
和cglib动态代理
,往下介绍~JDK API
的java.lang.reflect.Proxy
和java.lang.relfect.InnvocationHandler
这两个类来实现~java.lang.reflect.Proxy
代理类的newProxyInstance
方法,传递3个参数,分别是:目标对象的加载器
通过MyClass.getClass().getClassLoader
方式获取目标对象的实现接口类型
通过Object.getClass().getInterfaces()
方式获取InnvocationHandler事件处理器
通过new
实例化对象并重写invoke
方法方式获取IUserDao
public interface IUserDao {
//添加数据
public void insert();}
UserDao
/**
* @program: DataStructures
* @description:
* @author: JustinQin
* @create: 2021/8/23 23:32
* @version: v1.0.0
**/public class UserDao implements IUserDao{
@Override
public void insert() {
System.out.println("添加数据");
}}
UserProxy
/**
* @program: Jdk1.8Test
* @description: 动态代理类
* @author: JustinQin
* @create: 2021/8/23 23:31
* @version: v1.0.0
**/public class UserProxy {
private Object target; //目标对象
public UserProxy(Object target) {
this.target = target;
}
/**
* 利用JDK API获取到代理对象
* @return
*/
public Object getProxyInstance() {
//目标对象的加载器
ClassLoader loader = target.getClass().getClassLoader();
//目标对象的实现接口类型
Class>[] interfaces = target.getClass().getInterfaces();
//InnvocationHandler事件处理器实例对象
InvocationHandler h = new InvocationHandler() {
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("添加数据前:手动开启事务");
// 执行目标对象方法
Object value = method.invoke(target, args);
System.out.println("添加数据后:手动提交事务");
return null;
}
};
//传入3个参数,创建代理类的实例对象,并返回
return Proxy.newProxyInstance(loader, interfaces,h);
}}
/**
* @program: 动态代理单元测试类
* @description:
* @author: JustinQin
* @create: 2021/8/23 23:42
* @version: v1.0.0
**/public class UserProxyTest {
@Test
public void test() {
IUserDao target = new UserDao();
System.out.println("目标对象信息:" + target.getClass());
//获取代理类实例对象
IUserDao proxy = (IUserDao) new UserProxy(target).getProxyInstance();
System.out.println("代理对象信息:" + proxy.getClass());
//执行代理方法
proxy.insert();
}}
目标对象信息:class com.justin.java.reflect.UserDao代理对象信息:class com.sun.proxy.$Proxy2添加数据前:手动开启事务
添加数据
添加数据后:手动提交事务
cglib (Code Generation Library )
是一个第三方代码生成类库,运行时在内存中动态生成一个子类对象从而实现对目标对象功能的扩展。Spring AOP
结合了cglib动态代理
和JDK原生动态代理
来实现,这里不过多介绍,有兴趣小伙伴可以查阅资料学习下~3.3.3 动态代理中如何利用Java反射机制?
target.getClass().getClassLoader(
获取到目标对象的类加载器,target.getClass()
方式获取目标对象的Class实例对象使用的就是Java反射机制来实现的~3.4 Java JDBC数据库操作实现
3.4.1 利用反射加载JDBC驱动
Java JDBC连接数据库
主要分为七大步骤,其中第一步加载JDBC驱动
,利用Java反射机制通过传入不同的驱动名称,加载不同数据库的驱动~Class.forName("com.mysql.jdbc.Driver");
//加载MySQL驱动Class.forName("oracle.jdbc.driver.OracleDriver");
//加载Oracle驱动
3.4.2 Java JDBC连接示例
create DATABASE test;-- DROP TABLE IF EXISTS test.user;create table test.user(id int(7) primary key not null auto_increment,name varchar(255),sex char(1),age int(3))ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_general_ci;insert into TEST.user(name,sex,age) values('张一','男',21);insert into TEST.user(name,sex,age) values('张二','女',22);insert into TEST.user(name,sex,age) values('张三','男',23);
public static void main(String[] args) throws ClassNotFoundException, SQLException {
//1.加载JDBC驱动
Class.forName("com.mysql.jdbc.Driver");
//2.获取数据库的连接(Connection)对象
Connection connection = DriverManager.getConnection(
"jdbc:mysql://localhost/test", //mysql连接url,test表示你要连接的数据库名
"root", //数据库用户名
"abc@123456"); //密码
//3.获取数据库的操作(PrepareStatement)对象
PreparedStatement prepareStatement = connection.prepareStatement("select * from TEST.user where id = ?");
//4.设置传入参数
prepareStatement.setInt(1, 1);
//5.上传sql语句到服务器执行(excute),并返回结果集(ResultSet)
ResultSet result = prepareStatement.executeQuery();
//6.处理返回的ResultSet结果集
while (result.next()) {
System.out.print(result.getInt("id") + ",");
System.out.print(result.getString("name") + ",");
System.out.print(result.getString("sex") + ",");
System.out.print(result.getInt("age"));
System.out.print("\n");
}
//7.释放相关资源:Connection对象、PrepareStatement对象、ResultSet对象。
connection.close();
prepareStatement.close();
result.close();
}
1,张一,男,21
public class JdbcOracleTest {
public static void main(String[] args) throws ClassNotFoundException, SQLException {
//1.加载JDBC驱动
Class.forName("oracle.jdbc.driver.OracleDriver");
//2.获取数据库的连接(Connection)对象
Connection connection = DriverManager.getConnection(
"jdbc:oracle:thin:@127.0.0.1:1521:orcl", //oracle连接url
"root", //数据库用户名
"abc@123456"); //密码
//3.获取数据库的操作(PrepareStatement)对象
PreparedStatement prepareStatement = connection.prepareStatement("select * from TEST.user where id = ?");
//4.设置传入参数
prepareStatement.setInt(1, 1);
//5.上传sql语句到服务器执行(excute),并返回结果集(ResultSet)
ResultSet result = prepareStatement.executeQuery();
//6.处理返回的ResultSet结果集
while (result.next()) {
System.out.print(result.getInt("id")+",");
System.out.print(result.getString("name")+",");
System.out.print(result.getString("sex")+",");
System.out.print(result.getInt("age"));
System.out.print("\n");
}
//7.释放相关资源:Connection对象、PrepareStatement对象、ResultSet对象。
connection.close();
prepareStatement.close();
result.close();
}}
Java反射机制
指定不同的驱动名称,实现不同数据库驱动的加载~spring-mybatis.xml
<!-- 基于tomcat jdbc连接池的数据源 -->
<bean>
<!-- 基于dbcp连接池的数据源
<bean id="dataSource" class="com.justin.datasource.DbcpDataSource" destroy-method="close"> -->
<!-- 基于阿里druid连接池的数据源
<bean id="dataSource" class="com.justin.datasource.DruidDataSource" destroy-method="close"> -->
<property></property>
<property></property>
<property></property>
<property></property>
<!-- 初始化连接大小 -->
<property></property>
<!-- 连接池最大数量 -->
<property></property>
<!-- 连接池最大空闲 -->
<property></property>
<!-- 连接池最小空闲 -->
<property></property>
<!-- 获取连接最大等待时间 -->
<property></property>
</bean>
jdbc.propertis
#数据库连接驱动
app-data-source.driverClassName=com.mysql.jdbc.Driver#数据库连接url
app-data-source.url=jdbc:mysql://localhost:3306/test?useSSL=false&characterEncoding=UTF-8#数据库用户
app-data-source.username=root
#数据库用户密码(加密)app-data-source.password=abc@123456#连接池初始化大小
app-data-source.initialSize=10#连接池最大数量
app-data-source.maxActive=50#连接池最大空闲
app-data-source.maxIdle=20#连接池最小空闲
app-data-source.minIdle=5#获取连接最大等待时间
app-data-source.maxWait=30000
面试总结
Java Reflection
)是Java语言中一种动态(运行时)访问、检测 & 修改它本身
的能力,主要作用是动态(运行时)获取类的完整结构信息 & 调用对象的方法
~
更简单点的说就是Java程序在运行时(动态)通过创建一个类的反射对象,再对类进行相关操作,比如:
new
实例化创建对象,然后使用这个对象对类进行操作,这个就属于正射
~反射
则是一开始并不知道要初始化的是什么类,无法使用new
来实例化创建对象,主要是通过JDK提供的反射API来实现,在运行时才知道要操作的是什么类,并且可以获取到类的完整构造以及调用对应的方法,这就是反射
~java.lang.Class
objek contoh kelas Tiga cara biasa ialah:
2. Dapatkan melalui MyClass.class
Class.forName("类的全局定名")
new MyClass().getClass()
MyClass.class
pemuat kelas untuk memuatkan kelas ke dalam memori, tetapi ia tidak akan ClassLoader
tidak akan melakukan apa-apa kerja permulaan kelas , dan mengembalikan objek java.lang.Class
Class.forName("类的全局定名")
akan diproses Permulaan statik kelas berfungsi dan mengembalikan objek java.lang.Class
new MyClass().getClass()
untuk operasi instantiasi, jadi == pemula statik dan bukan statik Kerja akan dilakukan ==, kaedah new
tergolong dalam kaedah dalam kelas getClass
peringkat atas, dan boleh dipanggil oleh mana-mana objek subkelas yang dipanggil , objek Object
subkelas itu akan dikembalikan java.lang.Class
java.lang.Class
alamat memori adalah sama , dan hasil daripada perbandingan tanda sama berganda ialah ==
, sebab true
pemuat kelas yang sama digunakan semasa proses pemuatan kelas JVM untuk memuatkan kelas tertentu. Tidak kira berapa kali ia dimuatkan, akan sentiasa ada satu ClassLoader
objek yang dijana dalam kawasan timbunan, melainkan pemuat kelas tersuai memusnahkan JVM Mekanisme delegasi induk membenarkan JVM merawat kelas yang sama sebagai dua objek java.lang.Class
yang berbeza jika ia dimuatkan oleh pemuat kelas yang berbeza java.lang.Class
Pembelajaran yang disyorkan: "工厂模式
代理模式
Java JDBC
Atas ialah kandungan terperinci Analisis terperinci tentang prinsip mekanisme refleksi Java dan beberapa kaedah mendapatkan Kelas. Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!