Java基礎——Java反射機制及IoC原理

一、概念


?? ? ? 主要是指程序可以訪問,檢測和修改它本身狀態或行為的一種能力,并能根據自身行為的狀態和結果,調整或修改應用所描述行為的狀態和相關的語義。在java中,只要給定類的名字, 那么就可以通過反射機制來獲得類的所有信息。

? ? ? ?反射是Java中一種強大的工具,能夠使我們很方便的創建靈活的代碼,這些代碼可以再運行時裝配,無需在組件之間進行源代碼鏈接。但是反射使用不當會成本很高!

? ? ? ?類中有什么信息,利用反射機制就能可以獲得什么信息,不過前提是得知道類的名字。


二、作用


? ? 1)在運行時判斷任意一個對象所屬的類;

? ? 2)在運行時獲取類的對象;

? ? 3)在運行時訪問java對象的屬性,方法,構造方法等。


三、優點與缺點


? ? ? ?首先要搞清楚為什么要用反射機制?直接創建對象不就可以了嗎,這就涉及到了動態與靜態的概念。?

? ? ? ?靜態編譯:在編譯時確定類型,綁定對象,即通過。?

? ? ? ?動態編譯:運行時確定類型,綁定對象。動態編譯最大限度發揮了java的靈活性,體現了多態的應用,有以降低類之間的藕合性。

? ? ? ?反射機制的優點:可以實現動態創建對象和編譯,體現出很大的靈活性(特別是在J2EE的開發中它的靈活性就表現的十分明顯)。通過反射機制我們可以獲得類的各種內容,進行了反編譯。對于JAVA這種先編譯再運行的語言來說,反射機制可以使代碼更加靈活,更加容易實現面向對象。

? ? ? ?比如,一個大型的軟件,不可能一次就把把它設計的很完美,當這個程序編譯后,發布了,當發現需要更新某些功能時,我們不可能要用戶把以前的卸載,再重新安裝新的版本,假如這樣的話,這個軟件肯定是沒有多少人用的。采用靜態的話,需要把整個程序重新編譯一次才可以實現功能的更新,而采用反射機制的話,它就可以不用卸載,只需要在運行時才動態的創建和編譯,就可以實現該功能。?

? ? ? ?反射機制的缺點:對性能有影響。使用反射基本上是一種解釋操作,我們可以告訴JVM,我們希望做什么并且它 滿足我們的要求。這類操作總是慢于只直接執行相同的操作。


四、示例


1、通過一個對象獲取完整的包名和類名

注:所有類的對象其實都是Class類的實例

package Reflect;class Demo{//other codes...
}class hello{public static void main(String[] args) {Demo demo=new Demo();System.out.println(demo.getClass().getName());}
}
運行結果:

Reflect.Demo
2、實例化Class類對象
package Reflect;class Demo{//other codes...
}class hello{public static void main(String[] args) {Class<?> demo1=null;Class<?> demo2=null;Class<?> demo3=null;try{//一般盡量采用這種形式demo1=Class.forName("Reflect.Demo");}catch(Exception e){e.printStackTrace();}demo2=new Demo().getClass();demo3=Demo.class;System.out.println("類名稱   "+demo1.getName());System.out.println("類名稱   "+demo2.getName());System.out.println("類名稱   "+demo3.getName());}
}
運行結果:

類名稱   Reflect.Demo
類名稱   Reflect.Demo
類名稱   Reflect.Demo
3、通過Class實例化其他類的對象

package Reflect;class Person{public String getName() {return name;}public void setName(String name) {this.name = name;}public int getAge() {return age;}public void setAge(int age) {this.age = age;}@Overridepublic String toString(){return "["+this.name+"  "+this.age+"]";}private String name;private int age;
}class hello{public static void main(String[] args) {Class<?> demo=null;try{demo=Class.forName("Reflect.Person");}catch (Exception e) {e.printStackTrace();}Person per=null;try {per=(Person)demo.newInstance();} catch (InstantiationException e) {// TODO Auto-generated catch blocke.printStackTrace();} catch (IllegalAccessException e) {// TODO Auto-generated catch blocke.printStackTrace();}per.setName("Rollen");per.setAge(20);System.out.println(per);}
}
運行結果:

[Rollen  20]

? ? ? ?但是注意一下,當我們把Person中的默認的無參構造函數取消的時候,比如自己定義只定義一個有參數的構造函數之后,會出現錯誤:

比如定義了一個構造函數:

public Person(String name, int age) {               this.age=age;this.name=name;
}
然后繼續運行上面的程序,會出現:
java.lang.InstantiationException: Reflect.Person
at java.lang.Class.newInstance0(Class.java:340)
at java.lang.Class.newInstance(Class.java:308)
at Reflect.hello.main(hello.java:39)
Exception in thread "main" java.lang.NullPointerException
at Reflect.hello.main(hello.java:47)
? ? ? ?所以大家以后再編寫使用Class實例化其他類的對象的時候,一定要自己定義無參的構造函數。

4、通過Class調用其他類中的構造函數 (也可以通過這種方式通過Class創建其他類的對象)

package Reflect;import java.lang.reflect.Constructor;class Person{public Person() {   }public Person(String name){this.name=name;}public Person(int age){this.age=age;}public Person(String name, int age) {this.age=age;this.name=name;}public String getName() {return name;}public int getAge() {return age;}@Overridepublic String toString(){return "["+this.name+"  "+this.age+"]";}private String name;private int age;
}class hello{public static void main(String[] args) {Class<?> demo=null;try{demo=Class.forName("Reflect.Person");}catch (Exception e) {e.printStackTrace();}Person per1=null;Person per2=null;Person per3=null;Person per4=null;//取得全部的構造函數Constructor<?> cons[]=demo.getConstructors();try{per1=(Person)cons[0].newInstance();per2=(Person)cons[1].newInstance("Rollen");per3=(Person)cons[2].newInstance(20);per4=(Person)cons[3].newInstance("Rollen",20);}catch(Exception e){e.printStackTrace();}System.out.println(per1);System.out.println(per2);System.out.println(per3);System.out.println(per4);}
}
運行結果:

[null  0]
[Rollen  0]
[null  20]
[Rollen  20]
5、返回一個類實現的接口
package Reflect;interface China{public static final String name="Rollen";public static  int age=20;public void sayChina();public void sayHello(String name, int age);
}class Person implements China{public Person() {}public Person(String sex){this.sex=sex;}public String getSex() {return sex;}public void setSex(String sex) {this.sex = sex;}@Overridepublic void sayChina(){System.out.println("hello ,china");}@Overridepublic void sayHello(String name, int age){System.out.println(name+"  "+age);}private String sex;
}class hello{public static void main(String[] args) {Class<?> demo=null;try{demo=Class.forName("Reflect.Person");}catch (Exception e) {e.printStackTrace();}//保存所有的接口Class<?> intes[]=demo.getInterfaces();for (int i = 0; i < intes.length; i++) {System.out.println("實現的接口   "+intes[i].getName());}}
}
運行結果:

實現的接口   Reflect.China
(以下幾個例子,都會用到這個例子的Person類,所以為節省篇幅,此處不再粘貼Person的代碼部分,只粘貼主類hello的代碼)
6、取得其他類中的父類
class hello{public static void main(String[] args) {Class<?> demo=null;try{demo=Class.forName("Reflect.Person");}catch (Exception e) {e.printStackTrace();}//取得父類Class<?> temp=demo.getSuperclass();System.out.println("繼承的父類為:   "+temp.getName());}
}
運行結果:

繼承的父類為:   java.lang.Object
7、獲得其他類中的全部構造函數
//這個例子需要在程序開頭添加import java.lang.reflect.*;
class hello{public static void main(String[] args) {Class<?> demo=null;try{demo=Class.forName("Reflect.Person");}catch (Exception e) {e.printStackTrace();}Constructor<?>cons[]=demo.getConstructors();for (int i = 0; i < cons.length; i++) {System.out.println("構造方法:  "+cons[i]);}}
}
運行結果:

構造方法:  public Reflect.Person()
構造方法:  public Reflect.Person(java.lang.String)
class hello{public static void main(String[] args) {Class<?> demo=null;try{demo=Class.forName("Reflect.Person");}catch (Exception e) {e.printStackTrace();}Constructor<?>cons[]=demo.getConstructors();for (int i = 0; i < cons.length; i++) {Class<?> p[]=cons[i].getParameterTypes();System.out.print("構造方法:  ");int mo=cons[i].getModifiers();System.out.print(Modifier.toString(mo)+" ");System.out.print(cons[i].getName());System.out.print("(");for(int j=0;j<p.length;++j){System.out.print(p[j].getName()+" arg"+i);if(j<p.length-1){System.out.print(",");}}System.out.println("){}");}}
}
運行結果:
構造方法:  public Reflect.Person(){}
構造方法:  public Reflect.Person(java.lang.String arg1){}

8、取得其他類的全部屬性,將這些整理在一起,也就是通過class取得一個類的全部框架

class hello {public static void main(String[] args) {Class<?> demo = null;try {demo = Class.forName("Reflect.Person");} catch (Exception e) {e.printStackTrace();}System.out.println("===============本類屬性========================");// 取得本類的全部屬性Field[] field = demo.getDeclaredFields();for (int i = 0; i < field.length; i++) {// 權限修飾符int mo = field[i].getModifiers();String priv = Modifier.toString(mo);// 屬性類型Class<?> type = field[i].getType();System.out.println(priv + " " + type.getName() + " "+ field[i].getName() + ";");}System.out.println("===============實現的接口或者父類的屬性========================");// 取得實現的接口或者父類的屬性Field[] filed1 = demo.getFields();for (int j = 0; j < filed1.length; j++) {// 權限修飾符int mo = filed1[j].getModifiers();String priv = Modifier.toString(mo);// 屬性類型Class<?> type = filed1[j].getType();System.out.println(priv + " " + type.getName() + " "+ filed1[j].getName() + ";");}}
}
運行結果:

===============本類屬性========================
private java.lang.String sex;
===============實現的接口或者父類的屬性========================
public static final java.lang.String name;
public static final int age;
9、通過反射調用其他類中的方法
class hello {public static void main(String[] args) {Class<?> demo = null;try {demo = Class.forName("Reflect.Person");} catch (Exception e) {e.printStackTrace();}try{//調用Person類中的sayChina方法Method method=demo.getMethod("sayChina");method.invoke(demo.newInstance());//調用Person的sayHello方法method=demo.getMethod("sayHello", String.class,int.class);method.invoke(demo.newInstance(),"Rollen",20);}catch (Exception e) {e.printStackTrace();}}
}
運行結果:

hello ,china
Rollen  20

10、調用其他類的set和get方法

class hello {public static void main(String[] args) {Class<?> demo = null;Object obj=null;try {demo = Class.forName("Reflect.Person");} catch (Exception e) {e.printStackTrace();}try{obj=demo.newInstance();}catch (Exception e) {e.printStackTrace();}setter(obj,"Sex","男",String.class);getter(obj,"Sex");}/*** @param obj   操作的對象* @param att   操作的屬性* */public static void getter(Object obj, String att) {try {Method method = obj.getClass().getMethod("get" + att);System.out.println(method.invoke(obj));} catch (Exception e) {e.printStackTrace();}}/*** @param obj   操作的對象    * @param att   操作的屬性* @param value 設置的值* @param type  參數的屬性* */public static void setter(Object obj, String att, Object value,Class<?> type) {try {Method method = obj.getClass().getMethod("set" + att, type);method.invoke(obj, value);} catch (Exception e) {e.printStackTrace();}}
}// end class
運行結果:

11、通過反射操作屬性
class hello {public static void main(String[] args) throws Exception {Class<?> demo = null;Object obj = null;demo = Class.forName("Reflect.Person");obj = demo.newInstance();Field field = demo.getDeclaredField("sex");field.setAccessible(true);field.set(obj, "男");System.out.println(field.get(obj));}
}// end class
12、通過反射取得并修改數組的信息
import java.lang.reflect.*;class hello{public static void main(String[] args) {int[] temp={1,2,3,4,5};Class<?>demo=temp.getClass().getComponentType();System.out.println("數組類型: "+demo.getName());System.out.println("數組長度  "+Array.getLength(temp));System.out.println("數組的第一個元素: "+Array.get(temp, 0));Array.set(temp, 0, 100);System.out.println("修改之后數組第一個元素為: "+Array.get(temp, 0));}
}
運行結果:

數組類型: int
數組長度  5
數組的第一個元素: 1
修改之后數組第一個元素為: 100
13、通過反射修改數組大小
class hello{public static void main(String[] args) {int[] temp={1,2,3,4,5,6,7,8,9};int[] newTemp=(int[])arrayInc(temp,15);print(newTemp);System.out.println("=====================");String[] atr={"a","b","c"};String[] str1=(String[])arrayInc(atr,8);print(str1);}/*** 修改數組大小* */public static Object arrayInc(Object obj,int len){Class<?>arr=obj.getClass().getComponentType();Object newArr=Array.newInstance(arr, len);int co=Array.getLength(obj);System.arraycopy(obj, 0, newArr, 0, co);return newArr;}/*** 打印* */public static void print(Object obj){Class<?>c=obj.getClass();if(!c.isArray()){return;}System.out.println("數組長度為: "+Array.getLength(obj));for (int i = 0; i < Array.getLength(obj); i++) {System.out.print(Array.get(obj, i)+" ");}}
}
運行結果:

數組長度為: 15
1 2 3 4 5 6 7 8 9 0 0 0 0 0 0 =====================
數組長度為: 8
a b c null null null null null
14、動態代理
首先來看看如何獲得類加載器:
class test{}
class hello{public static void main(String[] args) {test t=new test();System.out.println("類加載器  "+t.getClass().getClassLoader().getClass().getName());}
}
運行結果:

類加載器  sun.misc.Launcher$AppClassLoader

其實在java中有三種類類加載器:

? ? 1)Bootstrap ClassLoader 此加載器采用c++編寫,一般開發中很少見。

? ? 2)Extension ClassLoader 用來進行擴展類的加載,一般對應的是jre\lib\ext目錄中的類

? ? 3)AppClassLoader 加載classpath指定的類,是最常用的加載器。同時也是java中默認的加載器。

如果想要完成動態代理,首先需要定義一個InvocationHandler接口的子類,已完成代理的具體操作。

package Reflect;import java.lang.reflect.*;//定義項目接口
interface Subject {public String say(String name, int age);
}// 定義真實項目
class RealSubject implements Subject {@Overridepublic String say(String name, int age) {return name + "  " + age;}
}class MyInvocationHandler implements InvocationHandler {private Object obj = null;public Object bind(Object obj) {this.obj = obj;return Proxy.newProxyInstance(obj.getClass().getClassLoader(), obj.getClass().getInterfaces(), this);}@Overridepublic Object invoke(Object proxy, Method method, Object[] args)throws Throwable {Object temp = method.invoke(this.obj, args);return temp;}
}class hello {public static void main(String[] args) {MyInvocationHandler demo = new MyInvocationHandler();Subject sub = (Subject) demo.bind(new RealSubject());String info = sub.say("Rollen", 20);System.out.println(info);}
}
運行結果:

Rollen  20

類的生命周期

? ? ? ?在一個類編譯完成之后,下一步就需要開始使用類,如果要使用一個類,肯定離不開JVM。在程序執行中JVM通過裝載、鏈接、初始化這3個步驟完成。

? ? ? ?類的裝載是通過類加載器完成的,加載器將.class文件的二進制文件裝入JVM的方法區,并且在堆區創建描述這個類的java.lang.Class對象。用來封裝數據。 但是同一個類只會被類裝載器裝載一次。

鏈接就是把二進制數據組裝為可以運行的狀態。

鏈接分為校驗,準備,解析這3個階段:

? ? 校驗:一般用來確認此二進制文件是否適合當前的JVM(版本),

? ? 準備:就是為靜態成員分配內存空間,。并設置默認值

? ? 解析:指的是轉換常量池中的代碼作為直接引用的過程,直到所有的符號引用都可以被運行程序使用(建立完整的對應關系)。

? ? ? ?完成之后,類型也就完成了初始化,初始化之后類的對象就可以正常使用了,直到一個對象不再使用之后,將被垃圾回收。釋放空間。當沒有任何引用指向Class對象時就會被卸載,結束類的生命周期。


五、IoC原理

Spring中的IoC的實現原理就是工廠模式加反射機制。


1、我們首先看一下不用反射機制時的工廠模式

/*** 工廠模式*/
interface fruit{public abstract void eat();
}class Apple implements fruit{public void eat(){System.out.println("Apple");}
}class Orange implements fruit{public void eat(){System.out.println("Orange");}
}
// 構造工廠類
// 也就是說以后如果我們在添加其他的實例的時候只需要修改工廠類就行了
class Factory{public static fruit getInstance(String fruitName){fruit f=null;if("Apple".equals(fruitName)){f=new Apple();}if("Orange".equals(fruitName)){f=new Orange();}return f;}
}class hello{public static void main(String[] a){fruit f=Factory.getInstance("Orange");f.eat();}
}
當我們在添加一個子類的時候,就需要修改工廠類了。如果我們添加太多的子類的時候,改的就會很多。
2、利用反射機制的工廠模式
package Reflect;interface fruit{public abstract void eat();
}class Apple implements fruit{public void eat(){System.out.println("Apple");}
}class Orange implements fruit{public void eat(){System.out.println("Orange");}
}class Factory{public static fruit getInstance(String ClassName){fruit f=null;try{f=(fruit)Class.forName(ClassName).newInstance();}catch (Exception e) {e.printStackTrace();}return f;}
}class hello{public static void main(String[] a){fruit f=Factory.getInstance("Reflect.Apple");if(f!=null){f.eat();}}
}

? ? ? ?現在就算我們添加任意多個子類的時候,工廠類就不需要修改。

? ? ? ?使用反射機制的工廠模式可以通過反射取得接口的實例,但是需要傳入完整的包和類名。而且用戶也無法知道一個接口有多少個可以使用的子類,所以我們通過屬性文件的形式配置所需要的子類。

3、使用反射機制并結合屬性文件的工廠模式(即IoC)
首先創建一個fruit.properties的資源文件:
apple=Reflect.Apple
orange=Reflect.Orange
然后編寫主類代碼:
package Reflect;import java.io.*;
import java.util.*;interface fruit{public abstract void eat();
}class Apple implements fruit{public void eat(){System.out.println("Apple");}
}class Orange implements fruit{public void eat(){System.out.println("Orange");}
}
//操作屬性文件類
class init{public static Properties getPro() throws FileNotFoundException, IOException{Properties pro=new Properties();File f=new File("fruit.properties");if(f.exists()){pro.load(new FileInputStream(f));}else{pro.setProperty("apple", "Reflect.Apple");pro.setProperty("orange", "Reflect.Orange");pro.store(new FileOutputStream(f), "FRUIT CLASS");}return pro;}
}class Factory{public static fruit getInstance(String ClassName){fruit f=null;try{f=(fruit)Class.forName(ClassName).newInstance();}catch (Exception e) {e.printStackTrace();}return f;}
}class hello{public static void main(String[] a) throws FileNotFoundException, IOException{Properties pro=init.getPro();fruit f=Factory.getInstance(pro.getProperty("apple"));if(f!=null){f.eat();}}
}
運行結果:

Apple


本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/446992.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/446992.shtml
英文地址,請注明出處:http://en.pswp.cn/news/446992.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

Ubuntu boost庫文件安裝編譯

簡單介紹 Boost庫是為C語言標準庫提供擴展的一些C程序庫的總稱&#xff0c;由Boost社區組織開發、維護.Boost向來有準標準庫之稱&#xff0c;很多新特性例如智能指針等都是先在boost中實現&#xff0c;后來被吸收到標準庫之中. Boost實現了日志、算法、日期、地理、數學、線程…

Java基礎——類加載機制及原理

一、什么是類的加載&#xff1f; 類的加載指的是將類的.class文件中的二進制數據讀入到內存中&#xff0c;將其放在運行時數據區的方法區內&#xff0c;然后在堆區創建一個java.lang.Class對象&#xff0c;用來封裝類在方法區內的數據結構。類的加載的最終產品是位于堆區中的Cl…

在Ubuntu環境下使用vcpkg安裝sqlite_orm包文件

Ubuntu安裝vcpkg 從github下載vcpkg的安裝包&#xff0c;在usr/local路徑下面執行如下命令 git clone https://github.com/Microsoft/vcpkg.git cd vcpkg //進入源碼目錄 ./bootstrap-vcpkg.sh //執行./bootstrap-vcpkg.sh進行編譯安裝&#xff0c;這個過程很慢 編譯安裝好…

finally語句與return語句的執行順序

網上有很多人探討Java中異常捕獲機制try...catch...finally塊中的finally語句是不是一定會被執行&#xff1f;很多人都說不是&#xff0c;當然他們的回答是正確的&#xff0c;經過我試驗&#xff0c;至少有兩種情況下finally語句是不會被執行的&#xff1a; try語句沒有被執行到…

window電腦查看ssh公鑰,以及將自己的公鑰添加到Github等類似網站

查看本機的ssh公鑰 使用命令 cd ~/.ssh使用命令 ls 可以看到 id_rsa id_rsa.pub known_hosts 三個文件&#xff0c;此處需要的是id_rsa.pub文件使用命令 cat id_rsa.pub 查看文件的內容拷貝這段內容 添加自己的公鑰 進入賬戶的設置頁面參照如下步驟&#xff0c;進入SSH Key…

java八大排序算法

一、概述 排序有內部排序和外部排序&#xff0c;內部排序是數據記錄在內存中進行排序&#xff0c;而外部排序是因排序的數據很大&#xff0c;一次不能容納全部的排序記錄&#xff0c;在排序過程中需要訪問外存。 我們這里說說八大排序就是內部排序。 當n較大&#xff0c;則應采…

密鑰安全性討論之密鑰分層管理結構

密鑰分層管理結構 密鑰的安全管理通常采用層次化的保護方法。密鑰管理分層管理機制將密鑰分為三層&#xff0c;即根密鑰、密鑰加密密鑰和工作密鑰下層密鑰為上層密鑰提供加密保護&#xff0c;采用分層的密鑰結構有助于密鑰的管理滿足本規范的要求 工作密鑰 工作密鑰對本地保存…

windows安裝 Git Large File Storage大文件下載工具ge

下載地址 導航到 git-lfs.github.com 并單擊Download開始下載git-lfs的用法指南 驗證安裝成功 打開Git Bash驗證安裝成功&#xff0c;使用命令 git lfs install &#xff0c;如果出現 >Git LFS initlized&#xff0c;就代表安裝成功參考鏈接 安裝 Git Large File Storag…

Java基礎——volatile關鍵字解析

簡介volatile關鍵字雖然從字面上理解起來比較簡單&#xff0c;但是要用好不是一件容易的事情。由于volatile關鍵字是與Java的內存模型有關的&#xff0c;因此在講述volatile關鍵之前&#xff0c;我們先來了解一下與內存模型相關的概念和知識&#xff0c;然后分析了volatile關鍵…

Linux ubuntu對于cmake的版本更新

問題產生 在ubuntu環境下運行C代碼&#xff0c;工程文件中CMakeLists文件顯示要求cmake的版本最低是3.15&#xff0c;但是我的本地版本是3.11&#xff0c;雖然修改CMakelists文件為3.11也是可以編譯通過&#xff0c;但是潛在的問題是未知的。 查看本地cmake的版本 cmake --ve…

Java基礎——Java IO詳解

一、概述 1、Java IO Java IO即Java 輸入輸出系統。不管我們編寫何種應用&#xff0c;都難免和各種輸入輸出相關的媒介打交道&#xff0c;其實和媒介進行IO的過程是十分復雜的&#xff0c;這要考慮的因素特別多&#xff0c;比如我們要考慮和哪種媒介進行IO&#xff08;文件、控…

Java基礎——Java NIO詳解(二)

一、簡介 在我的上一篇文章Java NIO詳解&#xff08;一&#xff09;中介紹了關于標準輸入輸出NIO相關知識&#xff0c; 本篇將重點介紹基于網絡編程NIO&#xff08;異步IO&#xff09;。 二、異步IO 異步 I/O 是一種沒有阻塞地讀寫數據的方法。通常&#xff0c;在代碼進行 rea…

Java基礎——Java NIO詳解(一)

一、基本概念 1、I/0簡介 I/O即輸入輸出&#xff0c;是計算機與外界世界的一個借口。IO操作的實際主題是操作系統。在java編程中&#xff0c;一般使用流的方式來處理IO&#xff0c;所有的IO都被視作是單個字節的移動&#xff0c;通過stream對象一次移動一個字節。流IO負責把對象…

MAC上Git安裝與GitHub基本使用

參考鏈接 MAC上Git安裝與GitHub基本使用

Java基礎——深入理解Java線程池

簡介 我們使用線程的時候就去創建一個線程&#xff0c;這樣實現起來非常簡便&#xff0c;但是就會有一個問題&#xff1a; 如果并發的線程數量很多&#xff0c;并且每個線程都是執行一個時間很短的任務就結束了&#xff0c;這樣頻繁創建線程就會大大降低系統的效率&#xff0c;…

密碼機項目安裝軟件時候出現的問題以及對應的解決辦法

Could NOT find Boost (missing: locale) (found version "1.65.1") 使用命令 apt-get install libboost-locale-dev 進行安裝 解決普通用戶cmake版本11&#xff0c;而root用戶版本15&#xff0c;clion對于版本兼容的問題 修改clion里面的toolchain&#xff0c;將其…

Java基礎——線程及并發機制

前言 在Java中&#xff0c;線程是一個很關鍵的名詞&#xff0c;也是很高頻使用的一種資源。那么它的概念是什么呢&#xff0c;是如何定義的&#xff0c;用法又有哪些呢&#xff1f;為何說Android里只有一個主線程呢&#xff0c;什么是工作線程呢。線程又存在并發&#xff0c;并…

密碼機 密鑰管理項目安裝配置 從零開始

安裝gcc 更新sudo apt-get update下載gcc sudo apt-get install gcc參考鏈接 不推薦 安裝g 下載g sudo apt-get install g 安裝make sudo apt -get install make參考鏈接 安裝cmake 下載地址參考鏈接 安裝ssh sudo apt-get install ssh 安裝git和配置 sudo apt-get inst…

Androud 如何有效減少重復代碼

前言 重復的代碼一直都是可維護性的大敵&#xff0c;重構的重要任務之一也就是要去除掉重復的代碼&#xff0c;有效的減少重復代碼&#xff0c;可以大大提高軟件的擴展性。 在Android開發中&#xff0c;很容易產生重復的代碼。因為Android是組件&#xff0c;模板式開發&#xf…