1. 程式人生 > >Java基礎學習第十天——修飾符與內部類

Java基礎學習第十天——修飾符與內部類

文件版本 開發工具 測試平臺 工程名字 日期 作者 備註
V1.0 2016.03.02 lutianfei none

形式引數和返回值問題

  • 形式引數

    • 基本型別
    • 引用型別
      • (匿名物件時有講):需要的是該物件
      • 抽象類:需要的是該抽象類子類物件
      • 介面: 需要的是該介面實現類物件
  • 返回值型別

    • 基本型別
    • 引用型別
      • :返回的是該物件
      • 抽象類:返回的是該抽象類子類物件
      • 介面類:返回的是該介面實現類物件

  • Eg: 當作為形式引數的情況舉例:

class Student {
    public
void study() { System.out.println("Good Good Study,Day Day Up"); } } class StudentDemo { public void method(Student s) { //ss; ss = new Student(); Student s = new Student(); s.study(); } } class StudentTest { public static void main(String[] args) { //需求:我要測試Student類的study()方法
Student s = new Student(); s.study(); System.out.println("----------------"); //需求2:我要測試StudentDemo類中的method()方法 StudentDemo sd = new StudentDemo(); Student ss = new Student(); sd.method(ss); System.out.println("----------------"); //匿名物件用法
new StudentDemo().method(new Student()); } }
  • Eg: 當抽象類作為形式引數的情況舉例:
abstract class Person {
    public abstract void study();
}

class PersonDemo {
    public void method(Person p) {//p; p = new Student();  Person p = new Student(); //多型
        p.study();
    }
}

//定義一個具體的學生類
class Student extends Person {
    public void study() {
        System.out.println("Good Good Study,Day Day Up");
    }
}

class PersonTest {
    public static void main(String[] args) {
        //目前是沒有辦法的使用的
        //因為抽象類沒有對應的具體類
        //那麼,我們就應該先定義一個具體類
        //需求:我要使用PersonDemo類中的method()方法
        PersonDemo pd = new PersonDemo();
        Person p = new Student();
        pd.method(p);
    }
}
  • Eg: 當介面作為形式引數的情況舉例:
//定義一個愛好的介面
interface Love {
    public abstract void love();
}

class LoveDemo {
    public void method(Love l) { //l; l = new Teacher();  Love l = new Teacher(); 多型
        l.love();
    }
}

//定義具體類實現介面
class Teacher implements Love {
    public void love() {
        System.out.println("老師愛學生,愛Java,愛林青霞");
    }
}

class TeacherTest {
    public static void main(String[] args) {
        //需求:我要測試LoveDemo類中的love()方法
        LoveDemo ld = new LoveDemo();
        Love l = new Teacher();
        ld.method(l);
    }
}
  • Eg: 當作為返回值的情況舉例:
class Student {
    public void study() {
        System.out.println("Good Good Study,Day Day Up");
    }
}

class StudentDemo {
    public Student getStudent() {
        return new Student();
    }
}

class StudentTest2 {
    public static void main(String[] args) {
        //需求:我要使用Student類中的study()方法
        //但是,這一次我的要求是,不要直接建立Student的物件
        //讓你使用StudentDemo幫你建立物件
        StudentDemo sd = new StudentDemo();
        Student s = sd.getStudent(); //new Student(); Student s = new Student();
        s.study();
    }
}
  • Eg: 當抽象類作為返回值的情況舉例:
abstract class Person {
    public abstract void study();
}

class PersonDemo {
    public Person getPerson() {
        //Person p = new Student();
        //return p;

        return new Student();
    }
}

class Student extends Person {
    public void study() {
        System.out.println("Good Good Study,Day Day Up");
    }
}

class PersonTest2 {
    public static void main(String[] args) {
        //需求:我要測試Person類中的study()方法
        PersonDemo pd = new PersonDemo();
        Person p = pd.getPerson(); //new Student();  Person p = new Student(); 多型
        p.study();
    }
}
  • Eg: 當介面作為返回值的情況舉例:
interface Love {
    public abstract void love();
}

class LoveDemo {
    public Love getLove() {
        //Love l = new Teacher();
        //return l;

        return new Teacher();
    }
}

//定義具體類實現介面
class Teacher implements Love {
    public void love() {
        System.out.println("老師愛學生,愛Java,愛林青霞");
    }
}

class TeacherTest2 {
    public static void main(String[] args) {
        //如何測試呢?
        LoveDemo ld = new LoveDemo();
        Love l = ld.getLove(); //new Teacher(); Love l = new Teacher(); 多型
        l.love();
    }
}

鏈式程式設計

  • 形式:物件.方法1().方法2()….方法n()
  • 每次呼叫方法完畢後,返回的是一個物件
    • 方法1呼叫完畢後應該返回一個物件方法2呼叫完畢後應該返回一個物件方法n呼叫完畢後可能是物件,也可能不是物件。
/*
    鏈式程式設計。
        每次呼叫完畢方法後,返回的是一個物件。
*/
class Student {
    public void study() {
        System.out.println("Good Good Study,Day Day Up");
    }
}

class StudentDemo {
    public Student getStudent() {
        return new Student();
    }
}

class StudentTest3 {
    public static void main(String[] args) {
        //如何呼叫的呢?
        StudentDemo sd = new StudentDemo();
        //Student s = sd.getStudent();
        //s.study();

        //
        sd.getStudent().study();
    }
}

包的概述

  • 作用:對類進行分類管理,其實就是資料夾
  • 包的劃分:
    • 基本的劃分:按照模組和功能分。
    • 高階的劃分:在具體專案中再說明。

包的定義及注意事項

  • 定義包的格式
    • package 包名;
    • 多級包用 . 分開即可
  • 注意事項:

    • package語句必須是程式的第一條可執行(可被虛擬機器執行)的程式碼
    • package語句在一個java檔案中只能有一個
    • 如果沒有package,預設表示無包名
  • 帶包的編譯和執行

    • 手動式
      • a:通過javac命令編譯該java檔案
      • b:手動建立包名。
      • c:將a步驟產生的類檔案放在b步驟的最底層包。
      • d:帶包地址執行java命令
    • 自動式
      • javac編譯的時候帶上-d即可
        • javac -d . HelloWorld.java

導包

  • 導包概述
    • 不同包下的類之間的訪問,每次使用不同包下的類的時候,都需要加包的全路徑。方便起見,java提供了導包的功能。
  • 導包格式
    • import 包名;
  • 注意:

    • 這種方式匯入是到的名稱。
    • 雖然可以最後寫*,但是不建議。
  • package,import,class有沒有順序關係(面試題)

    • package>import>class
    • package : 只能有一個
    • import:可以有多個
    • class:可以有多個,建議是一個。

修飾符

  • 許可權修飾符:private,預設的protected,public
  • 狀態修飾符:static,final
  • 抽象修飾符:abstract

許可權修飾符

類及其組成可以用的修飾符

  • 類:

    • 許可權修飾符:預設的,public
    • 狀態修飾符(外部類):final , (內部類可以使用static)
    • 抽象修飾符:abstract
    • 我們自己定義:public居多
  • 成員變數:

    • 許可權修飾符:private,預設的protected,public
    • 狀態修飾符:static,final
    • 我們自己定義:private居多
  • 構造方法:

    • 許可權修飾符:private,預設的protected,public
    • 我們自己定義:public 居多
  • 成員方法:

    • 許可權修飾符:private,預設的protected,public
    • 狀態修飾符:static,final
    • 抽象修飾符:abstract
    • 我們自己定義:public居多
  • 除此以外的組合規則:

    • 成員變數:public static final
    • 成員方法:
      • public static
        • public abstract
        • public final

內部類

內部類概述

  • 把類定義在其他類的內部,這個類就被稱為內部類
    • 舉例:在類A中定義了一個類B,類B就是內部類。
  • 內部類的訪問特點:
    • 內部類可以直接訪問外部類的成員,包括私有
    • 外部類要訪問內部類的成員,必須建立物件

內部類的位置

  • 按照內部類在類中定義的位置不同,可以分為如下兩種格式:
    • 成員位置(成員內部類)
    • 區域性位置(區域性內部類)
成員內部類
  • 成員內部類不是靜態的:

    • 外部類名.內部類名 物件名 = new 外部類物件.new 內部類物件;
    • 一般加 private 為了保證資料的安全性
  • 成員內部類是靜態的(被靜態修飾後的訪問方式是):

    • 外部類名.內部類名 物件名 = new 外部類名.內部類名();
    • static 為了讓資料訪問更方便,一般加public
  • 成員內部類不是靜態的例子

class Outer {
    private int num = 10;

    class Inner {
        public void show() {
            System.out.println(num);
        }
    }
}

class InnerClassDemo3 {
    public static void main(String[] args) {
        //格式:外部類名.內部類名 物件名 = new 外部類物件.new 內部類物件;
        Outer.Inner oi = new Outer().new Inner();
        oi.show();
    }
}
  • 上面成員內部類的使用,在實際開發中是不會這樣使用的。因為一般內部類就是不讓外界直接訪問的
class Body {
   private class Heart {
       public void operator() {
           System.out.println("心臟搭橋");
       }
   }

   public void method() {
       if(如果你是外科醫生) {
           Heart h = new Heart();
           h.operator();
       }
   }
}
  • 內部類被靜態修飾後的方法
    • 靜態修飾成員內部類只能訪問外部類靜態成員
    • 格式:外部類名.內部類名 物件名 = new 外部類名.內部類名();
class Outer {
    private int num = 10;
    private static int num2 = 100;

    //內部類用靜態修飾是因為內部類可以看出是外部類的成員
    public static class Inner {
        public void show() {
            //System.out.println(num);
            System.out.println(num2);
        }

        public static void show2() {
            //System.out.println(num);
            System.out.println(num2);
        }        
    }
}

class InnerClassDemo4 {
    public static void main(String[] args) {
        //成員內部類被靜態修飾後的訪問方式是:
        //格式:外部類名.內部類名 物件名 = new 外部類名.內部類名();
        Outer.Inner oi = new Outer.Inner();
        oi.show();
        oi.show2();

        //show2()的另一種呼叫方式
        Outer.Inner.show2();
    }
}
  • 練習:補齊程式(注意:內部類和外部類沒有繼承關係)要求請填空分別輸出30 20 10
class Outer {
    public int  num = 10;
    class Inner {
        public int  num = 20;
        public void show() {
            int  num = 30;
            System.out.println(?); //num
            System.out.println(??);//this.num
            System.out.println(???);
            //new Outer().num
            // Outer.this.num
        }
    }
}
區域性內部類
  • 可以直接訪問外部類的成員
  • 可以建立內部類物件,通過物件呼叫內部類方法,來使用區域性內部類功能
  • 區域性內部類訪問區域性變數的注意事項:
    • 必須被final修飾
      • 因為區域性變數會隨著方法的呼叫完畢而消失,這個時候,區域性物件並沒有立馬從堆記憶體中消失,還要使用那個變數。為了讓資料還能繼續被使用,就用fianl修飾,這樣,在堆記憶體裡面儲存的其實是一個常量值。
class Outer {
    private int num  = 10;

    public void method() {
        //int num2 = 20;
        //final int num2 = 20;
        class Inner {
            public void show() {
                System.out.println(num);
                //從內部類中訪問本地變數num2; 需要被宣告為最終型別
                System.out.println(num2);//20
            }
        }

        //System.out.println(num2);

        Inner i = new Inner();
        i.show();
    }
}

class InnerClassDemo5 {
    public static void main(String[] args) {
        Outer o = new Outer();
        o.method();
    }
}
匿名內部類
  • 就是內部類簡化寫法。
  • 前提:存在一個或者介面
    • 這裡的類可以是具體類也可以是抽象類
  • 格式:new 類名或者介面名() {重寫方法;}
  • 本質:是一個繼承了該或者實現了介面子類匿名物件
interface Inter {
    public abstract void show();
    public abstract void show2();
}

class Outer {
    public void method() {
        //一個方法的時候
        /*
        new Inter() {
            public void show() {
                System.out.println("show");
            }
        }.show();
        */

        //二個方法的時候
        /*
        new Inter() {
            public void show() {
                System.out.println("show");
            }

            public void show2() {
                System.out.println("show2");
            }
        }.show();

        new Inter() {
            public void show() {
                System.out.println("show");
            }

            public void show2() {
                System.out.println("show2");
            }
        }.show2();
        */

        //如果我是很多個方法,就很麻煩了
        //那麼,我們有沒有改進的方案呢?
        Inter i = new Inter() { //多型
            public void show() {
                System.out.println("show");
            }

            public void show2() {
                System.out.println("show2");
            }
        };

        i.show();
        i.show2();
    }
}

class InnerClassDemo6 {
    public static void main(String[] args) {
        Outer o = new Outer();
        o.method();
    }
}
  • 匿名內部類在開發中的使用
interface Person {
    public abstract void study();
}

class PersonDemo {
    //介面名作為形式引數
    //其實這裡需要的不是介面,而是該介面的實現類的物件
    public void method(Person p) {
        p.study();
    }
}

//實現類
class Student implements Person {
    public void study() {
        System.out.println("好好學習,天天向上");
    }
}

class InnerClassTest2 {
    public static void main(String[] args) {
        //測試
        PersonDemo pd = new PersonDemo();
        Person p = new Student();
        pd.method(p);
        System.out.println("--------------------");

        //匿名內部類在開發中的使用
        //匿名內部類的本質是繼承類或者實現了介面的子類匿名物件
        pd.method(new Person(){
            public void study() {
                System.out.println("好好學習,天天向上");
            }
        });
    }
}
  • 匿名內部類面試題(重難點)
    • 要求在控制檯輸出”HelloWorld”
  interface Inter { 
      void show();
  }
  class Outer { //補齊程式碼 

  }

  class OuterDemo {
      public static void main(String[] args) {
        Outer.method().show();
    }
  }
//分析:
/*
1:由Outer.method()可以看出method()應該是outer中的一個靜態方法。
2:Outer.method().show()可以看出method()方法的返回值是一個物件
3:由於介面Inter中有一個show()方法,所以認為method()方法的返回值型別是一個介面。
*/

//* 補充程式碼如下:在補齊程式碼後:
public static Inter method(){
    return new Inter(){
        public void show(){
            System.out.println("HelloWorld");
        }
    }
}