Java容易搞错的知识点
一、關(guān)于Switch
代碼:
Java代碼
1???????? public class TestSwitch {??
2???????? ????public static void main(String[] args) {??
3???????? ????????int i = 2;??
4???????? ????????switch (i) {??
5???????? ????????case 1:??
6???????? ????????????System.out.println(1);??
7???????? ????????case 2:??
8???????? ????????????System.out.println(2);??
9???????? ????????case 3:??
10???? ????????????System.out.println(3);??
11???? ????????default:??
12???? ????????????System.out.println(4);??
13???? ????????}??
14???? ????}??
15???? }?
?
?
結(jié)果:
2
3
4
?
分析:
少了break;所以2以下的case和default都執(zhí)行了一遍。
?
二、Equals和==運(yùn)算符
代碼:
Java代碼
1???????? public static void test() {??
2???????? ????String x = "hello";??
3???????? ????String y = "world";??
4???????? ????String z = new String("helloworld");??
5???????? ????String a = "helloworld";??
6???????? ????System.out.println("x+y equals z:" + (x + y).equals(z));??
7???????? ????System.out.println("a == z:" + (a == z));??
8???????? ????System.out.println("x == hello:" + (x == "hello"));??
9???????? ????System.out.println("a == helloworld:" + (a == "hello" + "world"));??
10???? ????System.out.println("a == x+y:" + (a == (x + y)));??
11???? }?
?
?
結(jié)果:
x+y equals z:true
a == z:false
x == hello:true
a == helloworld:true
a == x+y:false
?
分析:
1.String.equals()方法比較的是字符串的內(nèi)容,所以(x + y).equals(z)為true.
2.“==”比較的是 String 實(shí)例的引用,很明顯 a 和z 并不是同一個(gè) String 實(shí)例,所以(a == z)為false.
3.根據(jù)常量池的知識(shí),容易得知(x == "hello")和(a == "hello" + "world")都為true.
(常量池指的是在編譯期被確定并被保存在已編譯的.class 文件中的一些數(shù)據(jù)。它包含了
關(guān)于方法、類、接口等,當(dāng)然還有字符串常量的信息。也就是所謂的持久代。)
4.那么(a == (x + y))為什么是false呢?這點(diǎn)暫點(diǎn)有點(diǎn)不大清楚。初步認(rèn)為是x+y是引用相加,不能放入常量池。
?
三、Override覆蓋
代碼:
?
Java代碼
1???????? public class Parent {??
2???????? ??
3???????? ????public static String say() {??
4???????? ????????return "parent static say";??
5???????? ????}??
6???????? ??
7???????? ????public String say2() {??
8???????? ????????return "parent say";??
9???????? ????}??
10???? }??
11???? ??
12???? public class Child extends Parent {??
13???? ????public static String say() {??
14???? ????????return "child static say";??
15???? ????}??
16???? ??
17???? ????public String say2() {??
18???? ????????return "child say";??
19???? ????}??
20???? }??
21???? ??
22???? public class OverrideTest {??
23???? ??
24???? ????public static void main(String[] args) {??
25???? ????????Parent p = new Child();??
26???? ????????System.out.println(p.say());??
27???? ????????System.out.println(p.say2());??
28???? ??
29???? ????}??
30???? ??
31???? }?
?
?
結(jié)果:
parent static say
child say
?
分析:
1.我們創(chuàng)建了一個(gè)Parent類的實(shí)例。變量 p 的數(shù)據(jù)類型為 Parent 類 但是它仍舊是 Child 類的一個(gè)實(shí)例。因?yàn)镃hild類覆蓋了Parent類的方法say2(),所以p.say2()調(diào)用為子類的方法。
2.為什么p.say()卻是調(diào)用父類Parent的方法呢?因?yàn)镴ava中規(guī)定“實(shí)例方法被覆蓋,靜態(tài)方法被隱藏”.
關(guān)于Override的一些規(guī)則:
用子類的靜態(tài)方法隱藏父類中同樣標(biāo)識(shí)的實(shí)例方法是不合法的,編譯器將會(huì)報(bào)錯(cuò);
用子類的實(shí)例方法覆蓋父類中同樣標(biāo)識(shí)的靜態(tài)方法也是不合法的,編譯器同樣會(huì)報(bào)錯(cuò);
帶關(guān)鍵字 final的方法(靜態(tài)和實(shí)例方法)都不能被覆蓋;
實(shí)例方法能夠被覆蓋;
抽象方法必須在具體類中被覆蓋。
?
我們知道,在JAVA中,子類可以繼承父類,如果子類聲明的方法與父類有重名的情況怎么辦,大伙兒都知道要是重寫,但是實(shí)際上這又分為兩種情況,就是方法和變量在繼承時(shí)的覆蓋和隱藏問(wèn)題,這些概念性的東西看似無(wú)聊,但是在面試或者是SCJP認(rèn)證題中圍繞這些是會(huì)經(jīng)常碰到的,所以這里來(lái)討論下
?
首先我們來(lái)看幾個(gè)概念
?????? 隱藏 :child隱藏了parent的變量和方法,那么,child不能訪問(wèn)parent被隱藏的變量或者方法,但是,講B轉(zhuǎn)換成A中,可以訪問(wèn)A被隱藏的變量或者方法
??????? 覆蓋 :child覆蓋了parent的變量或者方法,那么,child不能訪問(wèn)parent被覆蓋的變量或者方法,將child轉(zhuǎn)換成parent后同樣不能訪問(wèn)parent被覆蓋的變量或者方法
?
首先看一下JAVA中方法和變量在繼承時(shí)的覆蓋和隱藏規(guī)則
?????? 1.父類的實(shí)例變量和靜態(tài)變量能被子類的同名變量隱藏
?????? 2.父類的靜態(tài)方法被子類的同名靜態(tài)方法隱藏
?????? 3.父類的實(shí)例方法被子類的同名實(shí)例變量覆蓋
?
還有幾點(diǎn)需要注意的是
?????? 1.不能用子類的靜態(tài)方法隱藏 父類中同樣標(biāo)示(也就是返回值 名字 參數(shù)都一樣)的實(shí)例方法
?????? 2.不能用子類的實(shí)例方法覆蓋 父類中同樣標(biāo)示的靜態(tài)方法
?????? 3.這點(diǎn)兒請(qǐng)注意,就是變量只會(huì)被隱藏 不會(huì)被覆蓋 ,無(wú)論他是實(shí)例變量還是靜態(tài)變量,而且,子類的靜態(tài)變量可以隱藏 父類的實(shí)例變量,子類的實(shí)例變量可以隱藏 父類的靜態(tài)變量
?
Java代碼 ?
1???????? //父類 ??
2???????? class?Parent ??
3???????? { ??
4???????? ????public?static?String?kind="javastudy.extendsstudy.parent"; ??
5???????? ????public?static?int?age=50; ??
6???????? ????public?String?name="Parent"; ??
7???????? ??
8???????? ????//靜態(tài)方法,返回包名 ??
9???????? ????public?static?String?getKind() ??
10???? ????{ ??
11???? ????????System.out.println("parent的getKind()方法被調(diào)用了"); ??
12???? ????????return?kind; ??
13???? ????} ??
14???? ????//靜態(tài)方法,返回年齡 ??
15???? ????public?static?int?getAge() ??
16???? ????{ ??
17???? ????????System.out.println("Parent的getAge()方法被調(diào)用了"); ??
18???? ????????return?age; ??
19???? ????} ??
20???? ??
21???? ????//實(shí)例方法,返回姓名 ??
22???? ????public?String?getName() ??
23???? ????{ ??
24???? ????????System.out.println("Parent的getName()方法被調(diào)用了"); ??
25???? ????????return?this.name; ??
26???? ????} ??
27???? } ??
28???? //子類 ??
29???? class?Child?extends?Parent ??
30???? { ??
31???? ????public?static?String?kind="javastudy.extendsstudy.child"; ??
32???? ????public?int?age=25; ??
33???? ????public?String?name="child"; ??
34???? ??
35???? ????//隱藏父類靜態(tài)方法 ??
36???? ????public?static?String?getKind() ??
37???? ????{ ??
38???? ????????System.out.println("child的getkind()方法被調(diào)用了"); ??
39???? ????????return?kind; ??
40???? ????} ??
41???? ???? ??
42???? ????//獲取父類包名 ??
43???? ????public?static?String?getParentKind() ??
44???? ????{ ??
45???? ????????return?Parent.kind; ??
46???? ????} ??
47???? ???? ??
48???? ????//覆蓋父類實(shí)例方法 ??
49???? ????public?String?getName() ??
50???? ????{ ??
51???? ????????System.out.println("child的getName()被調(diào)用了"); ??
52???? ????????return?this.name; ??
53???? ????} ??
54???? ???? ??
55???? ????//獲取父類名稱 ??
56???? ????public?String?getParentName() ??
57???? ????{ ??
58???? ????????return?super.name; ??
59???? ????} ??
60???? ????/* ?
61???? ?????*錯(cuò)誤,實(shí)例方法不能覆蓋父類的靜態(tài)方法 ?
62???? ????public?int?getAge() ?
63???? ????{ ?
64???? ????????return?this.age; ?
65???? ????} ?
66???? ????*/??
67???? } ??
68???? ??
69???? ??
70???? class?Test? ??
71???? { ??
72???? ????public?static?void?main(String[]?args)? ??
73???? ????{ ??
74???? ????????Child?child=new?Child(); ??
75???? ????????System.out.printf("子類名稱:%s,年齡:%d,包? 名:%s%n",child.name,child.age,child.kind); ??
76???? ????????//輸出:子類名稱:child,年齡:25,包:javastudy.extendsstudy.child ??
77???? ??
78???? ????????//把child轉(zhuǎn)換成parent對(duì)象 ??
79???? ????????Parent?parent=child; ??
80???? ??
81???? ????????System.out.printf("轉(zhuǎn)換后的名稱:%s,年齡:%d,包名:%s%n",parent.name,parent.age,parent.kind); ??
82???? ????????//輸出:轉(zhuǎn)換后的名稱:Parent,年齡:50,包:javastudy.extendsstudy.parent ??
83???? ??
84???? ????????System.out.printf("子類訪問(wèn)父類被隱藏的實(shí)例變量name:%s%n",child.getParentName()); ??
85???? ????????//輸出:子類訪問(wèn)父類被隱藏的實(shí)例變量name:Parent ??
86???? ???????? ??
87???? ????????System.out.printf("子類訪問(wèn)父類被隱藏的靜態(tài)變量kind:%s",child.getParentKind()); ??
88???? ????????//輸出:子類訪問(wèn)父類被隱藏的靜態(tài)變量kind:javastudy.extendsstudy.parent ??
89???? ??
90???? ????????child.getName(); ??
91???? ????????//輸出:child的getName()被調(diào)用了 ??
92???? ??
93???? ????????//**************注意看這個(gè)方法,返回的還是子類的getName ??
94???? ????????parent.getName(); ??
95???? ????????//輸出:child的getName()被調(diào)用了 ??
96???? ??
97???? ????????child.getKind(); ??
98???? ????????//輸出:child的getkind()方法被調(diào)用了 ??
99???? ??
100? ????????parent.getKind(); ??
101? ????????//輸出:parent的getKind()方法被調(diào)用了 ??
102? ????} ??
103? }??
//父類
class Parent
{
public static String kind="javastudy.extendsstudy.parent";
public static int age=50;
public String name="Parent";
?
//靜態(tài)方法,返回包名
public static String getKind()
{
? System.out.println("parent的getKind()方法被調(diào)用了");
? return kind;
}
//靜態(tài)方法,返回年齡
public static int getAge()
{
? System.out.println("Parent的getAge()方法被調(diào)用了");
? return age;
}
?
//實(shí)例方法,返回姓名
public String getName()
{
? System.out.println("Parent的getName()方法被調(diào)用了");
? return this.name;
}
}
//子類
class Child extends Parent
{
public static String kind="javastudy.extendsstudy.child";
public int age=25;
public String name="child";
?
//隱藏父類靜態(tài)方法
public static String getKind()
{
? System.out.println("child的getkind()方法被調(diào)用了");
? return kind;
}
//獲取父類包名
public static String getParentKind()
{
? return Parent.kind;
}
//覆蓋父類實(shí)例方法
public String getName()
{
? System.out.println("child的getName()被調(diào)用了");
? return this.name;
}
//獲取父類名稱
public String getParentName()
{
? return super.name;
}
/*
?*錯(cuò)誤,實(shí)例方法不能覆蓋父類的靜態(tài)方法
public int getAge()
{
? return this.age;
}
*/
}
?
?
class Test
{
public static void main(String[] args)
{
? Child child=new Child();
? System.out.printf("子類名稱:%s,年齡:%d,包名:%s%n",child.name,child.age,child.kind);
? //輸出:子類名稱:child,年齡:25,包:javastudy.extendsstudy.child
?
? //把child轉(zhuǎn)換成parent對(duì)象
? Parent parent=child;
?
? System.out.printf("轉(zhuǎn)換后的名稱:%s,年齡:%d,包名:%s%n",parent.name,parent.age,parent.kind);
? //輸出:轉(zhuǎn)換后的名稱:Parent,年齡:50,包:javastudy.extendsstudy.parent
?
? System.out.printf("子類訪問(wèn)父類被隱藏的實(shí)例變量name:%s%n",child.getParentName());
? //輸出:子類訪問(wèn)父類被隱藏的實(shí)例變量name:Parent
?
? System.out.printf("子類訪問(wèn)父類被隱藏的靜態(tài)變量kind:%s",child.getParentKind());
? //輸出:子類訪問(wèn)父類被隱藏的靜態(tài)變量kind:javastudy.extendsstudy.parent
?
? child.getName();
? //輸出:child的getName()被調(diào)用了
?
? //**************注意看這個(gè)方法,返回的還是子類的getName
? parent.getName();
? //輸出:child的getName()被調(diào)用了
?
? child.getKind();
? //輸出:child的getkind()方法被調(diào)用了
?
? parent.getKind();
? //輸出:parent的getKind()方法被調(diào)用了
}
}
??1.同名的實(shí)例方法被覆蓋 ,同名的靜態(tài)方法被隱藏 ,child類的getName實(shí)例方法覆蓋 了parent的getName實(shí)例方法,chind的getKind方法隱藏 了parent類的getKind方法
??2.隱藏 和覆蓋 的區(qū)別在于,子類對(duì)象轉(zhuǎn)換成父類對(duì)象后,能夠訪問(wèn)父類被隱藏 的變量和方法,而不能訪問(wèn)父類被覆蓋 的方法
??3.如果需要訪問(wèn)父類被隱藏 的實(shí)例變量,加上super就好了,比如訪問(wèn)父類的name,寫上super.name就好了
?
?
四、Java強(qiáng)類型
代碼:
Java代碼
1???????? public class Type {??
2???????? ??
3???????? ????public static void main(String[] args) {??
4???????? ????????double i = 5.0;??
5???????? ????????double j = 1 / 4 + 3 / 4 + i + 12 / 6.0 + 3 / 4 + 1 / 4;??
6???????? ????????System.out.println(j);??
7???????? ????}??
8???????? ??
9???????? }?
?
?
結(jié)果:
7.0
?
分析:
Java 是強(qiáng)類型的 strongly type,它支持8 種基本數(shù)據(jù)類型。通過(guò)對(duì)這些基本數(shù)據(jù)類型用法的嚴(yán)格檢查 Java 編譯器能夠及時(shí)地在開(kāi)發(fā)過(guò)程中捕捉到許多簡(jiǎn)單細(xì)微的錯(cuò)誤。基本數(shù)據(jù)類型的轉(zhuǎn)換可以隱性地發(fā)生,所以轉(zhuǎn)換時(shí)會(huì)有精度損失。由于1/4和3/4發(fā)生隱性類型轉(zhuǎn)換,精度損失,不會(huì)生成0.25和0.75,所以有分號(hào)的數(shù)都為0。
?
五、假構(gòu)造函數(shù)
代碼:
Java代碼
1???????? public class Constructor {??
2???????? ??
3???????? ????private int a, b, c;??
4???????? ??
5???????? ????public void Constructor() {??
6???????? ????????a = 3;??
7???????? ????????b = 5;??
8???????? ????????c = a + b;??
9???????? ????}??
10???? ??
11???? ????public void test() {??
12???? ????????System.out.println("The value of c :" + c);??
13???? ????} ??
14???? ??
15???? ????public static void main(String[] args) {??
16???? ????????Constructor c = new Constructor();??
17???? ????????c.test();??
18???? ????}??
19???? }?
?
?
結(jié)果:
The value of c :0
?
分析:
public void Constructor()并不是一個(gè)真正的構(gòu)造函數(shù),而是一個(gè)方法。所以c的值為默認(rèn)值0.
?
?
六、提前引用
代碼:
Java代碼
1???????? public class ForwardReference {??
2???????? ??
3???????? ????static int first = test();??
4???????? ????static int second = 2;??
5???????? ??
6???????? ????static int test() {??
7???????? ????????return second;??
8???????? ????}??
9???????? ??
10???? ????public static void main(String[] args) {??
11???? ????????System.out.println("first = " + first);??
12???? ????}??
13???? ??
14???? }?
?
?
結(jié)果:
first = 0
?
分析:
由于在初始化second之前test方法就訪問(wèn)了它,那么方法得到的是second的默認(rèn)值,即 0。 因此輸出結(jié)果first= 0,而不是2。假如你使用方法調(diào)用來(lái)初始化靜態(tài)變量,那么你必須保證 這些方法并不依賴于在它們之后聲明的其它靜態(tài)變量。靜態(tài)變量以及靜態(tài)初始化塊是在類被加載進(jìn) JVM 時(shí)執(zhí)行初始化操作的。Java 語(yǔ)言規(guī)范8.5節(jié)指出“靜態(tài)初始化塊和靜態(tài)變量是按照其在代碼中出現(xiàn)的順序依次執(zhí)行初始化操作的,而不能在類變量聲明出現(xiàn)之前就引用它”。
?
?
七、對(duì)象引用
代碼:
Java代碼
1???????? public class TestRef {??
2???????? ??
3???????? ????public static void main(String[] args) {??
4???????? ????????StringBuffer a = new StringBuffer("a");??
5???????? ????????StringBuffer b = new StringBuffer("b");??
6???????? ????????append(a, b);??
7???????? ????????System.out.println(a.toString() + "," + b.toString());??
8???????? ????????b = a;??
9???????? ????????System.out.println(a.toString() + "," + b.toString());??
10???? ????}??
11???? ??
12???? ????public static void append(StringBuffer a, StringBuffer b) {??
13???? ????????a.append(b);??
14???? ????????b = a;??
15???? ????}??
16???? }?
?
?
結(jié)果:
ab,b
ab,ab
?
分析:
大家來(lái)分析一下這題,我還沒(méi)有完全理解。
?我的分析,可能是錯(cuò)的,哈哈,算是拋磚引玉。
1.a.append(b);-->ab 。因?yàn)閍是引用,所以調(diào)用a的方法,相當(dāng)于直接調(diào)用jvm中的a,所做的append也相當(dāng)于直接在對(duì)象上操作,生效。
2.append方法中第一次b=a,-->b。因?yàn)閍,b都為main方法內(nèi)局部變量,跨append方法作用域b對(duì)a的引用不生效。
3.main方法中第二次b=a,-->ab。因?yàn)樵谕蛔饔糜蚍椒ㄖ?#xff0c;b對(duì)a的引用生效,。
轉(zhuǎn)載于:https://www.cnblogs.com/caogang/p/4378639.html
總結(jié)
以上是生活随笔為你收集整理的Java容易搞错的知识点的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: 错误记录,找不到sqlite dll
- 下一篇: KindEditor 4.1.10 (2