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