引出
1.類什么時(shí)候被加載到JVM中,new,Class.forName: Class.forName(“包名.類名”);
2.創(chuàng)建對(duì)象的方式,反射,本質(zhì)是獲得類的類對(duì)象Class;
3.克隆clone,深拷貝,淺拷貝的對(duì)比;
4.序列化和反序列化的方式;
類什么時(shí)候被加載JVM中
Hello h; // 此時(shí)沒(méi)有用Hello,jvm并沒(méi)有進(jìn)行類加載
- 看到new : new Book()
- Class.forName: Class.forName(“包名.類名”)
- 類加載器
package com.tianju.auth.reflect;
public class HelloTest1 {
public static void main(String[] args) throws ClassNotFoundException {
Hello h; // 此時(shí)沒(méi)有用Hello,jvm并沒(méi)有進(jìn)行類加載
System.out.println("**********");
new Hello(); // new 的時(shí)候會(huì)加載到內(nèi)存中
System.out.println("**********");
Class.forName("com.tianju.auth.reflect.Hello");
}
}
package com.tianju.auth.reflect;
public class Hello {
static {
System.out.println("hello");
}
public Integer count(Integer a,Integer b){
return a+b;
}
public static void main(String[] args) throws ClassNotFoundException, InstantiationException, IllegalAccessException {
int a = 3;
Class<?> aClass = Hello.class; // ?泛型的寫法
Class<?> aClass1 = Class.forName("com.tianju.auth.reflect.Hello");
Class<? extends Hello> aClass2 = new Hello().getClass();
System.out.println(aClass);
System.out.println(aClass1);
System.out.println(aClass2);
Hello o = (Hello) aClass.newInstance();
int count = o.count(1, 2);
System.out.println(count);
}
}
創(chuàng)建對(duì)象幾種方式
1.new 看到new : new Book()
2.反射 Class.forName(“包名.類名”)
一個(gè)類會(huì)產(chǎn)生一個(gè)唯一的Class對(duì)象,JVM底層原理
Car.java 編譯成 Car.clase 類加載到 JVM 中,加載時(shí)還沒(méi)有創(chuàng)建對(duì)象;
進(jìn)入JVM中給類Car創(chuàng)建單獨(dú)的唯一的對(duì)象Class 類,該Class對(duì)象中存儲(chǔ)了Car類的一些必要信息,沒(méi)有記錄相關(guān)的值;
以Class對(duì)象生產(chǎn)成多個(gè)Car對(duì)象,通過(guò)Class類映射出多個(gè)Car對(duì)象
如何獲取Class對(duì)象【反射的基礎(chǔ)】
- 對(duì)象.getClass()
- 類.class
- Class.forName(“包名.類名”)
案例:連接數(shù)據(jù)庫(kù)方法
類加載采用了反射的方式
采用枚舉方式封裝JDBC單例
方法程序:
package com.tianju.util;
import java.sql.*;
import java.util.Objects;
/**
* 采用枚舉單例封裝數(shù)據(jù)庫(kù)
*/
public enum DbUtilEnum {
INSTANCE;
private Connection conn;
private PreparedStatement pst;
private ResultSet rs;
private DbUtilEnum() {
// 注冊(cè)驅(qū)動(dòng)-類加載
register();
}
/**
* 第一步:注冊(cè)驅(qū)動(dòng),類加載
*/
private void register(){
try {
Class.forName("com.mysql.cj.jdbc.Driver");
} catch (ClassNotFoundException e) {
throw new RuntimeException(e);
}
}
// 建立數(shù)據(jù)庫(kù)連接
// 192.168.0.134:3306
// root,123
/**
* 第二步:建立數(shù)據(jù)庫(kù)連接
* @param ipAdress ip地址+端口號(hào)
* @param user 用戶名root
* @param password 密碼123
*/
public void connect(String ipAdress,String user,String password){
String url = "jdbc:mysql://"+ipAdress+"/emp_db?useSSL=false&serverTimezone=Asia/Shanghai&allowPublicKeyRetrieval=true";
try {
conn = DriverManager.getConnection(url,user,password);
System.out.println("成功連接數(shù)據(jù)庫(kù):"+ipAdress);
} catch (SQLException e) {
throw new RuntimeException(e);
}
}
/**
* 第三步:準(zhǔn)備SQL語(yǔ)句,
* @param sql sql語(yǔ)句
*/
public void setPreparedStatement(String sql, Object...values){
try {
pst = conn.prepareStatement(sql);
// 逐個(gè)填充 ? 處的空缺
for (int i=0;i<values.length;i++){
pst.setObject(i+1, values[i]);
}
} catch (SQLException e) {
throw new RuntimeException(e);
}
}
/**
* 第四步:增加,刪除,修改
*/
public void executeUpdate(){
try {
pst.executeUpdate();
System.out.println("執(zhí)行增刪改操作");
} catch (SQLException e) {
throw new RuntimeException(e);
}
}
/**
* 第四步:查詢ResultSet,調(diào)用next()方法
* @return 返回查詢的ResultSet
*/
public ResultSet executeQuery(){
try {
rs = pst.executeQuery();
System.out.println("執(zhí)行查詢操作,返回結(jié)果");
return rs;
} catch (SQLException e) {
throw new RuntimeException(e);
}
}
/**
* 第五步:關(guān)閉連接
*/
public void close(){
try {
if (Objects.nonNull(rs)){
rs.close();
}
if (Objects.nonNull(pst)){
pst.close();
}
if (Objects.nonNull(conn)){
conn.close();
}
System.out.println("操作完成,關(guān)閉數(shù)據(jù)庫(kù)連接");
} catch (SQLException e) {
throw new RuntimeException(e);
}
}
}
3.克?。截悾ヽlone
- 繼承的時(shí)候,可以將子類的訪問(wèn)控制符擴(kuò)大,但不能縮?。蛔宇惒坏帽雀割悞伋龈?,更大的異常。
- 淺拷貝、深拷貝問(wèn)題:
淺拷貝
// protected:代表本包或者繼承
// 繼承的時(shí)候,可以將子類的訪問(wèn)控制符擴(kuò)大,但不能縮??;
// 子類不能比父類拋出更多的異常
@Override
public Object clone() throws CloneNotSupportedException {
return super.clone();
}
深拷貝
public Book deepClone(){
Book book = new Book();
Author au = new Author();
au.setName(author.getName());
book.setAuthor(au);
book.setTitle(this.title);
book.setPrice(this.price);
return book;
}
案例
Author.java實(shí)體類
package com.tianju.auth.reflect;
import lombok.Data;
@Data
public class Author {
private String name;
}
Book.java實(shí)體類
implements Cloneable{ // 可以克隆的
package com.tianju.auth.reflect;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
@Data
@NoArgsConstructor
@AllArgsConstructor
public class Book implements Cloneable{ // 可以克隆的
private String title;
private Author author;
public double price;
static {
System.out.println("book的靜態(tài)代碼塊");
}
// protected:代表本包或者繼承
// 繼承的時(shí)候,可以將子類的訪問(wèn)控制符擴(kuò)大,但不能縮?。?/span>
// 子類不能比父類拋出更多的異常
@Override
public Object clone() throws CloneNotSupportedException {
return super.clone();
}
public Book deepClone(){
Book book = new Book();
Author au = new Author();
au.setName(author.getName());
book.setAuthor(au);
book.setTitle(this.title);
book.setPrice(this.price);
return book;
}
}
進(jìn)行測(cè)試
package com.tianju.auth.reflect;
public class TestDemo{
public static void main(String[] args) throws CloneNotSupportedException {
Author author = new Author();
author.setName("吳承恩");
Book book = new Book("三國(guó)演義", author,12.56);
Book book1 = book;
System.out.println(book1==book);// == 兩個(gè)引用是否指向同一個(gè)對(duì)象
// clone創(chuàng)建了一個(gè)新的對(duì)象,只是值一樣
Book bookClone = (Book) book.clone();
// 深拷貝,創(chuàng)建了新的對(duì)象,上面的淺拷貝,只是拷貝了引用
Book deepClone = book.deepClone();
System.out.println(bookClone==book);
System.out.println("克隆前:"+book);
System.out.println("克隆后:"+bookClone);
author.setName("小柯基");
System.out.println("修改后的原對(duì)象:"+book);
System.out.println("修改后的clone對(duì)象:"+bookClone);
// 深拷貝
System.out.println("***********");
System.out.println("深拷貝的方法:"+deepClone);
}
}
序列化和反序列化
對(duì)象流-把對(duì)象存儲(chǔ)為dat文件
要點(diǎn):
(1)實(shí)體類需要實(shí)現(xiàn)序列化接口 public class Car implements Serializable;【標(biāo)記接口】
(2)序列化的版本號(hào)最好不要寫,交給JVM實(shí)現(xiàn),要保證版本號(hào)一致;
功能:
ObjectOutputStream—->對(duì)象寫入文件
serialVersionUID :在序列化的時(shí)候指定的編號(hào), 在反序列化時(shí)應(yīng)該保證版本號(hào)一致。
案例:把car類存儲(chǔ)到dat文件中
1)類需要實(shí)現(xiàn)序列化的接口
public class Car implements Serializable { // 需要實(shí)現(xiàn)序列化的接口
// 序列化的版本號(hào),不要寫,交給jvm實(shí)現(xiàn);保證讀的和寫的對(duì)象實(shí)體類要一樣
// private static final long serialVersionUID = 2L;
private Integer id;
private String name;
public Car() {
}
}
2)從內(nèi)存寫入硬盤文件,為out,用write
ObjectOutputStream out =
new ObjectOutputStream(
new FileOutputStream("D:\\Myprogram\\idea-workspace\\IOStrem\\IOStrem\\src\\com\\woniuxy\\resources\\car.dat")
);
// 存多個(gè)的解決方法,存到List中
List<Car> list = new ArrayList<>();
list.add(new Car(1, "BMW"));
list.add(new Car(2, "BYD"));
list.add(new Car(3, "BMW"));
out.writeObject(list); // list也實(shí)現(xiàn)了Serializable
out.flush();
out.close();
3)從硬盤讀入內(nèi)存,為in,用read文章來(lái)源:http://www.zghlxwxcb.cn/news/detail-657112.html
ObjectInputStream in =
new ObjectInputStream(
new FileInputStream("D:\\Myprogram\\idea-workspace\\IOStrem\\IOStrem\\src\\com\\woniuxy\\resources\\car.dat")
);
// Car car = (Car) in.readObject(); // 讀對(duì)象,向下轉(zhuǎn)型
// System.out.println(car);
List<Car> list = (List<Car>) in.readObject();
System.out.println(list);
list.forEach(car -> System.out.println(car)); // list的lamda表達(dá)式
list.forEach(System.out::println); // 上面的簡(jiǎn)化寫法
in.close(); // 記得關(guān)閉
總結(jié)
1.類什么時(shí)候被加載到JVM中,new,Class.forName: Class.forName(“包名.類名”);
2.創(chuàng)建對(duì)象的方式,反射,本質(zhì)是獲得類的類對(duì)象Class;
3.克隆clone,深拷貝,淺拷貝的對(duì)比;
4.序列化和反序列化的方式;文章來(lái)源地址http://www.zghlxwxcb.cn/news/detail-657112.html
到了這里,關(guān)于Java進(jìn)階(4)——結(jié)合類加載JVM的過(guò)程理解創(chuàng)建對(duì)象的幾種方式:new,反射Class,克隆clone(拷貝),序列化反序列化的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!