一文读懂包和继承

包是组织类的一种方式。使用包是为了保证类的唯一性(因为我们工作的时候,一个项目是由很多人来完成的,可能会出现相同的类名,所以可以把相同的类名写在不同的包里,就不用担心类名重复了。)

导入包中的类

在我们使用的时候,最先用到的就是 Java 的 util 包。比如输入一个数的时候,就要导入 util 包地下的 Scanner 类。语句是:

import java.util.Scanner;

当然也可以直接使用通配符 “*” 来导入,这样就可以使用 util 包下的所有类。

import java.util.*;

但是在使用中更建议写出具体的类名,因为如果两个包当中有相同的类的话,就会引起冲突,编译器不知道调用哪个包的类。就像下面这样:

import java.util.*;
import java.sql.*;
public class Test {
    public static void main(String[] args) {
        // util 和 sql 中都存在一个 Date 这样的类, 此时就会出现歧义, 编译出错
        Date date = new Date();
        System.out.println(date.getTime());
   }
}

因为不明确,所以就会报错:
在这里插入图片描述

静态导入

使用 import static 可以导入包中的静态的方法和字段。导入之后就可以不用写一些前缀名了。就像导入 Math :

import static java.lang.Math.*;
public class Test {
    public static void main(String[] args) {
        double x = 30;
        double y = 40;
        // 静态导入的方式写起来更方便一些. 
        // double result = Math.sqrt(Math.pow(x, 2) + Math.pow(y, 2));
        double result = sqrt(pow(x, 2) + pow(y, 2));
        System.out.println(result);
   }
}

这里导入了 Math 包中静态的方法,所以算 sqrt 和 pow 的时候就不用写 Math. 了。

将类放在包中

使用编译器的 package 来把类放到包中。在给包命名的时候,公司一般会用域名的颠倒形式。比如:百度是 www.baidu.com 写包名的时候就是 com.baidu.www
我用的是 IDEA 编译器,创建过程是这样的:
在这里插入图片描述
我的包名是 com.Lockey ,建好之后再在包里面创建三个小包,如图所示:
在这里插入图片描述
然后在 test 里面创建名为 Test 的 class 文件,代码内容如下:

package com.lockey.test;  //说明包的目录
public class Test {
    int val = 10;
}

在这里创建之后,因为是 public 权限,所以在其它包下的所由目录都可以访问,但是在包外面就访问不到了。这就是包访问权限。

常见的系统包

  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编程开发包。

继承

在创建的类当中,是为了给一些抽象的事物提供一些方法。如果一些类、一些食物有共同的属性,那么就可以把这些属性封装为一个类。然后其它事物有这个属性的时候,就去继承这个类。通过 extends 关键字去继承。就比如说:猫和鸟,它们的共同特点都有名字和吃。所以就可以把名字和吃放在一个类里面。然后让它们去继承,降低代码量。把被继承的这个类叫做 Animal 可以发现猫和鸟对于 Animal 都是一种 is-a 的关系。在继承的时候,也会继承父类(Animal)的字段和方法。

语法

class 子类 extends 父类 { 
 
} 

所以上面的例子写出代码就是这样:

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);
    }
}
class Bird extends Animal {
    public Bird(String name) {
        super(name);
    }
    public void fly() {
        System.out.println(this.name + "正在飞 ︿( ̄︶ ̄)︿");
    }
}
public class Test4 {
    public static void main(String[] args) {
        Cat cat = new Cat("小黑");
        cat.eat("猫粮");
        Bird bird = new Bird("圆圆");
        bird.fly();
    }
}

子类在调用父类的构造方法的时候,要用到 super 关键字。用 super 关键字去把参数传进去。运行结果如下:
在这里插入图片描述
bird 就是在 Animal 继承的基础上又扩展出了 fly 方法。
如果把 name 的 public 改成 private 那么子类就访问不到了:

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

就会报这样的错误:
在这里插入图片描述

protected 关键字

因为把访问权限设置为 private 就会导致子类不能访问。如果是 public 就会导致失去封装的意义。所以就可以使用 protected 。因为对于类的子类和同一个包的其他类来说,protected 修饰的字段是可以访问的

class Animal {
    protected 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);
    }
}
class Bird extends Animal {
    public Bird(String name) {
        super(name);
    }
    public void fly() {
        System.out.println(this.name + "正在飞 ︿( ̄︶ ̄)︿");
    }
}
public class Test4 {
    public static void main(String[] args) {
        System.out.println("保护权限下的访问");
        Cat cat = new Cat("小黑");
        cat.eat("猫粮");
        Bird bird = new Bird("圆圆");
        bird.fly();
    }
}

在这里插入图片描述
可以发现:在保护权限下,也可以访问到。

Java 对于字段和方法的四种访问权限

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

访问情况如下图所示:
在这里插入图片描述
访问权限的使用
1、我们希望类要尽量做到 “封装”, 即隐藏内部实现细节, 只暴露出 必要 的信息给类的调用者。因此我们在使用的时候应该尽可能的使用 比较严格 的访问权限. 例如如果一个方法能用 private ,就尽量不要用 public 。
2、另外, 还有一种 简单粗暴 的做法: 将所有的字段设为 private, 将所有的方法设为 public. 不过这种方式属于是对访问权限的滥用, 还是更希望同学们能写代码的时候认真思考, 该类提供的字段方法到底给 “谁” 使用(是类内部自己用, 还是类的调用者使用, 还是子类使用)。

继承的注意事项

在刚刚的例子当中,我们仅仅涉及到三种类。但是我们逻辑上可以有很多种的继承,可以一直继承下去。所以我们在使用到中,尽量不要超过三层。因为超过三层会导致类之间的关系变得更加复杂。当然,如果不想被继承的话,就可以使用 final 关键字来修饰类。

final 关键字

之前学过,用 final 来修饰常数的时候,这个数不能被修改。所以用 final 来修饰类的时候,此时被修饰的类就不能被继承。

final 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);
    }
}
class Bird extends Animal {
    public Bird(String name) {
        super(name);
    }
    public void fly() {
        System.out.println(this.name + "正在飞 ︿( ̄︶ ̄)︿");
    }
}
public class Test4 {
    public static void main(String[] args) {
        Cat cat = new Cat("小黑");
        cat.eat("猫粮");
        Bird bird = new Bird("圆圆");
        bird.fly();
    }
}

就会报这样的错误:
在这里插入图片描述

组合

组合和继承类似,也是类之间的一种关系,也能达到代码重用。就是把一个类的实例作为另外一个类的字段。就像表示一个学校:

public class Student { 
 ...
}
public class Teacher { 
 ...
}
public class School {
    public Student[] students;
    public Teacher[] teachers;
} 

这里就是把学生和老师作为学校的字段。
组合和继承的区别:
组合表示 has - a 语义
在刚才的例子中, 我们可以理解成一个学校中 “包含” 若干学生和教师.
继承表示 is - a 语义
在上面的 “动物和猫” 的例子中, 我们可以理解成一只猫也 “是” 一种动物.

  • 10
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 5
    评论
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Lockey-s

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值