1. 程式人生 > >java初學 面向物件二 static關鍵字 封裝、繼承和多型

java初學 面向物件二 static關鍵字 封裝、繼承和多型

  1. static關鍵字

1:如果沒有static會怎樣?

1:定義Person類

1:姓名、年齡、國籍,說話行為

2:多個構造,過載形式體現

2:中國人的國籍都是確定的

1:國籍可以進行顯示初始化

class Person {

String name;

int age;

String gender;

String country = "CN";

 

Person() {

 

}

 

Person(String name, int age, String gender, String country) {

this.name = name;

this.age = age;

this.gender = gender;

this.country = country;

}

 

void speak() {

System.out.println("國籍:" + country + " 姓名:" + name + " 性別:" + gender + " 年齡:" + age + " 哈哈!!!");

}

 

}

 

3:new Person 物件

1:分析記憶體

2:每個物件都維護例項變數國籍也是。

public class PersonDemo {

public static void main(String[] args) {

Person p1 = new Person("jack", 20, "男");

p1.speak();

 

Person p2 = new Person("rose", 18, "女");

p2.speak();

}

}

 

 

4:記憶體分析

1:棧,堆、共享區

2:Demo.class載入近共享區

1:Demo類的main方法進棧

2:Person p1=new Person();

1:Person.class 載入進方法區

2:堆記憶體開闢空間,例項變數進行預設初始化,顯示初始化。

3:記憶體地址傳給變數p1,棧和堆建立連線

3:person p2=new Person();

1:堆記憶體開闢空間,例項變數進行預設初始化,顯示初始化。

2:記憶體地址傳給變數p2,棧和堆建立連線

4:如果建立多個Person物件發現問題

1:每個物件都維護有國籍。

5:解決問題,記憶體優化

1:為了讓所有Person物件都共享一個country ,可以嘗試將country放入共享區。

2:country變數如何放入共享區?物件如何訪問?

1:使用static

2:static

1:為了實現物件之間重複屬性的資料共享

3:static使用

1:主要用於修飾類的成員

1:成員變數

1:非靜態成員變數:需要建立物件來訪問

2:靜態成員變數:使用類名直接呼叫,也可以通過物件訪問

public static void main(String[] args) {

 

//訪問靜態成員

//直接通過類名來呼叫

String country=Person.country;

System.out.println(country);

 

//通過物件.成員的形式訪問

Person p1 = new Person("jack", 20, "男");

p1.country="US";

p1.speak();

 

}

class Person {

String name;

int age;

String gender;

//static 修飾成員變數

static String country = "CN";

 

Person() {

 

}

 

Person(String name, int age, String gender) {

this.name = name;

this.age = age;

this.gender = gender;

 

}

 

void speak() {

 

System.out.println("國籍:" + country + " 姓名:" + name + " 性別:" + gender

+ " 年齡:" + age + " 哈哈!!!");

}

 

}

 

2:成員方法

可以使用類名直接呼叫

1:靜態函式:

1:靜態函式中不能訪問非靜態成員變數,只能訪問靜態變數。

2:靜態方法不可以定義this,super關鍵字.

3:因為靜態優先於物件存在.靜態方法中更不可以出現this

 2:非靜態函式:非靜態函式中可以訪問靜態成員變數

class Person {

String name;

int age;

String gender;

//static 修飾成員變數

static String country = "CN";

 

Person() {

 

}

 

Person(String name, int age, String gender) {

this.name = name;

this.age = age;

this.gender = gender;

 

}

//非靜態方法

void speak() {

//非靜態方法可以訪問靜態成員

System.out.println("國籍:" + country );

 

System.out.println("國籍:" + country + " 姓名:" + name + " 性別:" + gender

+ " 年齡:" + age + " 哈哈!!!");

 

}

//靜態方法

static void run(){

//靜態方法只能訪問靜態成員變數。

System.out.println("國籍:"+country);

 

//靜態方法訪問非靜態成員變數,編譯報錯。

System.out.println(" 姓名:" + name);

 

//靜態方法中不可以出現this,編譯報錯

this.speak();

}

}

 

2:細節:

1:靜態函式中不能使用非靜態變數

2:非靜態函式可以訪問靜態變數

3:為什麼靜態函式中不能訪問非靜態成員

1:static修飾的成員在共享區中。優先於物件存在

2:驗證

1:使用靜態程式碼塊驗證

1:靜態程式碼塊

static{

靜態程式碼塊執行語句;

}

 1:靜態程式碼塊特點

隨著類的載入而載入。只執行一次,優先於主函式。用於給類進行初始化。

 

public class PersonDemo {

public static void main(String[] args) {

 

// 訪問靜態成員

// 直接通過類名來呼叫

String country = Person.country;

System.out.println(country);

 

// 通過物件.成員的形式訪問

Person p1 = new Person("jack", 20, "男");

p1.country = "US";

p1.speak();

 

}

}

 

 

class Person {

String name;

int age;

String gender;

// static 修飾成員變數

static String country = "CN";

static {

System.out.println("這是靜態程式碼塊");

}

 

{

System.out.println("這是構造程式碼塊");

}

 

Person() {

System.out.println("無引數構造");

}

 

Person(String name, int age, String gender) {

this.name = name;

this.age = age;

this.gender = gender;

System.out.println(" 有引數構造");

 

}

 

// 非靜態方法

void speak() {

// 非靜態方法可以訪問靜態成員

System.out.println("國籍:" + country);

 

System.out.println("國籍:" + country + " 姓名:" + name + " 性別:" + gender

+ " 年齡:" + age + " 哈哈!!!");

// 非靜態方法可以呼叫靜態方法。

run();

}

 

// 靜態方法

static void run() {

// 靜態方法只能訪問靜態成員變數。

System.out.println("國籍:" + country);

}

}

 

 

   

4:static特點

1 隨著類的載入而載入,靜態會隨著類的載入而載入,隨著類的消失而消失。說明它的生命週期很長。

       2 優先於物件存在。-->靜態是先存在,物件是後存在。

      3 被所有例項(物件)所共享。

       4 可以直接被類名呼叫

5:靜態變數(類變數)和例項變數的區別:

     1存放位置

         1:類變數隨著類的載入而載入存在於方法區中.

          2:例項變數隨著物件的建立而存在於堆記憶體中.

     2生命週期

          1:類變數生命週期最長,隨著類的消失而消失.

          2:例項變數生命週期隨著物件的消失而消失.

6:靜態優缺點

1: 優點:對物件的共享資料進行單獨空間的儲存,節省空間 例如Person 都有

國籍。該資料可以共享可以被類名調

2:缺點:生命週期過長

           訪問出現侷限性。(靜態只能訪問靜態)

7: 什麼時候定義靜態變數

1:靜態變數(類變數)當物件中出現共享資料

  例如:學生的學校名稱。學校名稱可以共享

        物件的資料要定義為非靜態的存放在對記憶體中(學生的姓名,學生的年齡)

8:什麼時候定義靜態函式

如果功能內部沒有訪問到非靜態資料(物件的特有資料。那麼該功能就可以定義為靜態)

9:靜態的應用

自定義陣列工具類

/*

定義陣列工具類

1:定義一個遍歷陣列的函式

2:定義一個求陣列和的功能函式  1. 遍歷  2. 兩兩相加

3:定義一個獲取陣列最大值的功能函式

4:定義一個獲取陣列最大值角標的功能函式

5:定義一個返回指定數在指定陣列中包含的角標的功能函式

6:定義一個可以用於排序int陣列的函式

1:冒泡

2:選擇

 

定義自己的工具類

 

 */

class Arrays {

 

private Arrays() {

 

}

 

// 1:定義一個遍歷陣列的函式

public static void print(int[] arr) {

for (int x = 0; x < arr.length; x++) {

if (x != (arr.length - 1)) {

System.out.print(arr[x] + ",");

} else {

System.out.print(arr[x]);

}

 

}

}

 

// 2:定義一個求陣列和的功能函式

public static int getSum(int[] arr) {

int sum = 0;

for (int x = 0; x < arr.length; x++) {

sum += arr[x];

}

return sum;

}

 

// 3:定義一個獲取陣列最大值的功能函式

public static int getMax(int[] arr) {

int max = 0;

for (int x = 0; x < arr.length; x++) {

if (arr[max] < arr[x]) {

max = x;

}

}

return arr[max];

}

 

// 4:定義一個獲取陣列最大值角標的功能函式

public static int getIndexMax(int[] arr) {

int max = 0;

for (int x = 0; x < arr.length; x++) {

if (arr[max] < arr[x]) {

max = x;

}

}

return max;

}

 

// 5:定義一個返回 指定數在指定陣列中包含的角標的功能函式

public static int getIndex(int[] arr, int src) {

int index = -1;

for (int x = 0; x < arr.length; x++) {

if (arr[x] == src) {

index = x;

}

}

return index;

}

 

// 冒泡

public static void test(int[] arr) {

for (int x = 0; x < arr.length - 1; x++) {

if (arr[x] > arr[x + 1]) {

int temp = arr[x + 1];

arr[x + 1] = arr[x];

arr[x] = temp;

 

}

}

}

 

// 選擇排序

public static void selectSort(int[] arr) {

for (int x = 0; x < arr.length - 1; x++) {

for (int y = 1 + x; y < arr.length; y++) {

if (arr[x] > arr[y]) {

int temp = arr[y];

arr[y] = arr[x];

arr[x] = temp;

}

}

}

}

 

// 7:定義一個可以將整數陣列進行反序的功能函式。

public static void reverseSort(int[] arr) {

int start = 0;

int end = arr.length - 1;

for (int x = 0; x < arr.length; x++) {

if (start < end) {

int tem = arr[start];

arr[start] = arr[end];

arr[end] = tem;

}

start++;

end--;

}

 

}

 

// 折半查詢

public static int halfSearch(int key, int[] arr) {

int min = 0;

int max = arr.length - 1;

int mid = 0;

 

while (min < max) {

mid = (min + max) / 2;

if (key > arr[mid]) {

min = mid + 1;

} else if (key < arr[mid]) {

max = mid - 1;

} else {

return mid;

}

}

return -1;

}

 

}

 

class Demo6 {

 

public static void main(String[] args) {

int[] arr = { 3, 4, 5, 2, 3, 7, 4 };

Arrays.print(arr);

System.out.println();

Arrays.selectSort(arr);

Arrays.print(arr);

 

}

}

 

練習:統計建立物件的人數

class Person

{

public String name;

public int age;

static public long  all_count;

public Person(){

    all_count++;

}

public Person( String name , int age ){

    all_count++;

this.name = name;

this.age = age;

}

// 統計人數的函式

public long getCount(){

  return all_count;

}

// 應該具備找同齡人的功能

public boolean isSameAge( Person p1 ){

  return this.age == p1.age;

}

}

class Demo9

{

public static void main(String[] args)

{

Person p1 = new Person( "jame" ,  34 );

Person p2 = new Person( "lucy" ,  34 );

 

Person p3 = new Person( "lili" ,  34 );

Person p4 = new Person();

System.out.println( p1.getCount() + " " + p2.getCount() + "  " + p3.getCount()  );

System.out.println( p1.isSameAge( p2 ) );

System.out.println( p1.isSameAge( p3 ) );

}

}

 

 

 

 

    1. main方法詳解

主函式是靜態的

public static void main(String[] args){

      

}

主函式是什麼:主函式是一個特殊的函式,作為程式的入口,可以被jvm識別。

主函式的定義:

       public :代表該函式的訪問許可權是最大的。

       static :代表主函式隨著類的載入,就已經存在了。

       void:  主函式沒有具體的返回值

       main : 不是關鍵字,是一個特殊的單詞可以被jvm識別。

       (String[] args) 函式的引數,引數型別是一個數組,該陣列中的元素是字串。字串型別的陣列。

       主函式的格式是固定的:jvm能夠識別

       jvm在呼叫函式是,傳入的是new String[0];

可以在dos視窗中執行 java  Demo5   hello  world   給類Demo5的main方法傳遞2個引數,引數與引數之間通過空格隔開。

class Demo5 {

 

public static void main(String[] args) {

 

// 獲取String[] args 陣列長度

System.out.println(args.length);

 

// 變數args陣列

for (int x = 0; x < args.length; x++) {

System.out.println(args[x]);

}

}

 

}

 

class MainTest {

 

public static void main(String[] args) {

// 字串陣列

String[] arr = { "good", "study", "java" };

 

// 呼叫Demo5類的main方法,傳遞引數。

Demo5.main(arr);

 

}

}

 

  1. 單例設計模式

 

一些人總結出來用來解決特定問題的固定的解決方案。

 

解決一個類在記憶體中只存在一個物件,想要保證物件的唯一。

1 為了避免其他程式過多的建立該類物件。禁止其他程式建立該類物件。

2 為了其他程式可以訪問該類物件,在本類中自定義一個物件。

3 方便其他程式對自定義類的物件的訪問,對外提供一些訪問方式。

 程式碼:

1將建構函式私有化

2在類中建立一個私有的本類物件

3提供一個用類名呼叫的公有方法獲取該物件。

class Single {

 

private static Single s = new Single(); // 惡漢式

 

private Single() {

 

}

 

public static Single getInstance() {

return s;

}

}

 

class Single2 {

private static Single2 s = null; // 懶漢

 

private Single2() {

 

}

 

public static Single2 getInstance() {

if (s == null) {

s = new Single2();

}

return s;

}

}

  1. 繼承
    1. 類和類之間的常見關係。

1:既然繼承是描述類和類之間的關係,就需要先來了解類和類之間的常見關係

      1. 現實生活的整體與部分

舉例說明

1:現實生活

1:學生   是人  

2:狗     是動物

3:球隊 包含 球員 整體與部分的關係,部分可以刪除和增加

4:筆記本包含 cpu 整體與部分的關係,部分不可以刪除和增加

5:航母編隊 包含(航母 護衛艦 驅逐艦 艦載機 核潛艇)

      1. java中的類與類關係

java中的類關係

1:is a 關係 (學生是人)

2:has a 整體與部分

class Person{

String name;

int age;

Address add;

 

Person(){

 

}

Person(String name,int age,Address add){

 

this.name=name;

this.age=age;

this.add=add;

 

}

 

void speak(){

System.out.println("姓名:"+name+" 年齡:"+age+" "+add.print());

}

}

class Address{

String country;

String city;

String street;

 

Address(){

 

}

Address(String country,String city,String street){

this.country=country;

this.city=city;

this.street=street;

}

 

String print(){

return "地址:"+country+" "+"城市:"+city+"  街道;"+street;

}

}

class Demo3{

 

public static void main(String[] args){

 

Address add=new Address("中國","廣州","棠東東路");

Person p=new Person("jack",27,add);

p.speak();

 

 

System.out.println();

      }

}

 

 

    1. 繼承

1:描述一個學生類

1:姓名年齡學號屬性,學習的方法

2:描述一個工人類

1:姓名年齡工號屬性,工作的方法

3:描述一個人類

1:姓名年齡屬性,說話的方法。

4:發現學生類和人類天生有著聯絡,學生和工人都是人。所以人有的屬性和行為學生和工人都會有。出現類程式碼重複

class Person {

String name;

int age;

 

// 靜態變數(類變數)物件和物件之間的程式碼重複使用靜態變數

static String country = "CN";

 

Person() {

 

}

 

void speak() {

System.out.println(name + ":哈哈,我是人!!!");

}

 

}

 

// 讓學生類和人類產生關係,發現學生is a 人,就可以使用繼承

class Student {

 

String name;

int age;

 

Student() {

 

}

 

void study() {

System.out.println("姓名:" + name + "年紀:" + age + ":好好學習");

}

}

 

class Worker {

String name;

int age;

 

void work() {

System.out.println(name + ":好好工作,好好掙錢。");

}

 

}

 

class Demo1 {

 

public static void main(String[] args) {

Student s = new Student();

s.name = "jack";

s.age = 20;

s.study();

 

Worker w = new Worker();

w.name = "rose";