【零基礎(chǔ) 快速學(xué)Java】韓順平 零基礎(chǔ)30天學(xué)會(huì)Java

## 1. Properties
### 1.1?Properties類(lèi)
#### 1.1.1 需求的引出
com.wjedu.properties_ Properties.01.java
如下一個(gè)配置文件 My_Sql.properties
```xml
ip=192.168.0.13
user=root
pwd=12345
```
編程讀取,ip user pwd的值,一般這個(gè)配置文件是給客戶(hù)使用的。
分析
1.傳統(tǒng)的方式
```java
BufferedReader bf =new BufferedReader(new FileReader("src\\My_Sql.properties"));
String line= ""
??while((line =?br.readLine())!=null){//循環(huán)讀取
???System.out.print(line);
???Sprint[] split = line.sprint("=")//傳統(tǒng)方式比較麻煩
???System.out.print(split[0]);??
????System.out.print(split[1]);??
????System.out.print(split[2]);??
??????
??}
```
2.Properties類(lèi)可以方便實(shí)現(xiàn)
#### 1.1.2 Properties類(lèi)基本介紹

1)專(zhuān)門(mén)用于讀寫(xiě)配置文件的集合類(lèi)
配置文件格式:鍵=值
2)注意:鍵值不能需要又空格,值不需要引號(hào)一起來(lái),默認(rèn)類(lèi)型是String
#### 1.1.3 Properties類(lèi)的常用方法
- load:加載配置文件的鍵值對(duì)到Properties對(duì)象
- list:將數(shù)據(jù)顯示到指定設(shè)備
- getProperties(key):根據(jù)鍵獲取值
- setProperties(key,value):設(shè)置簡(jiǎn)直對(duì)到properties對(duì)象
- store:講Properties中的簡(jiǎn)直對(duì)存儲(chǔ)到配置文件中,再idea中,保存信息到配置文件,如果含有中文,存儲(chǔ)為unicode碼。
```java
import java.io.IOException;
import java.util.Properties;
public class Properties01 {
??public static void main(String[] args) throws IOException {
????// 獲取Porperties對(duì)象
????Properties properties = new Properties();
????// 加載指定文件
????properties.load(new FileReader("src\\mysql.properties"));
????// 把k-v顯示控制到控制臺(tái)
????properties.list(System.out);
????// 取得對(duì)應(yīng)的鍵的值
????String user = (String) properties.get("user");
????String user1 = properties.getProperty("user");
????String pwd = (String) properties.get("pwd");
????System.out.println(user);
????System.out.println(user1);
????System.out.println(pwd);
??}
}
```
## 2.反射(reflection)
### 2.1 需求的引出
根據(jù)配置文件re.properties?指定信息,創(chuàng)建Cat對(duì)象,并調(diào)用hi()方法
```xml
classfullpath=com.wjedu.Cat
method=hi
```
```java
package com.wjedu.Reflection_;
import java.io.FileInputStream;
import java.io.IOException;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.Properties;
public class ReflectionQuestion {
??public static void main(String[] args) throws Exception {
????//傳統(tǒng)的方法我們創(chuàng)建Cat對(duì)象
//????Cat cat = new Cat("張三");
//????cat.hi();
//????如果我們調(diào)用類(lèi)創(chuàng)建對(duì)象,直接使用配置文件中的類(lèi)和方法信息來(lái)創(chuàng)建對(duì)象
????Properties properties = new Properties();
????properties.load(new FileInputStream("src\\re.properties"));
????String classfullname = properties.getProperty("classfullname");
????String method = properties.getProperty("method");
//????System.out.println(classfullname);
//????System.out.println(method);
????//2.創(chuàng)建對(duì)象,使用傳統(tǒng)方法行不通,
????//new classfullname
????//3. 使用反射機(jī)制解決(快速入門(mén))
????//(1)加載類(lèi) 返回一個(gè)Class類(lèi)型的對(duì)象,這個(gè)對(duì)象其實(shí)就是一個(gè)類(lèi)
????Class aClass = Class.forName(classfullname);
????//(2)通過(guò)aClass對(duì)象,得到你加載的類(lèi)的實(shí)例對(duì)象
????Object o = aClass.getDeclaredConstructor().newInstance();
????System.out.println(o.getClass());
????// (3)通過(guò)aClass對(duì)象得到加載類(lèi)的 method名字所代表的方法
????//把方法視為對(duì)象
????Method method1 = aClass.getMethod(method);
????//通過(guò)method1 來(lái)調(diào)用方法 即方法對(duì)象來(lái)調(diào)用方法
????method1.invoke(o);
??}
}
```
### 2.2反射機(jī)制
1. 反射機(jī)制允許程序再執(zhí)行期間借助于ReflectionAPI取得任何類(lèi)的內(nèi)部信息(如成員變量,構(gòu)造器,底層方法等等),并且操作對(duì)象的屬性及方法。反射在設(shè)計(jì)模式和框架底層都會(huì)用到
2. 加載完類(lèi)之后,在堆中就產(chǎn)生了一個(gè)Class對(duì)象類(lèi)型的對(duì)象(一個(gè)類(lèi)只有一個(gè)Class對(duì)象),這個(gè)對(duì)象包含了完整的結(jié)構(gòu)信息,通過(guò)這個(gè)對(duì)象得到類(lèi)的信息。這個(gè)對(duì)象就像一面鏡子,透過(guò)這個(gè)鏡子看到了類(lèi)的結(jié)構(gòu),所以稱(chēng)之為反射。?
#### 2.2.1?java反射機(jī)制原理圖

#### 2.2.2 java 反射機(jī)制可以完成
- 在運(yùn)行時(shí)判斷任意一個(gè)對(duì)象所屬的類(lèi)
- 在運(yùn)行時(shí)構(gòu)造任意一個(gè)類(lèi)的對(duì)象
- 在運(yùn)行時(shí)得到任意一個(gè)類(lèi)所具有的成員方法和變量
- 在運(yùn)行時(shí)調(diào)用任意一個(gè)對(duì)象的成員變量和方法
- 生成動(dòng)態(tài)代理
#### 2.2.3 反射相關(guān)的主要類(lèi)
- java.lang.Class 代表一個(gè)類(lèi),Class對(duì)象表示某個(gè)類(lèi)加載后在堆中的對(duì)象
- java.lang.reflect.Method 代表類(lèi)的方法
- java.lang.reflect.Field 代表類(lèi)的成員變量
- java.lang.reflect.Constructor 代表類(lèi)的構(gòu)造方法
```java
?// 獲取類(lèi)的成員變量
?// 不能獲取私有屬性
?Field nameField = aClass.getField("name");
?System.out.println(nameField.get(o));
?//用反射機(jī)制,Constructor 代表類(lèi)的構(gòu)造方法
?Constructor[] constructors1 = aClass.getConstructors();//?返回構(gòu)造器數(shù)組
?System.out.println(constructors1[0]);
?System.out.println(constructors1[1]);
?System.out.println(constructors1[2]);
//?Constructor[] constructors2 = aClass.getConstructors(String.class);
```
#### 2.2.4 反射優(yōu)缺點(diǎn)
優(yōu)點(diǎn):可以動(dòng)態(tài)創(chuàng)建對(duì)象和使用對(duì)象,使用靈活,沒(méi)有反射機(jī)制,框架技術(shù)就失去底層支撐
缺點(diǎn):使用反射基本是解釋執(zhí)行,對(duì)執(zhí)行速度有影響
```java
package com.wjedu.Reflection_;
import java.lang.reflect.Method;
public class Reflection_time {
??public static void main(String[] args) throws Exception {
????m2();
????m1();
????m3();
??}
??public static void m1() throws Exception {
????Class<?> aClass = Class.forName("com.wjedu.Reflection_.Cat");
????Object o = aClass.getDeclaredConstructor().newInstance();
????Method hi = aClass.getMethod("cry");
????long start = System.currentTimeMillis();
????for (int i = 0; i < 900000000; i++) {
??????hi.invoke(o);
????}
????long end = System.currentTimeMillis();
????long time = end - start;
????System.out.println("執(zhí)行時(shí)間是" + time);
??}
??public static void m2() {
????Cat cat = new Cat();
????long l = System.currentTimeMillis();
????for (int i = 0; i < 900000000; i++) {
??????cat.cry();
????}
????long l1 = System.currentTimeMillis();
????System.out.println(l1 - l);
??}
??//優(yōu)化反射
??public static void m3() throws Exception {
????Class<?> aClass = Class.forName("com.wjedu.Reflection_.Cat");
????Object o = aClass.getDeclaredConstructor().newInstance();
????Method hi = aClass.getMethod("cry");
????hi.setAccessible(true);//在反射調(diào)用方法時(shí),取消訪(fǎng)問(wèn)檢查
????long start = System.currentTimeMillis();
????for (int i = 0; i < 900000000; i++) {
??????hi.invoke(o);
????}
????long end = System.currentTimeMillis();
????long time = end - start;
????System.out.println("執(zhí)行時(shí)間是" + time);
??}
}
```
### 2.3 Class類(lèi)
#### 2.3.1?類(lèi)圖

#### 2.3.2 基本介紹
1. Class也是類(lèi),也是繼承Object類(lèi)
2. Class類(lèi)對(duì)象不是new出來(lái)的 而是系統(tǒng)創(chuàng)創(chuàng)建的(loadClass()方法加載 的)
3. 對(duì)于某個(gè)類(lèi)Class類(lèi)對(duì)象,在內(nèi)存中只有一份,因?yàn)轭?lèi)只加載一次
4. 每個(gè)類(lèi)的實(shí)例都會(huì)記得自己是有哪個(gè)Class實(shí)例所生成的
5. 通過(guò)Class可以完整的得到一個(gè)類(lèi)的完整結(jié)構(gòu),通過(guò)一些列的API操作

1. Class對(duì)象是存放在堆中的
2. 類(lèi)的字節(jié)碼二進(jìn)制數(shù)據(jù),是放在方法區(qū),有些地方成為類(lèi)的元素?fù)?jù)(包括方法代碼,方法名,訪(fǎng)問(wèn)權(quán)限等?www.zhihu.com/question/38496907)
#### 2.3.3 Class類(lèi)常用方法
```java
package com.wjedu.Reflection_;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
public class Class_ {
??public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException, NoSuchFieldException {
????//Class的方法
????// 1.獲取到Car類(lèi)對(duì)應(yīng)的Class對(duì)象
????Class<?> aClass = Class.forName("com.wjedu.Reflection_.Car");
????// 2.輸出aClass
????System.out.println(aClass);//顯示的是哪個(gè)類(lèi)的Class對(duì)象 class com.wjedu.Reflection_.Car
????Class<? extends Class> aClass1 = aClass.getClass(); // 返回Class對(duì)象
????System.out.println(aClass1);//輸出cls運(yùn)行類(lèi)型 class java.lang.Class
????//3 得到包名
????Package aPackage = aClass.getPackage();
????System.out.println(aPackage);
????System.out.println(aPackage.getName());
????//4 得到全類(lèi)名 返回字符串類(lèi)型
????String name = aClass.getName();
?????
????//5?創(chuàng)建對(duì)象實(shí)例
????Object o = aClass.getDeclaredConstructor().newInstance();
????Car car = (Car)o;
????System.out.println(car.toString());
????//通過(guò)反射獲取屬性
????Field color = aClass.getField("color");
????System.out.println(color.get(car));
????// 通過(guò)反射給屬性賦值
????color.set(car,"白色");
????System.out.println(car.toString());
????// 通過(guò)遍歷獲取所有屬性
????Field[] fields = aClass.getFields();
????//System.out.println(fields[0].get(car));
????for (Field f: fields) {
??????System.out.println(f.getName());
????}
??}
}
```
#### 2.3.4 獲取Class類(lèi)的對(duì)象6種方法

```java
package com.wjedu.Reflection_;
public class GetClass {
??public static void main(String[] args) throws ClassNotFoundException {
????//通過(guò)Class.forNname()來(lái)獲取
????String allfullPath = "com.wjedu.Reflection_.Car";//通過(guò)讀取配置文件
????Class<?> aClass1 = Class.forName(allfullPath);
????//通過(guò) 類(lèi)名.class,用于傳遞參數(shù)
????Class<Car> aClass2 = Car.class;
????//通過(guò)對(duì)象獲取 應(yīng)用場(chǎng)景,有實(shí)例對(duì)象
????Car car = new Car();
????Class<? extends Car> aClass3 = car.getClass();
????//通過(guò)類(lèi)加載器獲取到類(lèi)的對(duì)象
??????//1.先得到類(lèi)加載器
????ClassLoader classLoader = car.getClass().getClassLoader();
??????//2.通過(guò)類(lèi)加載器得到Class對(duì)象
????Class<?> aClass4 = classLoader.loadClass(allfullPath);
????System.out.println(aClass1.hashCode());
????System.out.println(aClass2.hashCode());
????System.out.println(aClass3.hashCode());
????System.out.println(aClass4.hashCode());
????//基本數(shù)據(jù)類(lèi)型 按照一下方法獲取Class對(duì)象
????Class<Integer> integerClass = int.class;
????Class<Character> characterClass = char.class;
????Class<Double> doubleClass = double.class;
????// 基本數(shù)據(jù)類(lèi)型對(duì)象包裝類(lèi),可以使用.TYPE得到Class類(lèi)對(duì)象
????Class<Integer> type = Integer.TYPE;
????Class<Character> type1 = Character.TYPE;
??}
}
```
#### 2.3.5 有哪些Class對(duì)象
如下類(lèi)型有Class對(duì)象?
- 外部類(lèi),成員內(nèi)部類(lèi),靜態(tài)內(nèi)部類(lèi),局部?jī)?nèi)部類(lèi),匿名內(nèi)部類(lèi)
- 接口 interface
- 數(shù)組?
- 枚舉 enum
- 注解 annotation
- 基本數(shù)據(jù)類(lèi)型
- void
###?2.4 類(lèi)加載
#### 2.4.1 基本說(shuō)明
反射機(jī)制是java實(shí)現(xiàn)動(dòng)態(tài)語(yǔ)言的關(guān)鍵,反射實(shí)現(xiàn)類(lèi)的動(dòng)態(tài)加載、
1. 靜態(tài)加載:編譯運(yùn)行時(shí)加載相關(guān)的類(lèi),如果沒(méi)有則報(bào)錯(cuò),依賴(lài)性強(qiáng)
2. 動(dòng)態(tài)加載:運(yùn)行時(shí)加載需要的類(lèi),如果運(yùn)行時(shí)不用該類(lèi),則不報(bào)錯(cuò),降低依賴(lài)
#### 2.4.2 類(lèi)的加載時(shí)機(jī)
1. 對(duì)象創(chuàng)建時(shí)(new)
2. 當(dāng)子類(lèi)被加載時(shí)
3. 調(diào)用類(lèi)中的靜態(tài)成員時(shí)
4. 通過(guò)反射
#### 2.4.3類(lèi)加載 過(guò)程


#####?1.加載階段
JVM在該階段主要是將字節(jié)碼從不同的數(shù)據(jù)源(可能是class文件,也可能是jar包,甚至網(wǎng)絡(luò))轉(zhuǎn)換為二進(jìn)制字節(jié)流加載到內(nèi)存中(方法區(qū)),并生成一個(gè)代表該類(lèi)的java.lang.Class對(duì)象
##### 2.連接階段-驗(yàn)證
1.目的是為了確保Class文件的字節(jié)流中包含的信息符合當(dāng)前虛擬機(jī)的要求,并且不會(huì)危害虛擬機(jī)的紫色安全
2.文件格式的驗(yàn)證、元數(shù)據(jù)驗(yàn)證、字節(jié)碼驗(yàn)證和符號(hào)引用驗(yàn)證
3.可以考慮使用 -Xverify:none?參數(shù)來(lái)關(guān)閉大部分的類(lèi)驗(yàn)證措施,縮短虛擬機(jī)類(lèi)加載的時(shí)間
##### 2.鏈接階段-準(zhǔn)備
JVM會(huì)在該階段堆靜態(tài)變量,分配內(nèi)存默認(rèn)初始化(對(duì)應(yīng)數(shù)據(jù)類(lèi)型的初始值,如0,null false等)。這些變量所使用的內(nèi)存都在方法區(qū)中進(jìn)行分配。
```java
//3種不同的成員變量在鏈接階段-準(zhǔn)備 屬性是如何處理的
public class A{
??public Int n1 = 10;// 實(shí)例屬性,準(zhǔn)備階段不分配內(nèi)存
??public static int n2 = 20; // 靜態(tài)屬性,準(zhǔn)備階段分配空間,默認(rèn)初始化0
??public static final int n3 = 30; //常量,一旦賦值,分配空間,賦值
}
```
##### 3.連接階段-解析
虛擬機(jī)將常量池內(nèi)的符號(hào)引用替換為直接引用的過(guò)程
##### 4.初始化 Initialization
1. 初始化階段,才是真正執(zhí)行類(lèi)中定義JAVA程序代碼,此階段是執(zhí)行<clinit>()方法過(guò)程
2. <clinit>()方法是由編譯器按語(yǔ)句在源文件中出現(xiàn)的順序,依次自動(dòng)收集類(lèi)中的所有靜態(tài)變量的賦值的動(dòng)作和靜態(tài)代碼塊中的語(yǔ)句,并進(jìn)行合并
3. 虛擬機(jī)會(huì)保證一個(gè)類(lèi)<clinit>()方法在多線(xiàn)程環(huán)境中被正確的加鎖、同步、如果多個(gè)線(xiàn)程同時(shí)去初始化一個(gè)類(lèi),那么只會(huì)有一個(gè)線(xiàn)程去執(zhí)行這個(gè)類(lèi)<clinit>()方法,其他線(xiàn)程都需要阻塞等待,知道活動(dòng)線(xiàn)程執(zhí)行<clinit>()方法完畢
#### 2.4.4 通過(guò)反射獲取類(lèi)的結(jié)構(gòu)信息
```JAVA
package com.wjedu.Reflection_;
import java.lang.annotation.Annotation;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
public class ReflectionUtils {
??public static void main(String[] args) throws ClassNotFoundException, InstantiationException, IllegalAccessException, NoSuchMethodException {
????String allfindPath = "com.wjedu.Reflection_.Car";
????Class<?> aClass = Class.forName(allfindPath);
????Object o = aClass.newInstance();
????//獲取類(lèi)的全名
????String name = aClass.getName();
????System.out.println(name);
????//獲取簡(jiǎn)單的類(lèi)名
????String simpleName = aClass.getSimpleName();
????System.out.println(simpleName);
????//獲取所有public修飾的屬性,包含本類(lèi)以及父類(lèi)的
????Field[] fields = aClass.getFields();
????for (Field fie :fields) {
??????System.out.println(fie.getName());
????}
????System.out.println("-----------------------");
????//獲取所有public修飾的方法,包含本類(lèi)和父類(lèi)的
????Method[] methods = aClass.getMethods();
????for (Method me : methods) {
??????// System.out.println(me.getName());
????}
????System.out.println("-----------------------");
????//獲取本類(lèi)中的所有方法
????Method[] declaredMethods = aClass.getDeclaredMethods();
????for (Method me : declaredMethods) {
??????System.out.println(me.getName());
????}
????// 獲取所有public修飾的構(gòu)造器 包含本類(lèi)以及父類(lèi)的
????Constructor<?>[] constructors = aClass.getConstructors();
????// 獲取所有public修飾的本類(lèi)構(gòu)造器
????Constructor<?> declaredConstructor = aClass.getDeclaredConstructor();
????//以package形式返回包信息
????Package aPackage = aClass.getPackage();
????System.out.println(aPackage.getName());
????//以Class形式返回父類(lèi)信息
????Class<?> superclass = aClass.getSuperclass();
????//返回接口信息,以Class[]
????Class<?>[] interfaces = aClass.getInterfaces();
????// 返回注解信息
????Annotation[] annotations = aClass.getAnnotations();
??}
}
```
### 2.5 通過(guò)反射爆破創(chuàng)建對(duì)象
```java
package com.wjedu.Reflection_;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
/*
* 通過(guò)反射機(jī)制創(chuàng)建實(shí)例對(duì)象
* */
public class ReflectionCreateInstance {
??public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException {
????//方式1 調(diào)用類(lèi)中的public修飾的無(wú)參構(gòu)造器
????// 獲取User類(lèi)的Class對(duì)象
????Class<?> aClass = Class.forName("com.wjedu.Reflection_.User");
????Object o = aClass.newInstance();// jdk8 創(chuàng)建實(shí)例對(duì)象
????System.out.println(o);
????Object obj = aClass.getDeclaredConstructor().newInstance();//jdk9以上
????System.out.println(obj);
????// 方式2 調(diào)用類(lèi)中的有參構(gòu)造器
????Constructor con1 = aClass.getDeclaredConstructor(String.class);
????Object obj2 = con1.newInstance("王五");
????System.out.println(obj2);
????//方式3 調(diào)用類(lèi)中的私有的有參構(gòu)造器
????Constructor<?> con3 = aClass.getDeclaredConstructor(int.class,String.class);
????con3.setAccessible(true);
????Object obj3 = con3.newInstance(36, "張三豐");//IllegalAccessException 需要爆破私有方法
????System.out.println(obj3);
??}
}
class User{
??public int age?= 10;
??public String name = "小張無(wú)忌";
??public User() {
??}
??public User(String name){
????this.name = name;
??}
??private?User(int age,String name){
????this.name = name;
????this.age?= age;
??}
??@Override
??public String toString() {
????return "User{" +
????????"age=" + age +
????????", name='" + name + '\'' +
????????'}';
??}
}
```
### 2.6 通過(guò)反射訪(fǎng)問(wèn)類(lèi)中的成員
```java
package com.wjedu.Reflection_;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
/*
* 通過(guò)反射機(jī)制訪(fǎng)問(wèn)成員變量
* */
public class ReflectionAccessProperty {
??public static void main(String[] args) throws Exception{
????//創(chuàng)建Studeng類(lèi)的對(duì)象
????Class<?> aClass = Class.forName("com.wjedu.Reflection_.Student");
????Constructor<?> con1?= aClass.getConstructor();
????Object o = con1.newInstance();
????//操作public成員對(duì)象
????Field age = aClass.getField("age");
????age.set(o,18);// 設(shè)置對(duì)象
????System.out.println(o);
????System.out.println(age.get(o));//獲取對(duì)象
????//操作private成員對(duì)象
????Field name = aClass.getDeclaredField("name");
????name.setAccessible(true);
????name.set(o,"王五");
????name.set(null,"jack");//?靜態(tài)成員可以寫(xiě)空
????System.out.println(name.get(o));
??}
}
class Student{
??public int age;
??private static String name;
??public Student() {
??}
??@Override
??public String toString() {
????return "Student{" +
????????"age=" + age +
????????'}';
??}
}
```
### 2.7 通過(guò)反射訪(fǎng)問(wèn)方法
```java
package com.wjedu.Reflection_;
import java.lang.reflect.Constructor;
import java.lang.reflect.Method;
public class ReflectionAccessMethod {
??public static void main(String[] args) throws Exception {
????//創(chuàng)建Boss類(lèi)的實(shí)例對(duì)象
????Class<?> aClass = Class.forName("com.wjedu.Reflection_.Boss");
????// 創(chuàng)建對(duì)象
????Constructor<?> con1 = aClass.getDeclaredConstructor();
????Object o = con1.newInstance();
????//根據(jù)方法名和參數(shù)列表獲取method對(duì)象方法
????Method method = aClass.getMethod("hi",String.class);
????Object jack = method.invoke(o, "jack");
????//爆破訪(fǎng)問(wèn)私有方法
????Method say = aClass.getDeclaredMethod("say", int.class, String.class, char.class);
????say.setAccessible(true);
????Object invoke = say.invoke(o, 15, "tom", '男');//私有方法不爆破 IllegalAccessException
????System.out.println(invoke);
??}
}
class Boss {
??public int age;
??private static String name;
??public Boss() {
??}
??private static String say(int n, String s, char c) {
????return n + " " + s + " " + c;
??}
??public void hi(String s) {
????System.out.println("hi " + s);
??}
}
```