面向对象编程

一、包

1. 如果需要使用 java.util 中的其他类, 可以使用import java.util.*

import java.util.*;
public class Test {
    public static void main(String[] args) {
        Date date = new Date();
        // 得到一个毫秒级别的时间戳
        System.out.println(date.getTime());
   }
}

2. 使用 import static 可以导入包中的静态的方法和字段

3. 将类放到包中

    基本规则:

  • 在文件的最上方加上一个 package 语句指定该代码在哪个包中。
  • 包名需要尽量指定成唯一的名字, 通常会用公司的域名的颠倒形式(例如 com.bit.demo1 )。
  • 包名要和代码路径相匹配. 例如创建 com.bit.demo1 的包, 那么会存在一个对应的路径 com/bit/demo1 来存储代码。
  • 如果一个类没有 package 语句, 则该类被放到一个默认包中。

4. 包的访问权限控制

我们已经了解了类中的 public 和 private. private 中的成员只能被类的内部使用.
如果某个成员不包含 public 和 private 关键字, 此时这个成员可以在包内部的其他类使用, 但是不能在包外部的类使用.

二、继承(is - a 语义).

// Animal.java 
public class Animal { 
    public String name; 

    public Animal(String name) { 
        this.name = name; 
    } 

    public void eat(String food) { 
        System.out.println(this.name + "正在吃" + food); 
    } 
}

// Cat.java 
class Cat { 
    public String name; 

    public Cat(String name) { 
        this.name = name; 
    }
 
    public void eat(String food) { 
        System.out.println(this.name + "正在吃" + food); 
    } 
}

// Bird.java 
class Bird { 
    public String name; 

    public Bird(String name) { 
        this.name = name; 
    } 

    public void eat(String food) { 
        System.out.println(this.name + "正在吃" + food); 
    } 

    public void fly() { 
        System.out.println(this.name + "正在飞 ︿( ̄︶ ̄)︿"); 
    } 
}

Java 单继承的语言

 面试问题: 继承到底继承了父类的什么东西?

            答: 继承就是子类继承父类的特征和行为,使得子类对象(实例)具有父类的实例域和方法,或子类从父类继承方法,使得子类具有父类相同的行为。​​​​​​​

1. 语法规则

class 子类 extends 父类 { 

}
  • 使用 extends 指定父类。
  • Java 中一个子类只能继承一个父类 (C++/Python等语言支持多继承)。
  • 子类会继承父类的所有 public 的字段和字段。
  • 对于父类的 private 的字段和方法,子类中是无法访问的。
  • 子类的实例中, 也包含着父类的实例,可以使用super关键字得到父类实例的引用。
  • 只写独有的数据 不用写父类中已有的。

2. protected关键字

如果设为private,子类不能访问

protected 体现封装性,但子类也可以访问

  • 对于类的调用者来说,protected修饰的字段和方法是不能访问的。
  • 对于类的子类和同一个包的其他类来说,protected修饰的字段和方法是可以访问的。
小结 : Java 中对于字段和方法共有四种访问权限
  • private: 类内部能访问, 类外部不能访问。
  • 默认default(也叫包访问权限): 类内部能访问, 同一个包中的类可以访问, 其他类不能访问。
  • protected: 类内部能访问,子类和同一个包中的类可以访问,其他类不能访问。
  • public: 类的内部和类的调用者都能访问。​​​​​​​

什么时候下用哪一种呢?
我们希望类要尽量做到 " 封装 ", 即隐藏内部实现细节 , 只暴露出 必要 的信息给类的调用者 .
因此我们在使用的时候应该尽可能的使用 比较严格 的访问权限 . 例如如果一个方法能用 private, 就尽量不要用
public.
另外 , 还有一种 简单粗暴 的做法 : 将所有的字段设为 private, 将所有的方法设为 public. 不过这种方式属于是对
访问权限的滥用 , 还是更希望同学们能写代码的时候认真思考 , 该类提供的字段方法到底给 " " 使用 ( 是类内部
自己用 , 还是类的调用者使用 , 还是子类使用 ).
3. final 关键字
曾经我们学习过 final 关键字 , 修饰一个变量或者字段的时候 , 表示  常量 ( 不能修改 ).
final int a = 10;
a = 20; // 编译出错

final 关键字也能修饰类, 此时表示被修饰的类就不能被继承

final public class Animal {
...
}
public class Bird extends Animal {
...
}
// 编译出错

Error:(3, 27) java: 无法从最终com.bit.Animal进行继承

final关键字的功能是限制类被继承

三、组合(has - a 语义)

和继承类似 , 组合也是一种表达类之间关系的方式 , 也是能够达到代码重用的效果 .
组合并没有涉及到特殊的语法 ( 诸如 extends 这样的关键字 ), 仅仅是将一个类的实例作为另外一个类的字段 .
这是我们设计类的一种常用方式之一 .

四、多态

1.向上转型(子类对象转成父类对象)

父类引用子类的对象  —> 叫向上转型 

Bird bird = new Bird("圆圆"); 
Animal bird2 = bird; 
// 或者写成下面的方式
Animal bird2 = new Bird("圆圆"); 
此时 bird2 是一个父类 (Animal) 的引用 , 指向一个子类 (Bird) 的实例 . 这种写法称为 向上转型。
向上转型:(发生的三个时机)
  1. 赋值 子类给父类
  2. 参数
  3. 返回类型
只能调用父类自己的方法或者访问自己属性
2.向下转型(父类对象转成子类对象)
前提条件:父类已经引用了子类对象,且子类要为向下转型的类型
Animal animal = new Bird("圆圆"); 
animal.eat("谷子"); 
// 执行结果:圆圆正在吃谷子

注意事项 :对于 Animal animal = new Bird("圆圆") 这样的代码:

  • 编译器检查有哪些方法存在, 看的是 Animal 这个类型。
  • 执行时究竟执行父类的方法还是子类的方法, 看的是 Bird 这个类型。
父类给子类 (强转) 最好不要用
// (Bird) 表示强制类型转换
Bird bird = (Bird)animal;
bird.fly();
// 执行结果:圆圆正在飞

instanceof 可以判定一个引用是否是某个类的实例. 如果是, 则返回 true. 这时再进行向下转型就比较安全了.

Animal animal = new Cat("小猫"); 
if (animal instanceof Bird) { 
    Bird bird = (Bird)animal; 
    bird.fly(); 
}

3.super 关键字(放第一行)

super与this的区别:

4.动态绑定(运行时绑定)(多态的一个过程)

Java , 调用某个类的方法, 究竟执行了哪段代码 (是父类方法的代码还是子类方法的代码) , 要看究竟这个引 用指向的是父类对象还是子类对象. 这个过程是程序运行时决定的(而不是编译期), 因此称为 动态绑定.

条件

  1. 先要向上转型——>父类的引用,引用子类的对象
  2. 父类和子类都有同名的覆盖方法(重写)

特殊:Class对象在方法区

5.方法重写

重写/覆盖/覆写(Override):

  1. 函数名相同
  2. 参数列表相同
  3. 返回值也要相同
  4. 静态的方法和构造方法不能被重写
  5. 子类的访问修饰限定符一定要大于等于父类的访问修饰限定符(父类的方法不能是私有的)

重载(Overload):

  1. 函数名相同
  2. 参数列表不同(类型,个数)
  3. 返回值不做要求

重写、重载的区别:

6.理解多态

多态顾名思义,就是“一个引用,能表现出多种不同的形态”

代码层次理解:多态存在的前提:

  1. 要有继承关系
  2. 子类要重写父类的方法
  3. 父类引用指向子类对象
  4. 运行时绑定(动态绑定)
class Shape { 
    public void draw() { 
        // 啥都不用干
    } 
} 

class Cycle extends Shape { 
    @Override 
    public void draw() { 
        System.out.println("○"); 
    } 
} 

class Rect extends Shape { 
    @Override 
    public void draw() { 
        System.out.println("□"); 
    } 
} 

class Flower extends Shape { 
    @Override 
    public void draw() { 
        System.out.println("♣"); 
    } 
} 

/我是分割线// 

// Test.java 
public class Test { 
    public static void main(String[] args) { 
        Shape shape1 = new Flower(); 
        Shape shape2 = new Cycle(); 
        Shape shape3 = new Rect(); 
        drawMap(shape1); 
        drawMap(shape2); 
        drawMap(shape3); 
    } 
    // 打印单个图形
    public static void drawShape(Shape shape) { 
        shape.draw(); 
    } 
}
在这个代码中 , 分割线上方的代码是 类的实现者 编写的 , 分割线下方的代码是 类的调用者 编写的.
当类的调用者在编写 drawShape  这个方法的时候 , 参数类型为 Shape ( 父类 ), 此时在该方法内部并 不知道 , 也不关注 当前的 shape 引用指向的是哪个类型 ( 哪个子类 ) 的实例 . 此时 shape 这个引用调用 draw 方法可能会有多种不同的表现 (和 shape 对应的实例相关 ), 这种行为就称为 多态.
" 用尽量简单的方式使对象进入可工作状态 ", 尽量不要在构造器中调用方法 ( 如果这个方法被子类重写 , 就会触发动态绑定, 但是此时子类对象还没构造完成 ), 可能会出现一些隐藏的但是又极难发现的问题 .
多态的核心:让调用者不必关注对象的具体类型. 这是降低用户使用成本的一种重要方式.

五、抽象类

abstract class Shape { 
    abstract public void draw(); 
}

1.包含抽象方法的类  叫做抽象类

2.抽象类和普通类,最大的区别:包含抽象方法;

3.抽象类不能被实例化 ,不能被new;

4.抽象类存在的最大意义:肯定要被继承;

5.抽象类一旦被继承,就要重写抽象方法;

6.如果一个类一旦继承了抽象类,那么如果不重写抽象类的方法,那么当前类,需要设计为抽象类;

7.抽象类不能final,抽象方法不能private;

8.抽象类中可以包含其他非抽象方法, 也可以包含字段. 这个非抽象方法和普通方法的规则都是一样的, 可以被重写, 也可以被子类直接调用。

六、接口

接口中包含的方法都是抽象方法, 字段只能包含静态常量。

interface IShape { 
    void draw(); 
} 
class Cycle implements IShape { 
    @Override 
    public void draw() { 
        System.out.println("○"); 
    } 
}
  • 使用interface定义一个接口
  • 定义的方法默认是:public abstract;
  • 定义的成员变量默认是:public static final;
  • 尽量简洁——>不用加上面所列的内容;
  • 类和接口的关系——>实现:implements;此时表达的含义不再是 "扩展", 而是 "实现"
  • 实现了接口,一定要重写抽象方法;
  • 在调用的时候同样可以创建一个接口的引用, 对应到一个子类的实例.
  • 接口不能单独被实例化.
扩展(extends) vs 实现 (implements)
扩展指的是当前已经有一定的功能了 , 进一步扩充功能

1.实现多个接口

class Duck extends Animal implements IRunning, ISwimming, IFlying { 
    public Duck(String name) { 
        super(name); 
    }

    @Override 
    public void fly() { 
        System.out.println(this.name + "正在用翅膀飞"); 
    } 

    @Override 
    public void run() { 
        System.out.println(this.name + "正在用两条腿跑"); 
    }
 
    @Override 
    public void swim() { 
        System.out.println(this.name + "正在漂在水上"); 
    } 
}
好处:   忘记类型 有了接口之后 , 类的使用者就不必关注具体类型 , 而只关注某个类是否具备某种能力.
2.接口间的继承
接口可以继承一个接口 达到复用的效果,   使用 extends 关键字 .。
interface IRunning { 
    void run(); 
} 

interface ISwimming { 
    void swim(); 
} 

// 两栖的动物, 既能跑, 也能游
interface IAmphibious extends IRunning, ISwimming { 

} 

class Frog implements IAmphibious { 
    ... 
}
抽象类和接口的核心区别: 抽象类中可以包含普通方法和普通字段 , 这样的普通方法和字段可以被子类直接使用 ( 不必重写 ), 而接口中不能包含普通方法, 子类必须重写所有的抽象方法 .

面试问题: 

什么是多态?

重写和重载的区别?

super,this区别?

抽象类和接口的区别?

访问修饰限定符了解吗?

应用:

多态   抽象类   接口

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值