寫了一段時間java,回顧下基礎(chǔ)知識
C1
在命令行運行Java
javac filename.java
java filename
基本數(shù)據(jù)類型
基本類型是Java語言里的一種內(nèi)置的特殊數(shù)據(jù)類型荆秦,并不是某個類的對象。 直接使用,如
char a = 'x';
這里x就是字面值
四種整型
byte 8位 2^8 -128~127
short 16 位
int 32位
long 64位 整型字面值以l結(jié)尾就是long悔叽,否則是int
默認是十進制,十六進制對應(yīng)0x 二進制對應(yīng)0b 八進制對于00
兩種浮點型
float 32位
double 64位
浮點型字面值默認是double爵嗅,后加f就是float娇澎。
以上六種默認值皆為0或0.0,均為帶符號數(shù)睹晒。
一種字符型
- char 只能保存一個字符趟庄,用單引號引起括细,長度為16位
char a='c';++a
a is b;
一種字符串型
String str="xxx";
嚴格來說,字符串是Immutable的
類型轉(zhuǎn)換
強制類型轉(zhuǎn)換用于從大到小
不同類型數(shù)據(jù)進行運算取較大數(shù)的
如果任何運算單元的長度都不超過int,那么運算結(jié)果就按照int來計算 (如兩個byte相加戚啥,結(jié)果一定是int)
命名規(guī)則
變量命名只能使用字母 數(shù)字 $ _ (中文也可以但我不會這么干的)
final
當一個變量被final修飾的時候奋单,該變量只有一次賦值的機會
操作符
邏輯操作符
注意java中邏輯操作符的操作數(shù)是true和false 不會是別的
短& 長&& 短| 長|| 非!
位操作符
有~ & | ^
三元操作符
? :
用于獲得輸入
Scanner s= new Scanner;
s.nextint();s.nextline();s.nextfloat();
因為回車也算是字符串的一部分猫十,剛好也是字符串(line)結(jié)束的標志览濒,故在回撤之后讀取字符串需要額外加一行s.nextline();
流程控制
基本的三種循環(huán)
switch,在java中拖云,可以是四種整型贷笛,String,char和enum宙项,語法如下
switch(x){
case xx:
;
break;
case xx:
;
;
break;
}
數(shù)組
在java中乏苦,數(shù)組是固定長度的,包含了相同類型數(shù)據(jù)的==容器==
聲明
聲明
int a[]
引用
new int[5]
賦值 聲明引用后可賦值杉允,也可以
int a[]=new int[5]{1,2,3,4,5}
orint a[]=new int[]{1,2,3}
orint a []={1,2,3}
增強型for 循環(huán)
for (int each:a) xxx;
工具類Arrays
Arrays.sort
Arrays.toString
Arrays.binarySearch
Arrays.equals
Arrays.fill
其他待補充
類與對象
創(chuàng)建與引用
new Class();是創(chuàng)建
Class c1= new Class();//左邊是引用
Class c2
c2=c1;//更改引用
變量的修飾符四種
先搞清類之間的關(guān)系邑贴,同包關(guān)系,子類關(guān)系叔磷,笛卡爾乘拢驾,得到
同包子類
同包非子類
不同包子類
沒關(guān)系,不同包非子類
之后改基,四種修飾符及用處如下
private 只有自己能訪問
缺省 同一個包里的可以訪問或者繼承繁疤,否則不行
protect 同一個包里的或者是子類,則可以繼承
public 誰都可以
初始化
對象屬性初始化有3種
聲明該屬性的時候初始化
構(gòu)造方法中初始化
初始化塊
類屬性初始化有2種
聲明該屬性的時候初始化
靜態(tài)初始化塊
static{
itemCapacity = 6;//靜態(tài)初始化塊 初始化
}
singleton 單例模式
構(gòu)造方法私有化
靜態(tài)屬性指向?qū)嵗?/p>
public static的 getInstance方法秕狰,返回第二步的靜態(tài)屬性
餓漢模式稠腊、懶漢模式還有許多其他模式 待補充
枚舉類型 enum
public enum Season{
Spring,Summer,Fall,Winter
}
for(Season s:Season.values())
System.out.println(s);
接口與抽象
instance of 判斷對象是否是子類
多態(tài)的實現(xiàn) 需要向上類型轉(zhuǎn)換和override 而隱藏就是靜態(tài)方法(類方法)的重寫(覆蓋)
構(gòu)造方法 子類一定會調(diào)用父類的構(gòu)造方法,如果父類沒有構(gòu)造方法(確切的說鸣哀,任何一個類沒有顯示聲明構(gòu)造方法)架忌,那么編譯器自動加上無參無內(nèi)容的空父類構(gòu)造方法,如果父類生命了無參構(gòu)造方法我衬,那么子類直接調(diào)用叹放,如果父類只聲明了有參構(gòu)造方法,那么子類
A:在父類中加一個無參構(gòu)造方法 B:通過使用super關(guān)鍵字去顯示的調(diào)用父類的帶參構(gòu)造方法==(需要放在子類的構(gòu)造函數(shù)的第一句)==C:子類通過this去調(diào)用本類的其他構(gòu)造方法
==所有對象==都繼承自O(shè)bject對象挠羔,因此也繼承了其一些方法如 String toString(),boolean equals(),wait(),notify(),notifyall(),hashcode()等方法井仰。
抽象類 一旦一個類中有抽象方法(public abstract void xx();)這個類就稱為抽象類,必須加上abstract破加,也因此俱恶,抽象類中不一定必須全是抽象方法,也可以有實體方法,叫做==默認方法==合是,interface中也是這樣了罪。但是interface中的方法一定是默認為public static final,while抽象類中這三個屬性都是可選的(抽象方法和實體方法都如此)
默認方法可以寫在接口和抽象類中端仰,通過default聲明(否則在接口中會報錯)
數(shù)字與字符串
裝箱與拆箱 繼承自抽象類Number的所有類都對應(yīng)一個基本類型(六種數(shù)字)
轉(zhuǎn)換到字符串 基本類型捶惜,使用
String.valueof(i);
裝箱類型田藐,直接使用繼承自O(shè)bject的to String();
轉(zhuǎn)換到其他類型 調(diào)用其他類型的封裝類的靜態(tài)方法
xx.parsexx(String str);
數(shù)學(xué)方法
round(); MATH.PI;MATH.E,sqrt();
Character 對應(yīng)char的類 有isdigit 和isnumber方法用于判斷是否位數(shù)字或是否為字符串(聯(lián)想 也可以通過=判斷荔烧,還可通過正則簡化枚舉)
格式化輸出。
//總長度是8,左對齊
System.out.format("%-8d%n",year);
//總長度是8,不夠補0
System.out.format("%08d%n",year);
//千位分隔符
System.out.format("%,8d%n",year*10000);
本質(zhì)上是printf(1)在DOS和Windows中汽久,每行結(jié)尾是 “\r\n”鹤竭;(2)Linux系統(tǒng)里,每行結(jié)尾只有 “\n”景醇;(3)Mac系統(tǒng)里臀稚,每行結(jié)尾是只有 "\r"。
字符串處理函數(shù)
charAt 獲取給定字符的位置
toCharArray 轉(zhuǎn)換成字符數(shù)組
subString 截取子串
split 分隔開
trim 去掉空格
toLowerCase toUpperCase 轉(zhuǎn)換成大小寫
indexOf lastIndexOf contains 字符串的位置三痰,是否包含
replaceAll replaceFirst 字符串替換
字符串比較
== 判斷是否為同一個對象
equals(String str)
判斷是否一樣startsWith
以...開始endsWith
以...結(jié)束
Stringbuffer 變長字符串
append delete insert reverse 以及l(fā)ength capacity 這些屬性 性能較高
日期處理
Date d=new Date();可選參數(shù) int 表示從1970年1月1日過了x毫秒(10^-3秒)對應(yīng)的時間吧寺。
gettime返回long類型,表示從那時到現(xiàn)在經(jīng)歷了多少毫秒
System.currentTimeMillis(); 返回系統(tǒng)當前時間散劫,long型稚机。 日歷類型:
//通過日歷對象得到日期對象
Date d = c.getTime();
Date d2 = new Date(0);
c.setTime(d2); //把這個日歷,調(diào)成日期 : 1970.1.1 08:00:00
還有add和set方法获搏。
- 通過這種方式來進行格式化輸出
M 代表月
d 代表日
H 代表24進制的小時
h 代表12進制的小時
m 代表分鐘
s 代表秒
S 代表毫秒
SimpleDateFormat sdf=new SimpleDateFormat("y-M-dd");
System.out.println(sdf.format(new Date(System.currentTimeMillis())));
C2
異常處理
通過try catch finally的方式進行處理赖条。
異常可分為錯誤ERROR和Exception常熙,后者又分為運行時異常(runtimeException)和可查異常纬乍,三者都繼承了Throwable類
[圖片上傳失敗...(image-5b2c1d-1551662952330)]
文件操作
File f = new File("");
// 以字符串數(shù)組的形式,返回當前文件夾下的所有文件(不包含子文件及子文件夾)
f.list();
// 以文件數(shù)組的形式裸卫,返回當前文件夾下的所有文件(不包含子文件及子文件夾)
File[]fs= f.listFiles();
// 以字符串形式返回獲取所在文件夾
f.getParent();
// 以文件形式返回獲取所在文件夾
f.getParentFile();
// 創(chuàng)建文件夾仿贬,如果父文件夾skin不存在,創(chuàng)建就無效
f.mkdir();
// 創(chuàng)建文件夾墓贿,如果父文件夾skin不存在茧泪,就會創(chuàng)建父文件夾
f.mkdirs();
// 創(chuàng)建一個空文件,如果父文件夾skin不存在,就會拋出異常
f.createNewFile();
// 所以創(chuàng)建一個空文件之前募壕,通常都會創(chuàng)建父目錄
f.getParentFile().mkdirs();
// 列出所有的盤符c: d: e: 等等
f.listRoots();
// 刪除文件
f.delete();
// JVM結(jié)束的時候调炬,刪除文件,常用于臨時文件的刪除
f.deleteOnExit();
File f = new File("d:/LOLFolder/LOL.exe");
System.out.println("當前文件是:" +f);
//文件是否存在
System.out.println("判斷是否存在:"+f.exists());
//是否是文件夾
System.out.println("判斷是否是文件夾:"+f.isDirectory());
//是否是文件(非文件夾)
System.out.println("判斷是否是文件:"+f.isFile());
//文件長度
System.out.println("獲取文件的長度:"+f.length());
//文件最后修改時間
long time = f.lastModified();
Date d = new Date(time);
System.out.println("獲取文件的最后修改時間:"+d);
//設(shè)置文件修改時間為1970.1.1 08:00:00
f.setLastModified(0);
//文件重命名
File f2 =new File("d:/LOLFolder/DOTA.exe");
f.renameTo(f2);
System.out.println("把LOL.exe改名成了DOTA.exe");
System.out.println("f1的絕對路徑:" + f1.getAbsolutePath());
// 相對路徑,相對于工作目錄舱馅,如果在eclipse中缰泡,就是項目目錄
File f2 = new File("LOL.exe");
System.out.println("f2的絕對路徑:" + f2.getAbsolutePath());
// 把f1作為父目錄創(chuàng)建文件對象
File f3 = new File(f1, "LOL.exe");
流
流是傳輸數(shù)據(jù)的一個方式,從程序的角度來區(qū)分輸入流和輸出流,來源可以是硬盤、程序棘钞、網(wǎng)絡(luò)等任意地方
FileInputStream fis= new FileInputStream(new File(str));
InputStream和OutputStream是最基本的字節(jié)流缠借,文件輸入輸出流繼承了他們。
關(guān)閉流有三種不同的編寫位置宜猜,可以在try中關(guān)閉泼返,但可能因為在fis.close執(zhí)行前就拋出異常導(dǎo)致無法關(guān)閉,也可以把close定義在finally中姨拥,但聲明xx=null就要在catch前绅喉,因為try語句塊和finally語句塊不共享變量,最后一種方法是sdk7開始的try后的()聲明和初始化流叫乌,這樣在try結(jié)束的時候就自動關(guān)閉了==待補充==
Reader Writer和剛才的InputStream OutputStream是一個地位的柴罐,不過不是字節(jié)而是字符讀取。
集合框架
用處:變長數(shù)組憨奸,可以同時存放多種類型革屠,如各種類和基本類型。
ArrayList ar=new Arraylist();
,然后調(diào)用add();remove();get();set();等方法即可對其操作排宰,它會自動變長度似芝。還可以指定其可以增加的類型,如
ArrayList <Hero> lh=new ArrayList <>();
(后邊一個<>中指定的類型在SDK7后可以省略板甘。這樣党瓮,就保證只能add這種類型。此外虾啦,通過實現(xiàn)統(tǒng)一個接口麻诀,可以實現(xiàn)只能增加確定數(shù)目個類。ArrayList實際上是實現(xiàn)了List接口==待補充==傲醉,繼承了其所有方法蝇闭。
ArrayList的遍歷,可以通過for(;;)get(index)來取得硬毕;也可以通過
Iterator<Hero> it =lh.iterator();
這樣來獲得迭代器呻引,然后通過it.hasnext()和it.next()
進行遍歷,還可以通過foreach循環(huán)進行遍歷吐咳。只是在要刪除其中某些元素時逻悠,直接使用it或者foreach會出現(xiàn)錯誤==待補充==(為什么?),韭脊,可以放到一個臨時容器童谒,刪除臨時容器來實現(xiàn)對象(內(nèi)存空間的釋放),這樣在原List(可以發(fā)現(xiàn)其為鏈表結(jié)構(gòu))中依然是連續(xù)的沪羔。LinkedList相比ArrayList實現(xiàn)了隊列饥伊、雙向鏈表的接口,因此多了addlast();addfirst();以及offer() 在最后添加元素;poll() 取出第一個元素;peek() 查看第一個元素這些方法
二叉樹排序、遍歷算法java實現(xiàn)時應(yīng)注意的事情琅豆,如travel方法應(yīng)獨立于對象==待補充==
HashMap和HashSet统捶,后者封裝了前者爱榕,都是無序的
Collection是一個接口滑臊,List牍疏,Deque(間接繼承),Set都繼承了它冻押,但Map是存放<x,x>的驰贷,故無關(guān)。Collections是一個類翼雀,容器的工具類,就如同Arrays是數(shù)組的工具類
HashMap和Hashtable都實現(xiàn)了Map接口饱苟,都是鍵值對保存數(shù)據(jù)的方式區(qū)別1: HashMap可以存放null;Hashtable不能存放null區(qū)別2:HashMap不是線程安全的類狼渊;Hashtable是線程安全的類
HashSet: 無序;LinkedHashSet: 按照插入順序类垦;TreeSet: 從小到大排序
泛型generic
之前用過的狈邑,集合中的泛型
ArrayList <Hero> lh=new ArrayList <>()
集合中實現(xiàn)了某個接口使得可以直接<>這樣寫。相對的:public class Mystack<T>{}``Mystack<Hero> mh=new Mystack<>();
自己聲明<T>即可蚤认,其中T將會替換掉類中方法返回值米苹、參數(shù)類型和屬性的類型聲明(可以)。如果希望只取出砰琢,不插入蘸嘶,就使用? extends Hero;如果希望只插入陪汽,不取出训唱,就使用? super Hero;如果希望挚冤,又能插入况增,又能取出,就不要用通配符训挡?
子類泛型和父類泛型都不能相互轉(zhuǎn)換澳骤,原因是子類轉(zhuǎn)父類(若是對象則可以)再加新的,內(nèi)存格式不對(其他子類)澜薄,父類轉(zhuǎn)子類为肮,倒是可以加進去,但是取出會有問題肤京。根本原因是相比對象颊艳,集合泛型同時具備了加入和取出操作,是雙向的,而向上類型轉(zhuǎn)換是單向的籽暇,導(dǎo)致轉(zhuǎn)換無法進行温治。
Lambda表達式
大體來說,有三種類型來寫一段代碼實現(xiàn)一個功能戒悠,一是直接剛代碼熬荆,但耦合性大,不易修改绸狐,不好復(fù)用卤恳,二是通過類解耦出來,通過匿名類new一個接口Comparator<Hero> c = new Comparator<Hero>() {}
(集合的排序方法寒矿,使用的泛型突琳,一般可以沒有)在其中重載接口中的方法,并在另一個方法中和它要處理的數(shù)據(jù)一起作為參數(shù)傳入方法,但這樣會生成很多匿名類符相。三是直接把數(shù)據(jù)和方法傳入拆融,那個方法就是Lambda表達式,格式是(argu)->(expression).使用Lambda表達式的好處是簡潔啊终,壞處是長了不易讀镜豹,不易維護,不易輸出日志蓝牲。
多線程
多線程是指一個進程中多個同時進行的任務(wù)==待補充==趟脂,java中多線程實現(xiàn)方式由繼承thread類:class A extends Thread;A aa=new A();A.start()
(需要在A中重寫run()方法);實現(xiàn)runnable接口class B implements Runnable;B bb=new B;new Thread(B).start()
,Runnable中聲明了run()方法例衍,自然B中需要重載昔期,但因為R中沒有start方法,只有Thread中有start()方法佛玄,故需要通過Thread的構(gòu)造函數(shù)來進行啟動線程硼一。匿名類也可以實現(xiàn)多線程。Thread t1=new Thread(){run(){};};t1.start();
匿名類的一個好處是可以很方便的訪問外部的局部變量翎嫡。前提是外部的局部變量需要被聲明為final欠动。(JDK7以后就不需要了)。還能使得代碼簡潔惑申。
線程的實現(xiàn)作為一個類或者接口肯定有一些方法具伍,包括yield暫停,sleep()睡眠圈驼,setpriority設(shè)置優(yōu)先級人芽,setDaemon(true);設(shè)置為守護線程
除了這些方法,多個線程對一個資源進行操作就會出現(xiàn)問題绩脆,根本原因是一個Thread中操作非原子萤厅,可再分橄抹,因而處理器執(zhí)行A的一部分再去執(zhí)行B,就會造成數(shù)據(jù)出錯(臟數(shù)據(jù)惕味?)楼誓。的最簡單的:銀行存款問題。
那么名挥,如何解決疟羹?根據(jù)剛才說的,只需要一個線程占有資源的時候禀倔,其他資源不能同時訪問進而占有進程即可榄融。可以通過java關(guān)鍵字sy來實現(xiàn)synchronized
Object someObject =new Object();
synchronized (someObject){
//此處的代碼只有占有了someObject后才可以執(zhí)行
}
這里someobject就相當于一個信號量救湖,也就是說愧杯,synchronized保證同時只有一個線程占有代碼塊中的操作。 因此鞋既,也可以用繼承了THread類的類作為Sy方法的參數(shù)力九,this(在方法聲明)或者對象名(在代碼塊中)都可以。 進一步地涛救,直接在類的定義的方法前加上sy畏邢,表示這個方法在被調(diào)用時所屬對象被鎖定(和上文的sy(this)是一樣的。
與syn類似的lock()
Lock lock = new ReentrantLock();
這個lock也可以完成syn所能完成的任務(wù)检吆,只是syn在代碼塊結(jié)束后自動釋放,而lock必須手動釋放程储,因此若忘記釋放蹭沛,就會造成死鎖;另一個區(qū)別是lock可以試圖在一定時間內(nèi)占用章鲤,如果占用失敗摊灭,就拉到,這可以很大程度上減少死鎖的產(chǎn)生败徊。
相對應(yīng)syn的交互辦法帚呼,lock也有相應(yīng)的交互辦法,分別是await皱蹦、signal煤杀、signalall,這些方法從lock對象得到的condition那里得到沪哺。
此外沈自,syn是java中的關(guān)鍵字,而lock是一個接口辜妓,是代碼層面的實現(xiàn)枯途。
線程安全的類
如果一個類忌怎,其方法都是有synchronized修飾的,那么該類就叫做線程安全的類酪夷。同一時間榴啸,只有一個線程能夠進入 這種類的一個實例 的去修改數(shù)據(jù),進而保證了這個實例中的數(shù)據(jù)的安全(不會同時被多線程修改而變成臟數(shù)據(jù))晚岭。java本身實現(xiàn)了一些線程安全的類鸥印。==待補充==
死鎖
死鎖是在線程安全的基礎(chǔ)上產(chǎn)生的,如t1占有r1腥例,之后想要占有r2辅甥,whilet2占有r2,之后想要占有r1燎竖,此時它倆互相等待璃弄,進入死鎖。擴展到更多的線程和資源的關(guān)系中构回,判定方法見操作系統(tǒng)(總算操作系統(tǒng)沒白學(xué))==待補充==
如何解決死鎖夏块?==待補充==
線程交互
多個線程同時進行,肯定需要交互纤掸,可以通過網(wǎng)絡(luò)監(jiān)聽+switch脐供。也有一些方法如wait()和notify(),屬于Object上的方法借跪,前者使當前線程停下等待后者政己,后者使得因前者停下的線程繼續(xù)運行。
生產(chǎn)者消費者問題
一開始我自己寫的時候掏愁,是在生產(chǎn)者和消費者這兩個類中實現(xiàn)了notify()和wait()歇由,然后在wait那里報錯,一開始寫的還是this.wait().....后來改成了ms.wait(),報錯是java.lang.IllegalMonitorStateException
google得知果港,是因為調(diào)用.wait()的方法沒有+同步鎖沦泌, 即syn,因此辛掠,wait()需要放在資源(的方法)中谢谦,而非調(diào)用資源的線程中!根本原因是this.wait()表示 讓占有this的線程等待萝衩,并臨時釋放占有回挽。this.notify() 表示通知那些等待在this的線程,可以蘇醒過來了欠气。 等待在this的線程厅各,恰恰就是減血線程。 一旦recover()結(jié)束预柒, 加血線程釋放了this队塘,減血線程袁梗,就可以重新占有this,并執(zhí)行后面的減血工作憔古。
線程池
類似剛才的生產(chǎn)者消費者問題遮怜,線程池的資源是指一個個需要解決的問題,而消費者是線程池中的線程鸿市,生產(chǎn)者是....emmm添加任務(wù)的人锯梁。
`ThreadPoolExecutor threadPool= new ThreadPoolExecutor(10, 15, 60, TimeUnit.SECONDS, new LinkedBlockingQueue<Runnable>());
`然后 通過excute(Runnable x)來添加任務(wù)。
atomic operation
詳見os焰情,不可再分的操作陌凳,java中提供了 AtomicInteger at= new AtomicInteger(3);
來保證++i的原子性操作(本來只有這種int i=1;
是原子操作的)。
網(wǎng)絡(luò)編程部分
小的聊天工具
Client.java&Server.java聊天内舟,傻到每個.java建立一個監(jiān)聽和一個發(fā)送合敦,這樣一個開啟監(jiān)聽的時候也開啟也發(fā)送,這個發(fā)送永遠了到不了另一個監(jiān)聽验游,因為另一個監(jiān)聽還沒開(試想你原來的Client先開的話充岛,Server是接受不到消息的)。所以耕蝉,只需要一個Socket連接崔梗。然后把接收和發(fā)送消息寫到同一個while(true)里,此時idea會報錯:循環(huán)不會結(jié)束垒在,后邊的訪問不到蒜魄,這時業(yè)務(wù)邏輯稍微改一下不===true就好。但是while()這樣有一個問題场躯,就是必須是一問一答的形式权悟,因為一定會是{接收消息;發(fā)送消息;}的樣子推盛。此時需要多線程(兩個就夠了)。
網(wǎng)絡(luò)基礎(chǔ)知識部分
java可以監(jiān)聽一個ip的一個端口來接收消息谦铃,至于具體怎樣耘成,去看計算機網(wǎng)絡(luò)吧==待補充==
C3
反射Reflection
類對象,就是用于描述這種類驹闰,都有什么屬性瘪菌,什么方法的。對比Hero對象嘹朗,Animal對象师妙。
獲取類對象有三個方法,分別是類名.class;對象名.getclass;以及Class.forname(類名);
之后通過類對象的構(gòu)造器和強制類型轉(zhuǎn)換獲得想要的對象
Constructor c=b.getConstructor();
Hero hh=(Hero)c.newInstance();
除了第一個屹培,其他都會初始化要求類對象的類的類方法即static語句塊默穴。
與反射有關(guān)的怔檩,syn鎖+在對象方法上,占用的對象是當前對象蓄诽,也即當前對象無法被其他對象訪問薛训,而+在類方法之前,占用的對象就是類對象仑氛。
通過反射獲取對象其內(nèi)容是空的乙埃,要通過獲取到的唯一的類對象的方法進行設(shè)定,具體如下
Field f1=hh.getClass().getField("name");
Field f2=hh.getClass().getDeclaredField("hp");
f1.set(hh,"temmo");
區(qū)別是前者可以獲得public的屬性锯岖,包括從父類繼承的介袜,后者可以獲得所有屬性,但不能獲得繼承來的出吹,同時遇伞,private的不可直接訪問(protected的在同一個包里可以(本來就可以)),需要方法setAccessible(true);
獲取對象之后就需要獲取趋箩、調(diào)用方法赃额,與剛才類似
Method m=hh.getClass().getDeclaredMethod("setHp", double.class);
m.invoke(hh,23.9);
那么,這樣做又什么好處呢叫确?從上邊看出來跳芳,反射可以通過String類名直接獲得類對象,進而獲得對象并對其屬性和方法進行修改竹勉。也就是說飞盆,可以通過外部配置文件決定生成的類。(如果要用java自己實現(xiàn)次乓,讀取文件之后做if或者switch吓歇,或者把那個String型類名嵌入到j(luò)ava代碼中)這樣就實現(xiàn)了解耦。Spring框架就是這么干的票腰。
Annotation
java中注解是可以被編譯器接收的對代碼段起影響的代碼城看,工程上目的主要是解耦⌒游浚可以分為內(nèi)置注解测柠、框架注解和自定義注解,其中自定義注解需要元注解進行配置缘滥,內(nèi)置注解也需要轰胁,都需要(......)。根據(jù)注解的作用域@Retention朝扼,注解分為RetentionPolicy.SOURCE: Java源文件上的注解赃阀;RetentionPolicy.CLASS: Class類文件上的注解;RetentionPolicy.RUNTIME: 運行時的注解擎颖。
還有自定義注解榛斯,通過配置一個@interface观游,并在另一個類前用其注解,然后通過反射這個類獲得在注解處配置的值肖抱,還是有點迷备典,這樣做的意義除了解耦還有啥?==待補充==
日志
通常意述,調(diào)試信息需要通過打印來輸出提佣,但這樣有一些缺點。通過日志更加方便荤崇,在使用之前拌屏,首先要導(dǎo)入jar包,idea導(dǎo)入jar包的方式术荤。
待續(xù) ......