JAVA基礎2

1、成員變量和局部變量

                    成員變量                           局部變量


作用範圍    在該類中                           在函數內
所在位置    堆中,new對象時產生         在棧中
初始值        0或者null或者false           隨機數,不初始化沒辦法使用


2、匿名對象
new Car().num = 5;
new Car().color = "red";
new Car().run();
//上面三個語句都是使用了匿名對象。但是注意了,三個是不同的對象,當執行完第一

//個語句後,這個對象就沒有引用了,所以變垃圾了。


3、構造函數和構造代碼塊

(1)如果沒定義構造函數,系統給你創建一個默認的 Person(){}
(2)如果定義了,系統就不會創建默認的了。
(3)構造函數在對象被創建的時候調用。

(4)構造代碼塊在創建對象時必然會調用,並且優先於構造函數

{
System.out.println("構造代碼塊");  //這裏就是構造代碼塊的定義
}


4、this關鍵字,那個對象調用該函數,this就是那個對象。

Person(int age){

this.age = age;

}

當本類裏的構造函數調用本類另外一個構造函數時,使用this();進行調用。

注意,this();必須是構造函數裏的第一行

Person(String name,int age)
{
this(age); 
this.name = name;
}


5、static關鍵字

(1)static的成員變量和成員函數都是隨着類的加載而加載的,生命週期最長。
    所謂的加載就是使用到這個類,比如 new Person();這個時候Person類就加載進內存
    還有Person.show();和在命令行中輸入java hello這三種情況會加載類進內存
            但是,Person p這個語句只是定義,這個時候Person類並沒有加載進內存

(2)static的變量是分配在數據段的

(3)static的成員優先於非static的成員存在

(4)靜態的方法裏不能調用非靜態的成員變量和方法

(5)非靜態的方法裏能調用靜態的和非靜態的成員變量和方法

(6)靜態方法裏不能出現this,super這樣的關鍵字,因爲靜態的本來就可以不需對象就能調用

(7)靜態的數據時屬於類的,而不屬於某一個對象的,所以類名. 就能調用


6、靜態代碼塊
//靜態代碼塊在類加載進內存的時候執行
//當我們在命令行輸入java StaticCode時,StaticCode類就加載進內存
//只有類加載的時候 靜態代碼塊才能執行,並不是說new多少個對象就執行多少次
//然後JVM纔開始調用main方法。
//輸出結果是: b a c
public class StaticCode
{
static
{
System.out.println("b");
}
public static void main(String[] args)
{
System.out.println("a");
Test test = null;   //這個時候沒有加載
new Test();   //這個時候Test類加載進內存
}
}
class Test
{
static
{
System.out.println("c");
}
}


7、JAVA內存分配圖



8、內存執行過程分析:
Person p = new Person("zhangsan",18);
(1)把Person類加載進內存
(2)如果有靜態代碼塊,則執行靜態代碼塊
(3)在堆內存裏開闢一塊空間,分配內存地址
(4)成員變量默認初始化,name=null,age=0;
(5)成員變量顯示初始化,name="lisi";
(6)構造代碼塊執行
(7)構造函數執行,name="zhangsan",age=18;
(8)把內存地址賦值給棧中的變量p


9、主函數
(1)靜態的原因是 JVM直接可以通過類名調用
(2)參數(String[] args) 對應 命令行java HelloWorld haha heihei   裏的 haha heihei


10、單例模式
(1)餓漢式,開發中用這種。
class SingleDemo{
//第一步,創建一個對象
private static SingleDemo single = new SingleDemo();
//第二步,構造函數私有化
private SingleDemo(){

}
//第三步,對外暴露獲取本類對象的方法
public static SingleDemo getInstance(){
return single;
}
}
(2)懶漢式(延遲加載的設計模式),此方式存在弊端,多線程時有可能出現多個對象的存在。
class SingleDemo{
//第一步,創建一個對象
private static SingleDemo single = null;
//第二步,構造函數私有化
private SingleDemo(){

}
//第三步,對外暴露獲取本類對象的方法
public static SingleDemo getInstance(){
if(single == null)
single = new SingleDemo();
return single;
}
}


11、繼承
class Parent
{
int num = 4;
}
class Child extends Parent
{
int num = 5;
void show(){
int num = 6;
System.out.println(num);  
}
}
class Demo{
public static void main(String[] args){
Child c = new Child();
//就近原則,結果是6。如果沒有局部變量,那麼結果是5。
//this.num 那結果就是5。
//super.num 那結果是4。
//this是當前的對象
//super不是父類的對象,而是父類的內存空間。
c.show();
}
}


12、重寫
(1)重寫的方法中,子類的權限必須大於等於父類的該方法的權限
(2)靜態只能覆蓋靜態,因爲優先於對象存在。


13、繼承中構造函數特點:子類的構造函數裏,第一行有一個隱式的super()調用父類的構造函數。如果父類裏沒有默認的構造函數,而子類中的構造函數也沒有顯式調用,那必然會報錯。


14、final關鍵字
final修飾的類不能被繼承
final修飾的方法不能被重寫
final修飾的變量(成員變量和局部變量)是常量,不能再賦值。


15、abstract抽象類
(1)聲明爲抽象方法,那麼該類就必須爲抽象類。
(2)抽象類不能new對象,誰繼承了抽象類,必須重寫。
(3)當然,如果一個抽象類繼承了一個抽象類,那麼該抽象類不用重寫抽象方法,但是隻要後面的不是抽象類的 繼承了該抽象類,那麼就要重寫裏面的所有抽象方法。
abstract class Person{
abstract void show();
}



16、接口interface,其就是一個特殊的抽象類
interface Inter
{
public static final int a = 5;     //接口裏的變量都是public static final修飾的
public abstract void show();   //接口裏所有的抽象方法都是public修飾的
public abstract void display();
}  //同樣,實現接口,就要重寫裏面的所有的抽象方法。
(1)類與類之間是繼承關係。
(2)類與接口之間是實現的關係。
interface A
{
public abstract void show();
}
interface B
{
public abstract void display();
}
class C
{
public void func(){}
}
class D extends C implements A,B  //多實現,重寫裏面的所有抽象方法
{
public void show(){}
public void display(){}
}
(3)接口與接口之間是繼承關係(可以多繼承)。
interface A
{
}
interface B
{
}
interface C extends A,B  //接口之間的多繼承
{
}


17、多態
成立條件:
(1)有繼承關係
(2)方法重寫
(3)父類引用指向子類對象
abstract class A
{
abstract void eat();
}
class B extends A
{
public void eat(){
System.out.println("B");
}
public void show(){
System.out.println("B show");
}
}
class C extends A
{
public void eat(){
System.out.println("C");
}
public void display(){
System.out.println("C display");
}
}
public class Test
{
public static void main(String[] args){
A a1 = new B(); //多態,向上轉型
A a2 = new C();
a1.eat(); //調用B裏的eat方法
a2.eat(); //調用C裏的eat方法
a1.show(); //不行,show是子類特有的方法,a1是A類型,所以看不到該方法
a2.display(); //不行,理由同上
//要想調用子類裏特有的方法,怎麼辦?
B b = (B)a1;  //向下轉型
b.show(); //這樣就可以調用了,因爲現在b是B類的對象
}
}


18、多態的特點
(1)成員變量,看左邊,左邊有,那就執行。
class A{
int num = 5;
}
class B extends A{
int num = 6;
}
class Demo{
public static void main(String[] args){
A a = new B();
a.num; //結果是 5
}
}
(2)成員函數,還是看左邊,執行的的時候如果發現show方法重寫了,就會執行子類show的方法
class A{
void show(){
System.out.println("A run...");
}
}
class B extends A{
void show(){
System.out.println("B run...");
}
}
class Demo{
public static void main(String[] args){
A a = new B();
a.show();  //結果是 B run
}
}
(3)靜態成員,還是看左邊,因爲很對象沒有關係。
class A{
static void show(){
System.out.println("A run...");
}
}
class B extends A{
static void show(){
System.out.println("B run...");
}
}
class Demo{
public static void main(String[] args){
A a = new B();
a.show();  //結果是 A run
}
}

19、instanceof關鍵字
abstract class Animal
{
abstract void eat();
}
class Cat extends Animal
{
void eat(){
System.out.println("cat eat");
}
}
class Dog extends Animal
{
void eat(){
System.out.println("dog eat");
}
}
public class Test
{
public static void main(String[] args)
{
Animal a1 = new Cat(); //這句話可理解爲:a1實際是一隻貓,我們叫它爲動物
Animal a2 = new Dog();
Dog d = new Dog();
System.out.println(a1 instanceof Cat);  //true     a1是一種貓嗎?
System.out.println(a1 instanceof Animal); //true   a1是一種動物嗎?
System.out.println(a1 instanceof Dog); //false
System.out.println(d instanceof Dog);  //true
System.out.println(d instanceof Animal); //true     d是一種動物嗎?
}
}


20、equals的用法
class Demo
{
String name;
Demo(String name){
this.name = name;
}
public boolean equals(Object obj){  //重寫Object類裏的equals方法
if(obj instanceof Demo){    
Demo d = (Demo)obj;   //向下轉型,獲得Demo裏的成員變量name
return this.name == d.name;
}else{
return false;
}
}
}
public class EqualsDemo
{
public static void main(String[] args){
Demo d1 = new Demo("hello");
Demo d2 = new Demo("world");
System.out.println(d1.equals(d2));  //false
}
}


21、getClass(),獲得該對象所屬的字節碼對應的類文件對象。
通過這個對象就能獲取這類的一些相關信息,比如成員變量,方法等。


22、面試題:
//結果爲false
//首先在常量區裏有個" abc "字符串,把trim運算後的結果賦值給s1,
//注意了,此時常量區裏還沒有"abc",只有" abc "
//當出現另外一個常量"abc"時,他們明顯代表的是不同的常量
public class Test
{
public static void main(String[] args){
String s1 = " abc ".trim();
System.out.println(s1 == "abc");  
}
}


23、內部類
(1)內部類可直接訪問外部類的所有成員,包括私有的成員變量和成員方法
(2)外部類不能直接訪問內部類的成員,若想訪問,必須通過對象。通過對象也能訪問到內部類的私有成員。
(3)其他類訪問內部類的方法,Outer.Inner inner = new Outer().new Inner();
(4)Inner類是可以被private修飾的,因爲它出現在Outer類的成員位置
(5)假如有外部類的成員變量x=5,內部類的成員變量x=6,內部類的function方法的
局部變量x=7。那麼在function裏執行System.out.println(x)是輸出7
執行System.out.println(this.x)是輸出6
執行System.out.println(Outer.this.x)是輸出5
從此也可以得到一個結果,內部類可以直接訪問外部類的成員,其實就是省略
寫Outer.this.x
class Outer
{
int x = 5;
class Inner
{
void function(){
System.out.println(x);  //對應於上面的(1)
}
}
void show(){              
Inner in = new Inner();  //對應於上面的(2)
in.function();           
}
}
public class Test
{
public static void main(String[] args){
Outer.Inner inner = new Outer().new Inner(); //對應於上面的(3)
inner.function();   
}
}
/******************************************************************************/
靜態內部類
(1)由於內部類在外部類裏的位置是成員,所以可以用static來修飾
(2)靜態內部類只能訪問外部類裏靜態的成員
(3)其他類訪問靜態內部類的方式Outer.Inner in = new Outer.Inner();
(4)靜態內部類裏的成員可以是靜態的,也可以是非靜態的
(5)非靜態的內部類裏的成員只能是非靜態的。
class Outer
{
private static int x = 5;
static class Inner
{
void function(){
System.out.println(x);
}
}
}
public class Test
{
public static void main(String[] args){
Outer.Inner in = new Outer.Inner();
in.function();
}
}
/******************************************************************************/
內部類出現在局部變量的位置
(1)同樣可以直接訪問外部類的成員
(2)要想訪問所在方法裏的局部變量,只能加final來修飾
(3)此內部類不能被private static等關鍵字修飾,因爲是局部變量
class Outer
{
int x = 5;
void show(){
int y = 6;
class Inner
{
void function(){
System.out.println(x); //如(1)所說,沒問題
System.out.println(y); //如(2)所說,有問題,y必須是final
}
}
new Inner().function();
}
}
public class Test
{
public static void main(String[] args){
new Outer().show();
}
}


24、匿名內部類
abstract class Demo
{
abstract void show();
}
class Outer
{
int x = 5;
void function(){
new Demo(){      //可以理解爲,有一個類繼承於Demo,創建該類的對象。
void show(){  //這個子類重寫了父類的抽象方法
System.out.println(x);
}
}.show(); //執行裏面的方法
}
}


25、修飾符的訪問權限
------------------------------------------------------------ 
                        類內部     package內       子類         其他 
public           允許         允許         允許         允許 
protected        允許         允許         允許        不允許 
default          允許         允許        不允許       不允許 
private          允許        不允許       不允許       不允許 
------------------------------------------------------------- 


26、異常
try{

}catch(Exception e){
//異常時執行
}finally{
//一定會執行
}
throws關鍵字:如果一個函數使用該關鍵字,那表明往外拋異常,當調用該函數的
時候,必須捕獲處理。當然你也如果不想處理可以繼續往外拋
throw關鍵字:自定義異常,相當於用這個關鍵字能產生一個異常
class MyException extends Exception
{


}
class Demo
{
int show(int a) throws MyException{ //然後往外拋纔算是完成一個自定義的異常
if(a == 0){
throw new MyException(); //自定義產生一個異常
}else{
return a;
}
}
}
//注意:RunTimeException可以不用try catch,也可以不用throws


27、包
package pack;
public class PackageDemo
{
public static void main(String[] args){
System.out.println("hello world");
}
}
dos命令窗口:
E:\java_project> javac -d . PackageDemo.java  ==>當前目錄即(E:\java_project目錄)
下生成了一個整體,這個整體是文件夾名字爲pack,裏面有一個PackageDemo.class文件


E:\java_project> java pack.PackageDemo  ==>執行,要寫全稱
//注意,如果不想在當前目錄下生成class文件,那麼可以在-d後指定自己設定的路徑
//但是執行的時候就要主要classpath的問題了


28、import關鍵字
爲了簡化b.packageB test = new b.packageB();寫法
import b.packageB;
packageB test = new packageB();


29、打包JAR文件
jar包:打包命令 jar -cvf haha.jar a b   //把a b目錄下的class文件打包爲haha.jar
jar包的使用,直接將jar包的路徑設到classpath裏
比如在C盤的根目錄下有一個haha.jar包
set classpath=c:\haha.jar   就可以了

發佈了41 篇原創文章 · 獲贊 0 · 訪問量 3萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章