您好,登錄后才能下訂單哦!
這篇文章將為大家詳細講解有關java基礎之關鍵字的示例分析,小編覺得挺實用的,因此分享給大家做個參考,希望大家閱讀完這篇文章后可以有所收獲。
在講解static定義屬性操作之前,首先編寫如下一道程序。
現在定義一個表示中國人的操作類,所有人所在的國家為中國。
class Person{ private String name; private int age; String country = "中國"; public Person(String name,int age){ this.name = name; this.age = age; } public String getInfo(){ return "姓名:"+this.name+" "+"年齡:"+this.age+" "+"國家:"+country; } } public class TestDemo1{ public static void main(String args[]){ Person per1 = new Person("張三",30); Person per2 = new Person("李四",40); Person per3 = new Person("王五",50); System.out.println(per1.getInfo()); System.out.println(per2.getInfo()); System.out.println(per2.getInfo()); } }
很明顯,現在不管有多少個Person對象他的屬性country的內容都是相同的,如果這時中國改名了,那么所有Person類的country屬性都好更改,這樣的話太過繁瑣。
現在可以發現這樣的問題:
1、country屬性應該是一個公共的內容,但上面的代碼是將其分配給每一個對象;
2、對country屬性維護的時候要考慮的對象太多了,不便于維護。
所以如果想將country與普通屬性相區分,并表示公共的概念,則應該使用static關鍵字完成。
class Person{ private String name; private int age; static String country = "中國"; public Person(String name,int age){ this.name = name; this.age = age; } public String getInfo(){ return "姓名:"+this.name+" "+"年齡:"+this.age+" "+"國家:"+country; } } public class TestDemo1{ public static void main(String args[]){ Person per1 = new Person("張三",30); Person per2 = new Person("李四",40); Person per3 = new Person("王五",50); per1.country = "美國"; System.out.println(per1.getInfo()); System.out.println(per2.getInfo()); System.out.println(per2.getInfo()); } }
那么現在對一個對象的屬性country進行修改就一定會影響到其他對象的country屬性,但是這里有個問題既然使用了static定義的屬性表示一個公共屬性,那么如果現在又一個對象進行修改是不合適的,應該有所有對象的集合的最大代表,就是類。即:static屬性最好的調用,是通過“類名稱.static屬性”的方式來完成。
Person.country = “美國”; //類名稱.static屬性
通過本程序,就因該清楚一下幾點:
1.使用static定義的屬性不在堆內存之中保存,保存在全局數據區;
2.使用static定義的屬性表示類屬性,類屬性可以由類型名稱直接進行調用;
3.static屬性雖然定義在類之中,但是其可以在沒有實例化對象的時候進行調用(普通屬性保存在堆內存之中,static屬性保存在全局數據區)
在以后的開發之中,首先想到的不是static屬性,而是普通屬性。
class Person{ private String name; private int age; //static String country = "中國"; private static String country = "中國"; public Person(String name,int age){ this.name = name; this.age = age; } //無法從靜態上下文中引用非靜態 變量 this //靜態方法中沒有辦法使用this變量 public static void setCountry(String c){ country = c; } public static String getCountry(){ return country; } public String getInfo(){ return "姓名:"+this.name+" "+"年齡:"+this.age+" "+"城市:"+country; } } public class TestDemo1{ public static void main(String args[]){ /*Person per1 = new Person("張三",30); Person per2 = new Person("李四",40); Person per3 = new Person("王五",50); per1.country = "美國"; System.out.println(per1.getInfo()); System.out.println(per2.getInfo()); System.out.println(per2.getInfo());*/ //調用的方法必須為靜態方法 //姓名:張三 年齡:30 城市:中國人民共和國 Person.setCountry("中國人民共和國");//沒有實例化對象產生 Person p1 = new Person("張三",30); System.out.println(p1.getInfo()); } }
以上的代碼如果單獨觀察都不難理解,主要都是由于static定義的特殊性所決定的,但是現在的類之中就比較熱鬧了,分成了兩類:static和非static,而對于方法的操作有如下兩定義:
1、static定義的方法不能調用非static的方法或是屬性;
2、非static定義的方法卻可以調用static方法和static屬性;
討論:為什么要有這樣的限制?
使用static定義的屬性和方法,可以在沒有實例化對象的時候調用,而非static方法必須在實例化對象之后才能調用。
在講解主方法之前,思考一下小小的區別:在之前講解Java方法定義格式的時候給過以下格式:如果一個方法在主類之中定義,并且有主方法直接調用的時候,前面必須有public static。
public class TestDemo{ public static void main(String args[]){ print(); //主方法直接調用 } public static void print(){ System.out.println("Hello World"); } }
按照之前所學習的概念來講,此時,表示的是一個static方法調用其他的static方法,但是如果這個時候的print方法上沒有static呢?所有非static方法幾乎都有一個特點:非方法要由實例化對象調用。
public class TestDemo{ public static void main(String args[]){ //Hello,World! new TestDemo().print(); //實例化對象調用非static方法 } public void print(){ System.out.println("Hello,World!"); } }
主方法的組成:
Public:表示一個訪問權限,表示公共
static:此方法由類名稱直接調用,執行類:Java 類名稱
void:主方法是一切的開始
main:系統規定的一個方法名稱,執行類的時候默認找到此名稱
String args[]:表示的是一些運行時參數,通過字符串接收
public class TestDemo2{ public static void main(String args[]){ for(int x = 0;x<args.length;x++){ System.out.println(args[x]); } } }
在實際的工作之中,使用static的原因有兩個:
希望可以在沒有實例化對象的時候可以輕松的執行類的某些操作
現在希望表示出數據共享的概念
統計一個類的實例化對象的個數
class Person{ private String name; static int num = 0; public Person(){ num++; } public void setName(String name){ this.name = name; } public String getName(){ return name; } } public class TestDemo3{ public static void main(String args[]){ Person per1 =new Person(); Person per2 =new Person(); Person per3 =new Person(); Person per4 =new Person(); System.out.println(Person.num); } }
public class PuTongDaiMaKuai{ public static void main(String args[]){ { //普通代碼塊 int x = 10; //局部變量 System.out.println("x ="+x); } int x = 100; //全局變量 System.out.println("x ="+x); } } //x =10 //x =100
class Person{ public Person(){ System.out.println("構造方法1") } { System.out.println("構造塊2"); } } public class PuTongDaiMaKuai{ public static void main(String args[]){ new Person(); new Person(); new Person(); } } /* 構造塊2 構造方法1 構造塊2 構造方法1 構造塊2 構造方法1 */
可以發現,構造塊優先于構造方法先執行,而且每當有一個新的實例化對象產生的時候,就會出現構造塊的執行。
靜態塊也是定義在類之中的,如果一個構造塊上使用了static關鍵字進行定義的話,那么就表示靜態塊,但是靜態塊要考慮兩種情況。
情況一:在非主類之中定義的靜態塊
class Person{ public Person(){ System.out.println("構造方法1"); } {//構造塊 System.out.println("構造塊2"); } static{//靜態塊 System.out.println("靜態塊3"); } } public class JingTaiKuai{ public static void main(String args[]){ new Person(); new Person(); new Person(); } }/*構造塊3構造塊2構造方法1構造塊2構造方法1構造塊2構造方法1*/
可以發現,靜態塊優先于構造塊,而且不管產生多少實例化對象,靜態塊只調用一次。
情況二:在主類中定義的靜態塊
public class TestDemo4{ static{ System.out.println("靜態塊"); } public static void main(String args[]){ System.out.println("主方法"); } } /* 靜態塊 主方法 */
在主類之中的靜態塊優先于主方法執行,那么既然靜態塊有這個特點,我們可以加以利用。
Person java:
class Person{ private String name; private int age; public void setName(String name){ this.name=name; } public void setAge(int age){ this.age=age; } public String getName(){ return this.name; } public int getAge(){ return this.age; } }
Student java:
class Student{ private String name; private int age; private String school; public void setName(String name){ this.name=name; } public void setAge(String age){ this.age=age; } public void setSchool(String school){ this.school=school; } public String getName(){ return name; } public int getAge(){ return age; } public String getSchool(){ return school; } }
可以發現里面有一大部分的內容已經重復了,但是現在拋開程序不談,學生和人的關系是:學生就是一個人,但是學生類比人類的定義更加嚴格,此時按照之前的概念肯定無法解決問題。
在Java中,如果想要明確的實現繼承的關系,則可以使用extends關鍵字完成,格式如下:
//但是在這里需要注意的是:子類又被稱為派生類; //父類也被稱為超類(super class) class 子類 extends 父類{}
class Person{ private String name; private int age; public void setName(String name){ this.name=name; } public void setAge(int age){ this.age=age; } public String getName(){ return this.name; } public int getAge(){ return this.age; } } class Student extends Person { } public class TestDemo5{ public static void main(String args[]){ Student stu = new Student(); stu.setName("張三"); System.out.println(stu.getName()); } }
通過程序的運行我可以發現,現在在子類之中,沒有定義任何方法,而是可以直接將父類中定義的操作繼續使用,所以在子類之中可以對父類進行重用,當然,子類也可以定義屬于自己的操作。
class Person{ private String name; private int age; public void setName(String name){ this.name=name; } public void setAge(int age){ this.age=age; } public String getName(){ return this.name; } public int getAge(){ return this.age; } } class Student extends Person{ private String school; public void setSchool(String school){ this.school = school; } public String getSchool(){ return this.school; } } public class TestDemo5{ public static void main(String args[]){ Student stu = new Student(); stu.setName("張三"); stu.setSchool("賓夕法尼亞大學"); //name = 張三,school = 賓夕法尼亞大學 System.out.println("name = " + stu.getName()+ ",school = " +stu.getSchool()); } }
通過以上程序了一發現,在開發語言之中,子類最基本的功能就是維持父類的原本操作,所以在程序語言之中并不會存在所謂的現實生活中的“敗家子”的概念。所以通過程序可以發現,繼承的功能就是對已有類功能的一種擴充。
1.在使用繼承關系后,子類對象在實例化對象前一定首先實例化父類構造方法,再調用子類的構造方法后子類再進行實例化操作。——現實生活之中,沒有老子,也絕對沒有后代,肯定是老子先出來,之后在輪到小的再出來,所以這樣的實例化方式非常吻合現實生活,如果在調用子類構造之前先去調用父類構造就可以證明是先實例化父類對象,而后再實例化子類對象。
2.Java中只允許單繼承,不允許多繼承。
3.在進行繼承的時候,子類會繼承父類所有的結構。所有的非私有操作采用顯式繼承的方式,所有的私有操作采用隱式繼承的方式。——按之前的開發所講,一個類中的全部內容肯定都被子類繼承,對于之前學生和人之間的操作,學生類也繼承了Person類中的name和age兩個屬性,這兩個屬性是間接繼承(隱式繼承),只能通過方法訪問
class Person{ public Person(){ System.out.println("父類構造"); } } class Student extends Person{ public Student(){ //既然是進行構造方法的調用,必須寫再首行位置 super();//此語句再無參時寫與不寫一樣 System.out.println("子類構造"); } } public class JiChengXing{ public static void main(String args[]){ new Student(); } }
而如果說現在父類中沒有明確的無參構造方法,這個時候就可以利用super()來指定要調用的父類構造參數。
class Person{ public Person(String name,int age){ System.out.println("父類構造"); } } class Student extends Person{ public Student(String name,int age,String school){ super(name,age); System.out.println("子類構造"); } } public class JiChengXing{ public static void main(String args[]){ new Student("Jokser",22,"北京大學"); } }
既然現在出現類繼承的關系,就出現類子類和父類之間的聯系,而在子類之中有可能定義了和父類完全相同的方法或屬性的名稱,這個時候就成為覆寫。
當子類定義了和父類在方法名稱、返回值類型、參數類型以及個數完全相同的方法的時候,成為方法的覆寫。
class A{ public void print(){ System.out.println("我是A的輸出方法"); } } class B extends A{ public void print(){ System.out.println("我是B的輸出方法"); } } public class TestDemo6{ public static void main(String args[]){ B b=new B(); //我是B的輸出方法 b.print(); } }
當我們一個類之中的方法被覆寫之后,如果實例化的是這個子類對象,則被調用的方法就是被覆寫過的方法。
但是在進行方法覆寫的時候有一個點需要注意:被子類所覆寫的方法不能擁有比父類更嚴格的訪問控制權限,對于訪問控制權限現在已經接觸過三種:private<default(不寫)<public。
如果此時父類的訪問權限是default權限,那么子類覆寫的時候只能是default或public權限,而如果父類的方法是public,那么子類之中的覆寫方法訪問權限只能是public。
提示:別沒事找事干!以后只要是方法都是public類型。屬性就寫private類型
當一個子類覆寫了一個父類方法的時候,那么在這種情況下,如果子類想要調用父類的被覆寫過的方法,則在方法前加上“super”。
class A{ public void print(){ System.out.println("我是A的輸出方法"); } } class B extends A{ public void print(){ //如果想在子類中調用父類的方法就在子類首行加super.方法名 super.print(); System.out.println("我是B的輸出方法"); } } public class TestDemo6{ public static void main(String args[]){ B b=new B(); //我是B的輸出方法 b.print(); } }
?面試題:重載和覆寫的區別?在進行重載的時候返回值是否可以不同?
區別 | 重載 | 覆寫 |
---|---|---|
英文單詞 | OverLoding | Overrider |
概念 | 方法名稱相同,參數類型以及個數不同 | 方法名稱、參數類型、參數個數必須全部相同 |
范圍 | 發生在一個類里面 | 發生在多個類里面 |
限制 | 沒有要求 | 被覆寫的方法不能有比父類更高的訪問控制權限 |
方法重載的時候返回類型是可以不同的,但是良好的設計要求是類型一致。
當一個子類定義了和父類重名的屬性名稱的時候,就表示屬性的覆蓋了。
class A{ String str = "Hello World"; } class B extends A{ int str = 100; public void print(){ System.out.println(this.str); System.out.println(super.str); } } public class FuXie{ public static void main(String args[]){ B b=new B(); //100 //Hello World b.print(); } }
這種操作幾乎沒有意義,因為從開發來講,屬性一定進行封裝,封裝之后就沒有覆蓋了。
區別 | this | super |
---|---|---|
定義 | 表示本類對象 | 表示父類對象 |
使用 | 本類操作:this()、this.屬性、this.方法 | super()、super.屬性、super.方法 |
調用構造方法 | 調用本類構造方法放在首行 | 子類調用父類構造放在首行 |
查找范圍 | 先從本類中,查找不到父類 | 直接由子類查找父類 |
特殊 | 表示當前對象 | 無 |
**要求:**現在要求定義一個整型數組的操作類,數組的大小由外部決定,用戶可以向數組之中增加數據,以及取得數組中的全部數據,也可以根據外部提供的數組的增長大小,在原本的數組之上擴充指定的容量,另外,在此類上派生兩個子類:
排序類(sortArray):取得數組內容是經過排序出來的結果;
反轉類(Fanzhuan):取得數組的內容是反轉出來的結果;
首先要完成的是定義父類,根本就不需要考慮子類。
class Array{ private int data[];//定義一個數組,數組大小由外部決定 private int foot = 0;//數組角標 //創建數組 public Array(int len){ if(len > 0){ this.data = new int [len];//開辟空間 }else{ this.data = new int [1]; } } //增加數組 public boolean add(int num){ if(this.foot >= data.length){ return false; }else{ this.data[this.foot ++] = num; return true; } } //輸出數組 public int[] getData(){ return this.data; } //動態擴充數組 public void inc(int num){ int [] newData = new int [this.data.length + num]; /* public static void arraycopy(Object src, src - 源數組。 int srcPos, srcPos - 源數組中的起始位置。 Object dest, dest - 目標數組。 int destPos, destPos - 目的地數據中的起始位置。 int length) length - 要復制的數組元素的數量。 */ System.arraycopy(this.data,0,newData,0,this.data.length); this.data = newData; } } //對數組進行排序操作 class sortArray extends Array{ public sortArray(int num){ super(num); } public int[] getData(){ java.util.Arrays.sort(super.getData()); return super.getData(); } } //數組內容翻轉 class Fanzhuan extends Array{ public Fanzhuan(int num){ super(num); } public int[] getData(){ int head = 0; int tail = super.getData().length - 1; int center = super.getData().length / 2; for(int i = 0 ; i < center ; i++,head++,tail--){ int temp = super.getData()[head]; super.getData()[head] = super.getData()[tail]; super.getData()[tail] = temp; } return super.getData(); } } public class Exam1{ public static void main(String args[]){ //Array arr = new Array(5); //sortArray arr = new sortArray(5); Fanzhuan arr = new Fanzhuan(5); System.out.println(arr.add(3)); System.out.println(arr.add(1)); System.out.println(arr.add(3)); System.out.println(arr.add(8)); System.out.println(arr.add(0)); arr.inc(3); System.out.println(arr.add(7)); System.out.println(arr.add(20)); System.out.println(arr.add(10)); int result[] = arr.getData(); for(int i = 0; i < result.length ; i++){ System.out.print(result[i]+"、"); } } }
在整個程序開發之中,可以明顯的感覺到,所有的操作都是圍繞著父類功能的擴充進行的,但是方法并沒有改變,所以在開發之中,父類的設計是最重要的,子類最好繼承或者說是覆寫覆寫操作,都是應該以父類的方法為主。
在Java中,final關鍵字表示的是一個終結器的概念,使用final可以定義類、方法、變量。
使用final定義的類不能有子類
final class A{ } class B extends A{ }
使用final定義的方法不能被子類所覆寫
final class A{ public final void print(){} } class B extends A{ public void print(){} }
使用final定義的變量,就表示常量,常量在定義的時候必須設置默認值,并且無法修改
final class A{ final String str = "hello world";//常量 public final void print(){ str = "你好"; //無法修改 } } public class Final{ public static void main(String args[]){ } }
而如果說現在使用了public static定義的常量,那么這個常量就成為全局常量。
public static final String STR = "hello,world";//全局常量
而對于以上final關鍵字的三個操作,只有全局常量的概念是被開發之中所使用的,像類或方法定義上使用的情況,幾乎不會再我們編程中出現。
關于“java基礎之關鍵字的示例分析”這篇文章就分享到這里了,希望以上內容可以對大家有一定的幫助,使各位可以學到更多知識,如果覺得文章不錯,請把它分享出去讓更多的人看到。
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。