Java初阶之包的使用与继承

目录

前言

一、包的使用

1.访问修饰符

2.包

3.包的导入

4.包访问权限

二、继承

1.继承的实现

2.继承的使用规则

3.访问父类的属性

4.在子类中调用父类的方法

5.父子类对象的产生

三、组合与继承

四、final的用法

1.final修饰属性

2.被final修饰的方法不能被重写

3.被final修饰的类不能被继承

总结


前言

在Java初阶之包的使用与继承学习中,我通过总结以及查阅资料,对以下问题有了更深一层的理解。

  1. 访问修饰符有哪些?他们的权限大小是如何排序的?
  2. 什么是包?常见的包有哪些?包是如何导入的?什么是包访问权限?
  3. 继承是如何实现的?继承的使用规则有哪些?
  4. 如何进行父类属性的访问?在子类中如何调用父类方法?
  5. 父子类对象如何产生?如何调用父类的构造方法?
  6. 组合与继承的典型表现是什么?
  7. final的用法有哪些?

如果你在Java初阶之包的使用与继承的学习中,也想对这些问题有一个更深的了解,请阅读这篇文章,或许会对你有所启发。

一、包的使用

1.访问修饰符

在Java中一共有四个关于权限的关键字,依从权限从小到大为private<default<protected<public

public//公共的
protected//受保护的
default//默认的
private//私有的
  • private是私有访问权限,仅在当前类的内部可见,是一种封装的体现
  • default是默认访问权限,同一个包中的类可以访问,什么时没有加修饰符,认为是friendly
  • protected是继承访问权限,在不同包(和父类不同包)的子类可见
  • public是公共访问权限,可以被所有其他类所访问

2.包

包其实就是操作系统的一个文件夹,包访问权限,就是访问权限什么也不需要写,只有在当前这一级文件夹的内部可见,正因为有包访问权限的存在,可以在不同的包中创建同名的类,类似在操作系统的同一个文件夹内不能创建多个同名同类型的文件,但是在不同文件夹中,可以创建多个同名称同类型的文件,在Java中类的全名称是包名,类名,一个类使用package关键字来声明该类属于哪个包下。

JDK中常见的包有:

  • java.lang:系统常用的基础类,String,Object,Math
  • java.lang.reflext:反射开发包
  • java.util:java提供的工具开发包(所有集合类ArrayList,LinkedList,HashMap等) 
  • java.sql:java数据库开发相关的包
  • java.io:IO开发包(文件的操作)

3.包的导入

在Java中提供了很多现成的类供开发者使用,例如Data类,日期类,在java.util包下有Data类,在java.sql包下也有Data类,因此我们在具体使用的时候就要使用全名称,可以使用关键字import告知编译器导入包,假设我们现在在当前类中还需要使用java.util这个包中的其他类我们就可以用通配符*来表示导入,也就是import java.util.*导入util包,需要哪个就导入哪个,需要我们注意的是import关键字表示在java中导入某个包中的某个具体的类,无法直接导入一个文件夹的。

4.包访问权限

包访问权限是指在同一个包中可见,仅限于当前这个包中的所有类之间可见,其他包包括子包都不行。

代码展示:

public class Person{
    String name;
    int age;
    void show(){
        System.out.println();
    }
}

下图中,Person和Test都属于同一级包,因此Person中的包访问权限对于Test类是可见的。

二、继承

1.继承的实现

将若干个不同的类之间相同的属性和方法抽象为一个共同的父类,子类只需要扩展自己类中独有的属性和方法即可,把这种编程特性,称之为“继承”,要想使用继承,能发生继承的类之间必须满足is a原则,比如Dog is an Animal,Cat is an Animal。在Java中使用extends表示继承一个父类,父类中的所有属性和行为都会被子类继承下来,子类只需要关心实现自己独有的属性和行为即可,大大减少了重复代码,实现了代码的复用,扩展新的子类就更加容易。

2.继承的使用规则

在Java中,类的继承是单继承,一个类智能使用extends关键字继承一个父类,Java不允许多重继承,但是允许多层继承,一般多层继承最多不超过3层关系。

错误代码展示:

正确代码展示:

class A {
    int a;
}
class B extends A{
    int b;
}
public class C extends B{
    public static void main(String[] args) {
        C c = new C();
        System.out.println(c.a);
        System.out.println(c.b);
    }
}

关于继承方面的隐式继承和显示继承,隐式继承就是父类中的某些属性和方法,子类继承下来了,但是无法直接使用,显示继承就可以随时使用。

3.访问父类的属性

子类要想直接访问父类的属性,父类中的属性权限必须大于等于protected的访问权限,若继承是显示继承,使用父类的属性,可以直接使用,此时必须是子类中没有和父类同名的属性,那若子类也定义了父类相同名称的属性呢?此时就又要用到我们之前提到的程序开发的就近匹配原则,编译器会率先在方法中寻找,再在当前类的内部寻找变量,也就是在子类中寻找,最后去父类中寻找同名变量,这时我们可以发现,父类中的同名变量就被子类覆盖了,那若是父类和子类变量名称相同,但是类型不同,访问的又该是什么呢?其实只要在子类中定义了和父类名称相同的属性,无关类型使用相同名称时,调用的都是子类中覆盖后的变量!

代码展示:

public class Derived extends Base{
    int a;
    int c;
    int d;

    public static void main(String[] args) {
        Derived derived=new Derived();
        derived.b=20;
        derived.c=30;
        derived.d=40;
        //到底访问的是子类中的a属性还是父类中的a属性呢?
        System.out.println(derived.a);
    }
}

如果要想在子类中调用被覆盖的父类中同名属性,需使用super关键字,super是用来修饰属性的,明确表示直接从父类中寻找同名属性,表达式为super.

代码展示:

public class Derived extends Base{
    int a;
    int c;
    int d;

    public static void main(String[] args) {
        Derived derived=new Derived();
        derived.test();
    }
    public void test(){
        //调用子类中的a属性
        System.out.println(a);
        //调用父类中被覆盖的属性a,使用super关键字
        System.out.println(super.a);
    }
}

4.在子类中调用父类的方法

public class Derived extends Base{
    int a;
    int c;
    int d;

    public static void main(String[] args) {
        Derived derived=new Derived();
        derived.testA();
        derived.testB();
    }
    public void testB(){
        System.out.println("子类中的testB方法");
    }
}

从上述代码中我们可以看到testA在子类中不存在,继续去父类中寻找同名方法,若子类定义了和父类名称完全相同的方法呢?此时就要提出一个新的名词,叫方法重写,方法重写英文表示override,是指发生在有继承关系的类之间,子类定义了和父类除了权限不同以外其他全部相同,包括名称,参数列表,返回值都相同的方法,我们要保证的是子类重写后的方法权限大于等于父类的权限,要想在子类中调用被覆写后的父类方法,使用super.方法名称()表示直接从父类中寻找同名方法。

5.父子类对象的产生

当调用子类构造方法产生子类对象时,JVM首先调用父类的构造方法先产生父类对象而后产生子类对象。

代码展示:

public class Derived extends Base{
    int a;
    int c;
    int d;

    public Derived(){
        //显示使用super表示调用父类的有参构造
        super('a');
        System.out.println("子类Derived的构造方法");
    }
}

结果展示:

调用父类的构造方法要使用 super关键字,若调用的是父类的无参构造,super可以不写;若调用的是父类的有参构造,则必须在参数列表显示使用super,明确表示先调用父类的构造方法。在子类中我们既可以使用super关键字来调用父类的构造方法,也可以用this关键字进行调用,调用父类构造方法时,super必须放在子类构造方法的首行,this的构造方法调用也得放首行,this和super表示构造方法调用时,不能同时出现。

super调用错误代码展示:

public class Derived extends Base{
    int a;
    int c;
    int d;

    public Derived(){
        this(10);
        //显示使用super表示调用父类的有参构造
        super('a');
        System.out.println("子类Derived的构造方法");
    }

结果展示:

this调用错误代码展示:

public class Derived extends Base{
    int a;
    int c;
    int d;

    public Derived(){
        //显示使用super表示调用父类的有参构造
        super('a');
        this(10);
        System.out.println("子类Derived的构造方法");
    }

结果展示:

this可以表示当前对象的引用,但是super没有这个特点,只能引用父类的属性或方法,super在引用父类构造方法时必须放首行,super和this都表示成员域的属性,它们有一个共同的特点是都不能在静态域中直接使用。

三、组合与继承

组合与继承讲的其实是类和类之间的关系,学生类和人类就是典型的继承关系,继承满足is a原则,继承关系的类之间是个树状结构。

代码展示:

class Person{
    public void sleep(){
        System.out.println("正在呼呼大睡");
    }
    public void eat(){
        System.out.println("正在大口大口吃");
    }
}
class Student extends Person{
    @Override
    public void eat(){
        System.out.println("正在大口大口吃");
    }

    public static void main(String[] args) {
       Student s=new Student();
       s.sleep();
       s.eat();
    }
}

说到组合,学生类和学校类就是最典型的组合关系,组合满足has a原则。

代码展示:

class School{
    public void school(){
        System.out.println("school");
    }
}
class Student{
    public void student(){
        System.out.println("student");
    }
}
class Study{
    public void study(){
        new School().school();
        new Student().student();
    }
}
public class Test{
    public static void main(String[] args) {
        new Study().study();
    }
}

四、final的用法

1.final修饰属性

final表示终极器,到此为止的意思,final修饰的属性,值无法修改,使用final关键字来定义常量。

  • final修饰基本数据类型,值不能修改,数值在定义后无法修改
final int a=10;
System.out.println(a);
a=20;
System.out.println(a);
//其中a表示一个常量,定义后值无法修改,只能保存10
  •  final修饰引用数据类型,值不能改,这个值指的是引用保存的地址不能改,但是地址中包含的内容依旧可以修改。
//final修饰引用数据类型,引用指向的地址值不能修改
//arr引用保存的地址值不能修改
//此时arr只能指向这个数组
final int[] arr=new int[3];
arr[0]=10;
arr[1]=20;
System.out.println(Arrays.toString(arr));
int[] arr1=new int[10];
arr=arr1;

2.被final修饰的方法不能被重写

当使用final修饰方法时,这个方法将成为最终方法,不允许被子类覆盖,但是该方法仍然可以被继承。

代码展示:

class Aniaml {
    public final void bark(){
        System.out.println("叫");
    }
    public void eat(){
        System.out.println("吃");
    }
}
class Dog extends Animal{
    //final修饰的方法不能被重写,但此方法仍然可以被继承
    public void eat(){
        System.out.println("狗在吃骨头");
    }
}
public class Test{
    public static void main(String[] args) {
        Dog d=new Dog();
        d.bark();
    }
}

3.被final修饰的类不能被继承

被final修饰的类不能被继承意味着final修饰的类没有子类,JDK中的String类就是一个典型的final,类,那为何String类要使用final修饰?这是保证JDK的使用者,大家用到的String类完全一模一样,没有任何别的版本。

总结

以上就是今天所讲内容,希望大家都能熟练掌握!

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值