Java基本语法(六)——面向对象(下)

125 阅读7分钟

1.关键字:static

应用场景:当我们需要给某个类的属性设定一个默认值(比如中国人的class,其中所有对象的country属性值都应该为“中国”)

关于static:

  • 静态

  • 可以修饰属性、方法、代码块、内部类(不能修饰构造器)

    • 修饰属性:静态属性(静态变量、类变量),即当修改某一个对象的静态属性时,其他对象的此静态属性值也是修改后的结果。

       public class StaticTest {
       ​
           public static void main(String[] args) {
               Chinese p1 = new Chinese();
               p1.country = "CHN";
               
               Chinese p2 = new Chinese();
               System.out.println(p2.country);//虽然p2的country未赋值,但结果为“CHN”
               
               p2.country = "CHINA";
               System.out.println(p1.country);//此时p1的country值也变成“CHINA”
           }
       ​
       }
       class Chinese{
           int age;
           String name;
           static String country;
       }
      
      • 为什么叫类变量:静态变量是随着class的加载而加载,可以通过“类名.静态变量”的方式直接调用。(因此静态变量的创建早于对象的创建)
      • 由于类只加载一次,因此静态变量在内存中只存在一份:存在方法区的静态域中。
    • 修饰方法:静态方法

      • 同静态属性:随着class的加载而加载,可以通过“类名.静态方法”的方式直接调用。
      • 静态方法中:只能调用静态的方法或属性(生命周期)。不能使用this、super关键字。

2.类的成员之四:代码块

  • 代码块(初始化块)作用:用来初始化类、对象。

  • 只能用static修饰。

    • static代码块:

      • 随着类的加载而执行,且只执行1次;
      • 作用:初始化类的信息。
      • 如果一个类中定义了多个static代码块,按定义的先后顺序执行。
      • 先执行static代码块,再执行非static。
      • 只能调用static属性、方法。
    • 非static代码块:

      • 随着对象的创建而执行,每创建一个对象就执行一次代码块。

      • 可以在对象的创建时,对其属性进行初始化。

      • 定义多个非static代码块,也是按先后顺序执行。

      • static/非static属性、方法都可调用。


 package com.coderLeo.study;
 ​
 public class BlockTest {
     public static void main(String[] args) {
         String desc = Person.desc;
         /*执行完上一句,就显示:hello, static code block!
          * 说明static代码块,是随着类的加载而执行
          * */
         
         Person p1 = new Person();
         /* 显示:hello, nostatic code block!
          * 说明随着对象的创建而执行
          * */
         
         Person.info();
         //只执行I am a funny man!
         //说明静态代码块随着类的加载,只执行1次
         
     }
 }
 ​
 class Person{
     //attribute
     int age;
     String name;
     static String desc = "我是一个人";
     
     //constructor
     public Person(){
         
     }
     public Person(int age, String name){
         this.age = age;
         this.name = name;
     }
     //static code block
     static{
         System.out.println("hello, static code block!");
         info();//可以调用static方法
         //this.age = 10; //非static不能调用
         
     }
     //nostatic code block
     {
         this.age = 1;//nostatic的block,初始化对象的属性。
         System.out.println("hello, nostatic code block!");
     }
     
     //method
     public void Eat(){
         System.out.println("I am eating!");
     }
     @Override
     public String toString() {
         return "Person [age=" + age + ", name=" + name + "]";
     }
     static public void info(){
         System.out.println("I am a funny man!");
     }
     
 }
  • 关于代码块的执行顺序:由父类到子类,static先行。
  • 代码块的变量赋值顺序:与显式赋值和代码块赋值的先后顺序有关,即谁在前谁先赋值。

3.关键字:final

final用来修饰:class、method、variable

  • 修饰class:final class 类名。此时

    • 这个class不能被其他类继承。比如:String类、StringBuffer类、System类
  • 修饰method:权限符后+final

    • 表示method不可被重写(override)。有:Object类中的getClass。
  • 修饰variable:此时的”variable“是一个constant

    • 修饰属性:可以考虑显示初始化、代码块、构造器。

    • 修饰局部变量:constant

      • 方法体内部:不能修改。
      • 形参:调用方法时给常量形参赋值后,只能在方法内调用,不能修改。
  • static final xx:修饰属性表示全局常量。直接用类调用(类名.xx

4.抽象类和抽象方法

关键字:abstract,用来修饰class、method。

对于class:

  • 一旦加上abstract,不可实例化
  • 但抽象类中仍然有构造器。

对于method:

  • 只有方法声明,无方法体:权限 abstract 返回值 方法名(形参)
  • 包含抽象方法的class一定是抽象类。
  • 子类重写父类中所有的抽象方法后,此子类方可实例化。否则,该子类也是抽象类(也应该加上abstract关键字)

使用时注意:

  • 不能用来修饰属性、构造器、私有方法、静态方法、final方法、final类

抽象类的匿名对象:

 public class PersonTest {
 ​
     public static void main(String[] args) {
         //创建匿名子类的对象:p
         Person p = new Person(){
             @Override
             public void eat(){
                 System.out.println("people is eating...");
             }
         };
         /*理解:由于Person类是abstract,不能实例化对象。因此这里创建的是Person子类,这个子类是无名的,因此叫匿名子类
          * 并且随后重写了其中的抽象方法eat()
          * 然后用多态的方式以Person p来接收这个Person子类
          */
         method(p);//people is eating...
         
         //匿名子类的匿名对象
         method(new Person(){
             @Override
             public void eat(){
                 System.out.println("people have eaten");
             }
         });//people have eaten
     }
     
     public static void method(Person p){
         p.eat();
     }
 }
 ​
 abstract class Person {
     String name;
     int age;
     
     public Person(){}
     public Person(String name, int age) {
         super();
         this.name = name;
         this.age = age;
     }
     
     public abstract void eat();
     public void walk(){
         System.out.println("people walk...");
     }
     
 }

5.接口(Interface)

关键字:interface。java中class和interface是并列关系。

定义接口:定义接口的成员

  • jdk7及以前:只能定义全局常量(public static final)和抽象方法(public abstract
  • jdk8:还可以定义静态方法、默认方法
  • 不能定义构造器

java中,让class去实现(implements) 接口:

  • 实现类重写了所有接口中的抽象方法,则此实现类可以实例化。
  • 否则该实现类仍然是抽象类。
  • java类可以实现多个接口,格式:class 类名 extends 父类名 implements 接口1,接口2...

接口与接口之间可以继承,而且可以多继承。

一个例子:

 public class InterfaceTest {
     public static void main(String[] args) {
         Plane test = new Plane();
         test.fly();//engine fly
         System.out.println(test.MAX_SPEED);//7900
     }
 }
 ​
 interface Flyable{
     //全局常量
     public static final int MAX_SPEED = 7900;
     int MIN_SPEED = 1;//public static final可以省略,interface默认是这样
     
     //抽象方法 
     public abstract void fly();
     void stop();//也是可以省略public abstract 
 }
 ​
 interface Offensive{
     public abstract void attack();
 }
 ​
 class Plane implements Flyable{
     @Override
     public void fly() {
         System.out.println("engine fly");
     }
 ​
     @Override
     public void stop() {
         System.out.println("stop by engine");
     }
 }
 ​
 abstract class Kite implements Flyable{
     
 }
 ​
 class Bullet extends Object implements Flyable, Offensive, CC{
 ​
     @Override
     public void attack() {
     }
 ​
     @Override
     public void fly() {
     }
 ​
     @Override
     public void stop() {        
     }
     
     //Bullet继承了CC,CC多继承AA、BB,Bullet类就要实现这两个抽象方法
     @Override
     public void method1() {
     }
 ​
     @Override
     public void method2() {
     }
 }
 ​
 interface AA{
     void method1();
 }
 interface BB{
     void method2();
 }
 interface CC extends AA,BB{//CC多继承AA、BB
     
 }

还有几个重要的点:

  1. 接口满足多态性

  2. 接口定义了一种规范

  3. 创建接口匿名实现类的对象:

    1. 非匿名实现类的非匿名对象
    2. 非匿名实现类的匿名对象
    3. 匿名实现类的非匿名对象
    4. 匿名实现类的匿名对象
 public class USBTest {
     public static void main(String[] args) {
         Computer test = new Computer();
         //造实现类的对象,这里有Flash、Printer实现USB。
         Flash flash = new Flash();
         //①非匿名实现类(Flash)的非匿名对象(flash)
         
         //1.(对应上述第1条)Computer的transferData虽然声明的是USB形参,但出入的是其实现类Flash,体现了接口的多态性,而且这是必须的。
         test.transferData(flash);
         /*FLASH starts working...
              具体的传输细节
           FLASH stop working...
         */
         
         //②非匿名实现类(Printer)的匿名对象(new出来的这个对象没名)
         test.transferData(new Printer());
         
         //③匿名实现类(USB的实现类没名,在这里创建时直接重写了实现的方法)的非匿名对象(phone)
         USB phone = new USB(){
 ​
             @Override
             public void start() {
                 System.out.println("phone start working");
             }
 ​
             @Override
             public void stop() {
                 System.out.println("phone stop working");
             }
         };
         test.transferData(phone);
         
         //④匿名实现类的匿名对象
         test.transferData(new USB(){
 ​
             @Override
             public void start() {
                 System.out.println("Laptop start working");
             }
 ​
             @Override
             public void stop() {
                 System.out.println("Laptop stop working");
             }
             
         });
     }
 }
 ​
 class Computer{
     //参数为USB接口,但是接口本身不能实例化,因此实际传入的是其实现类的对象
     public void transferData(USB usb){
         usb.start();
         System.out.println("具体的传输细节");
         usb.stop();
     }
 }
 ​
 //定义接口USB。2.(第2条)定义了一种规范,就是每个想要用USB接口的都得遵循这里的start、stop
 interface USB{
     void start();
     void stop();
 }
 ​
 //Flash类实现USB
 class Flash implements USB{
 ​
     @Override
     public void start() {
         System.out.println("FLASH starts working...");
     }
 ​
     @Override
     public void stop() {
         System.out.println("FLASH stop working...");
     }
 }
 //Printer实现USB
 class Printer implements USB{
 ​
     @Override
     public void start() {
         System.out.println("Printer starts working...");
     }
 ​
     @Override
     public void stop() {
         System.out.println("Printer stop working...");
     }
 }