面向对象编程

本文介绍了Java中的包的概念及其作用,包括如何导入和创建包,以及包的权限访问控制。同时讲解了类的继承、protected关键字、final关键字和多态,特别是动态绑定和方法重写。此外,还探讨了抽象类和接口的应用,以及它们在继承和多态中的角色。最后,提到了接口的继承和使用场景。
摘要由CSDN通过智能技术生成

什么是包?

包(package) 是组织类的一种方式.也就是说类统一都放在包里。


使用包的主要目的:保证类的唯一性.
例如, 你在代码中写了一个 Test 类. 然后你的同事也可能写一个 Test 类. 如果出现两个同名的类, 就会冲突, 导致代码不能编译通过。

 

导入包中的类

假如你想要使用包中的某个类,那你必须要先将这个类导入。怎么导入呢?使用import关键字。

代码示例:

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

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

静态导入

使用 import static 可以导入包中的静态的方法和字段,不过这种用的很少。

代码示例:

import static java.lang.System.*;
public class Test {
    public static void main(String[] args) {
        out.println("hello");
    }
}

将类放入包中

我们前面说了类都是放在包里的。那么怎么放呢?

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

 操作步骤
1) 在 IDEA 中先新建一个包: 右键 src -> 新建 -> 包

2) 在弹出的对话框中输入包名, 例如 com.baidu.demo1

3) 在包中创建类, 右键包名 -> 新建 -> 类, 然后输入类名即可
 

包的权限访问控制

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

常见的系统包

  1.  java.lang:系统常用基础类(String、Object),此包从JDK1.1后自动导入。
  2.  java.lang.reflect:java 反射编程包;
  3.  java.net:进行网络编程开发包。
  4.  java.sql:进行数据库开发的支持包。
  5.  java.util:是java提供的工具程序包。(集合类等) 非常重要
  6.  java.io:I/O编程开发包

 
继承

什么是继承?其实就跟我们日常生活中理解的意思差不多。例如你继承了你父亲的财产,那么这些财产都为你所拥有了。Java中的继承也就是这样,当一个类继承另一个类后,这个类自然也就继承了它公有的属性和方法

代码示例:

class Animal {
    public String name;
    public Animal(String name) {
        this.name = name;
    }
    public void eat(String food) {
        System.out.println(this.name + "正在吃" + food);
    }
}
class Cat extends Animal {
    public Cat(String name) {
// 使用 super 调用父类的构造方法.
        super(name);
    }
}

如上代码所示,用extends关键字可以实现继承。Cat继承了AnImal,那么Cat就拥有了 AnImal的一些属性和方法。

此时AnImal被称为父类、基类或超类。而继承AnImal的Cat被称为子类或派生类

注意事项:

  • 子类只能继承父类public的属性和方法,private修饰的字段和方法是无法获取到的。
  • 子类实例化前要先帮助父类进行构造
  • 在java中一个类只能继承一个类
  • 子类的实例中, 也包含着父类的实例. 可以使用 super 关键字得到父类实例的引用
     

protected关键字

刚才我们发现, 如果把字段设为 private, 子类不能访问. 但是设成 public, 又违背了我们 "封装" 的初衷.两全其美的办法就是 protected 关键字.

  • 对于类的调用者来说, protected 修饰的字段和方法是不能访问的
  • 对于类的 子类 和 同一个包的其他类 来说, protected 修饰的字段和方法是可以访问的

小结: Java 中对于字段和方法共有四种访问权限

  • private: 类内部能访问, 类外部不能访问
  • 默认(也叫包访问权限): 类内部能访问, 同一个包中的类可以访问, 其他类不能访问.
  • protected: 类内部能访问, 子类和同一个包中的类可以访问, 其他类不能访问.
  • public : 类内部和类的调用者都能访问
     

final关键字

我们知道被final修饰的变量是不能被修改的。对于一个类来说,如果这个类被final修饰则说明这个类是不能被继承的。举个很简单的栗子,我们平时用的 String 字符串类, 就是用 final 修饰的, 不能被继承。

多态

多态是面向对象程序设计中比较难理解的部分.通俗来讲就是说利用一个引用指向不同的对象从而实现不同的代码功能,尽管这样的说法是不太准确的但这能帮助我们更好的理解多态。

多态在编码上能带来很大的好处. 多态的核心都是让调用者不必关注对象的具体类型. 这是降低用户使用成本的一种重要方式。

多态的实现:

  • 向上转型
  • 动态绑定
  • 重写
     

向上转型:

向上转型就是指父类引用指向子类对象

Bird bird = new Bird("圆圆");
    Animal bird2 = bird;
    // 或者写成下面的方式
    Animal bird2 = new Bird("圆圆");

此时 bird2 是一个父类 (Animal) 的引用, 指向一个子类 (Bird) 的实例. 这种写法称为 向上转型
 

动态绑定:

我们来思考这样一个问题:如果子类和父类中出现同名方法的时候, 再去调用会出现什么情况呢?

// Animal.java
public class Animal {
    protected String name;
    public Animal(String name) {
        this.name = name;
    }
    public void eat(String food) {
        System.out.println("我是一只小动物");
        System.out.println(this.name + "正在吃" + food);
    }
}
// Bird.java
public class Bird extends Animal {
    public Bird(String name) {
        super(name);
    }
    public void eat(String food) {
        System.out.println("我是一只小鸟");
        System.out.println(this.name + "正在吃" + food);
    }
}
// Test.java
public class Test {
    public static void main(String[] args) {
        Animal animal1 = new Animal("圆圆");
        animal1.eat("谷子");
        Animal animal2 = new Bird("扁扁");
        animal2.eat("谷子");
    }
}
    // 执行结果
    我是一只小动物
            圆圆正在吃谷子
    我是一只小鸟
            扁扁正在吃谷子    

此时, 我们发现:

  • animal1 和 animal2 虽然都是 Animal 类型的引用, 但是 animal1 指向 Animal 类型的实例, animal2 指向Bird 类型的实例.
  • 针对 animal1 和 animal2 分别调用 eat 方法, 发现 animal1.eat() 实际调用了父类的方法, 而animal2.eat() 实际调用了子类的方法.


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


方法重写:

针对刚才的 eat 方法来说:
子类实现父类的同名方法, 并且参数的类型和个数完全相同, 这种情况称为 覆写/重写/覆盖(Override).
关于重写的注意事项
1. 重写和重载完全不一样. 不要混淆(思考一下, 重载的规则是啥?)
2. 普通方法可以重写, static 修饰的静态方法不能重写

3. 重写中子类的方法的访问权限不能低于父类的方法访问权限.
4. 重写的方法返回值类型不一定和父类的方法相同(但是建议最好写成相同, 特殊情况除外).

有了上面的向上转型, 动态绑定, 方法重写之后, 我们就可以使用 多态(polypeptide) 的形式来设计程序了。
 

抽象类:

  1. 带有抽象方法的类就是抽象类。那什么是抽象方法?抽象方法就是用abstract关键字修饰的方法。
  2. 抽象方法没有方法体(没有 { }, 不能执行具体代码).
  3. 对于包含抽象方法的类, 必须加上 abstract 关键字表示这是一个抽象类.

代码示例:

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

注意事项
1) 抽象类不能直接实例化

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

 

抽象类的作用

 抽象类存在的最大意义就是为了被继承.
抽象类本身不能被实例化, 要想使用, 只能创建该抽象类的子类. 然后让子类重写抽象类中的抽象方法.



问题来了, 普通的类也可以被继承呀, 普通的方法也可以被重写呀, 为啥非得用抽象类和抽象方法呢?

确实如此. 但是使用抽象类相当于多了一重编译器的校验.
使用抽象类的场景就如上面的代码, 实际工作不应该由父类完成, 而应由子类完成. 那么此时如果不小心误用成父类了,
使用普通类编译器是不会报错的. 但是父类是抽象类就会在实例化的时候提示错误, 让我们尽早发现问题.



很多语法存在的意义都是为了 "预防出错", 例如我们曾经用过的 final 也是类似. 创建的变量用户不去修改, 不就相当于常量嘛? 但是加上 final 能够在不小心误修改的时候, 让编译器及时提醒我们.
充分利用编译器的校验, 在实际开发中是非常有意义的
 

接口

接口是抽象类的更进一步. 抽象类中还可以包含非抽象方法, 和字段. 而接口中包含的方法都是抽象方法, 字段只能包含静态常量

代码示例:

interface IShape {
    void draw();
}
class Cycle implements IShape {
    @Override
    public void draw() {
        System.out.println("○");
    }
}
public class Test {
    public static void main(String[] args) {
        IShape shape = new Rect();
        shape.draw();
    }
}
  • 使用 interface 定义一个接口
  • 接口中的方法一定是抽象方法, 因此可以省略 abstract
  • 接口中的方法一定是 public, 因此可以省略 public
  • Cycle 使用 implements 继承接口. 此时表达的含义不再是 "扩展", 而是 "实现"
  • 在调用的时候同样可以创建一个接口的引用, 对应到一个子类的实例.
  • 接口不能单独被实例化

接口的作用:

我们上面说了一个类只能继承一个类,但是接口不同,一个类可以实现多个接口以此达到一个拓展的功能。
 

接口间的继承:
接口可以继承一个接口, 达到复用的效果. 使用 extends 关键字

interface IRunning {
    void run();
}
interface ISwimming {
    void swim();
}
// 两栖的动物, 既能跑, 也能游
interface IAmphibious extends IRunning, ISwimming {
}
class Frog implements IAmphibious {
...
}


通过接口继承创建一个新的接口 IAmphibious 表示 "两栖的". 
接口间的继承相当于把多个接口合并在一起
 


 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值