Java语言之包和继承详解

目录
  • 一、包
    • 包名
  • 类的导入与静态导入
    • 在包中添加类
    • 包访问权限
  • 二、继承
    • 类、超类与子类
      • 重写方法(override)
      • this与super的区别:
      • 子类构造器
      • protected关键字
      • 阻止继承:final关键字
      • 组合
  • 总结

一、包

包名

在讲包名前,我们先来了解一下,包是用来干什么的?

Java中允许使用包(package),包将类组织在一个集合中。借助包可以方便管理组织自己的代码,并将自己的代码与别人的提供的代码库分开管理。

包是组织类的一种方式。使用包的主要目的就是保证类的唯一性。

在Windows操作系统中,我们都知道,同一个文件夹下,不能同时出现两个一样的文件名的文件。而我们的java类,对应的就是一个.class文件,所以产生了包,而包其实就可以理解为路径中所存放的文件夹,为了出现重命的类名,所以将各个类分布在不同的包(文件夹)中。

而包名的命名:包名必须全部是小写字母,且一般包的命名方式是所在公司的官网(域名)的逆序写,假如www.xxxx.com,一般包名就是com.xxxx.——等等。

从编译器的角度来看,嵌套的包之间没有任何关系。例如:java.util包和java.util.jar包毫无关系。每一个包都是独立的类集合。

类的导入与静态导入

一个类可以使用所属包中的所有类,以及其他包下的公共类(public class)。

访问另一个包的类有两种方式:

1.使用完全限定名,也就是说在包名后面跟着类名。

java.util.Scanner scan = new java.util.Scanner(); //类名前面,直接跟包名

2.使用import关键字

import语句应该位于源文件的顶部,且位于package语句的后面。

import java.util.Scanner;
public class Main {
    public static void main(String[] args) {
        Scanner sc = new scanner();
    }
}

对于导包,我们还有一种比较简单的方式,如下

import java.util.*;

*,就是通配符。也就是在当前类中,可以直接使用util包的所有类,从而不需要再次导包了。值得注意的是,这里的导入,并不是导入util包下的所有类,这里跟C语言的include,不一样。C语言中的include,是导入头文件下的所有内容;而这里的import导入,只会在需要使用这个包下的类的时候,才会导入进来

当然,对于import导入包时,还需要特别注意一个问题,如下:

import java.util.*;
import java.sql.*;
public class Main {
    public static void main(String[] args) {
        Date date = new Date(); //error, java.util.Date 还是 java.sql.Date?
    }
}

此时进行编译,就会产生一个如上面代码的注释部分的错误。此时的编译器无法确定你想使用的是哪一个包下的Date类。现在就可以添加一个特定的import来解决这个问题。

import java.util.*;
import java.sql.*;
import java.util.Date; //特别指出是使用这个包下的Date类
public class Main {
    public static void main(String[] args) {
        Date date = new Date();
    }
}

如果此时,两个包中的Date都需要使用,那就只能使用完全限定名了。如下:

import java.util.*;
import java.sql.*;
public class Main {
    public static void main(String[] args) {
        java.util.Date date = new java.util.Date();
        java.sql.Date  date2 = new java.util.Date();
    }
}

静态导入

我们还可以使用静态导入包的方式,进行代码的缩写。使用import static 可以导入包中的静态方法和静态字段。这样就可以不必再加类名前缀。

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

只是有这样一种机制,可以进行代码的缩写,但在现实中,这样的代码,可能更不容易读懂。所以大家使用时,酌情考虑。

在包中添加类

如果要想将类放入包中,就必须将包的名字放在源文件的开头,即就是放在定义这个包中各个类的代码之前。如下:

如果没有在这个源文件的开头,写package语句,则这个源文件中类就属于无名包(unnamed package)。无名包没有包名。

基本规则:

  • 在源文件的最上方加一个package语句,可以指定该代码在哪个包
  • 包名尽量指定成唯一的名字,通常会使用公司的域名逆序形成
  • 包名要和代码路径相匹配。例如:package com.xxxx.demo,那么所对应的文件路径就是com/xxxx/demo
  • 如果一个源文件没有package语句,则该类会被放到无名包(默认包)中

IDEA建包过程:

包访问权限

在之前的文章中,我们介绍过publicprivate。而private修饰的方法或成员变量,只能在当前这个类中访问。

如果有个类,既没有写public,也没有写private访问修饰限定符,则此时这个(类、方法或成员变量)可以在包内部(当前文件夹下)的其他类中使用,但是不能在包外部(其他文件夹下)的类中使用。如下代码:

import com.xxxx.demo1;
//demo1 包
public class Main {
    public static void main(String[] args) {
        Test test = new Test(); //会报错,访问权限不够。
    }
}
//=====假设下面是第二个文件夹下的文件=====
import com.xxxx.demo2;
class Test { //访问修饰限定符:没写,我们就称为 默认
    public int number;
}
public class Demo2 {
    public int val;
}

访问修饰限定符权限:

范围 private 默认(default) protected public
同包同类 Y Y Y Y
同包不同类 Y Y Y
不同包,子类 Y Y
不同包,不同类 Y

其中,protected会在继承中讲到,我们继续往下看!!!

二、继承

继承的基本思想就是:在已有类的基础之上,创建新的类。继承已存在的类得到就是复用了(继承)这些类的方法,而且可以增加一些新的方法和成员变量。

类、超类与子类

我们先来举个例子,比如一只猫和一只狗。它们了分别有自己的名字、性别、还是吃东西等等的一些性质。如下图:

他们分别都有自己的这些特征,我们也可以很容易的发现,他们都有自己一些共有的特征:比如姓名,性别。所以如果我们分别在新建猫和狗的类,还得写专属于它们自己的成员变量,这样的话,就显得代码重复累赘,如下图这样:

我们可以很清晰的看到,红色框代码部分,就是一模一样的,所以出现了重复的代码。而且这两个类都是动物,所以说引出了一个继承中的一个概念:“is -a”关系。

也就是说,什么是一个什么这样的概念。就可能会用到继承。

那该怎么实现继承关系呢?我们来看下图:

我们可以使用extends关键字来实现继承关系,这样的话,猫和狗两个类,就能够同时实现name和sex字段。这就是继承。

此时猫和狗类,我们称为子类或者派生类。而Animal类我们称为父类基类超类

总结:

  • 使用extends指定父类
  • Java中一个子类只能继承一个父类。(而C++中可以实现多继承)
  • 子类会继承父类所有的public的字段和方法
  • 对于父类的private的字段和方法,子类是无法进行访问的
  • 子类的实例中,也包含这父类的实例。可以使用super关键字得到父类实例的引用。

重写方法(override)

像上图,子类和父类中,方法名和参数列表是一模一样的。我们就称为方法重写(override)。可能有人就会问,我该怎么调用相应的方法呢?

我们想调用Animal的eat方法,我们只需要new出一个Animal的对象,就能进行调用,当然,Cat类的实例对象也是如此。如果我们想在Cat类的实例对象调用父类的方法,则我们可以使用super关键字进行调用。如下图:

切记:

  • super关键字,在使用的时候,只能调用他的直接父类的方法或字段。比如:Animal类还继承了一个类,此时Cat类中,使用super,则只会调用Animal中的方法或字段。
  • 在子类中重写的方法,这个方法的访问修饰限定符的等级,应高于或等于父类的方法的访问修饰限定符。比如:父类中的eat方法是public修饰,而子类中的eat方法也应该是public,或者是更高的。(当然只是举个例子,public就是最高的访问修饰限定符了)
  • 被重写的方法,不能是被static修饰的

this与super的区别:

子类构造器

在上面说了,super关键字来调用父类的构造方法,那具体是如何进行调用的,我们来看一下具体的代码实现:

public class Cat extends Animal{
    public Cat(String name, String sex) {
        super(name, sex); //调用父类的构造方法,super语句必须在子类构造器的第一行
        System.out.println("Cat的构造方法");
    }
    public void eat() {
        System.out.println("吃鱼");
    }
}
public class Animal {
    public String name;
    public String sex;
    public Animal(String name, String sex) { //父类的构造方法
        this.name = name;
        this.sex = sex;
    }
    public void eat() {
        System.out.println("吃肉");
    }
}

总结:

  • 使用super构造方法的语句必须放在子类构造方法中的第一行。
  • 如果子类中,没有显示地调用父类的构造方法,将自动地调用超类的无参构造方法。
  • 在进行子类的实例化时,会调用子类的构造方法,而在调用子类构造方法时,将会先调用父类的构造方法。也就是说:new Cat ,实际上将先会新建出父类,在父类新建完成后,才会回到子类的构造方法,进行新建子类。

下面是一道有趣的题:请问下列代码的输出结果是什么。

class X {
    Y y=new Y();
    public X() {
        System.out.print("X");
    }
}
class Y {
    public Y() {
        System.out.print("Y");
    }
}
public class Z extends X {
    Y y=new Y();
    public Z() {
        System.out.print("Z");
    }
    public static void main(String[] args) {
        new Z();
    }
}

上面的代码的输出结果是:YXYZ。

分析:

  • 如果调用的是子类,那么在进入子类构造方法后,将先执行super语句(若没写,编译器自带),先构造父类。
  • 在父类构造完成后,再次回到子类的构造方法。此时将先初始化当前类的成员变量。
  • 在成员变量初始化之后,才会执行构造方法里面的语句。

上诉代码执行流程图:

protected关键字

在上文中,我写了一个访问修饰限定符的表,表中第3个protected关键字。

前面我们学了public和private访问修饰限定符,public的权限有大了,对于public来说,整个工程都可以进行使用;而对于private来说,只能在当前的类中进行使用。二者之前,一个权限过大,一个权限过小。所以在Java的继承中,还引入了这个关键字:protected;

对于protected来说,protected修饰的内容,在这个包下,可以直接使用。而在不同的包下,只有继承了这个类,才能在不同的包下使用该类被protected修饰内容。

阻止继承:final关键字

在前面的文章中,我们介绍过final关键字,final修饰的变量,在初始化之后,将不能被修改。

final int a = 10;
a = 20; //编译出错,此时的a被final修饰,存储在方法区,且不能被修改

final也能修饰类,,表示不能再被继承,称为密封类。

final还能修饰方法,表示此时的方法不能被重写,称为密封方法。

切记:如果一个类被final修饰,那么其中的方法将自动地称为final,但是不包括字段。如果一个方法没有被重写并且还很短,编译器将会对此进行优化处理,这个过程称为内联

组合

和继承类似的,还有一个叫组合的概念,也是用于表达类之间的关系,也能够达到代码的重复使用。

例如:一个公司由很多人组合而成,有当经理的、职员的、保洁员的等等……

class Person {
    public String name;
    public String sex;
}
class Manager extends Person { //继承 人
    //经理的薪水
    public double getSalary() {
    }
}
class Staff extends Person { //继承 人
    //普通职员的薪水
    public double getSalary() {
    }
}
//组合
public class Company {
    public Manager[] manager; //经理
    public Staff[] staff; //普通职员
}

组合并没有涉及到特殊的语法,仅仅只是将一个类的实例作为另一个类的字段,这也是我们设计类的一种常用的方式或思想。

组合表示has- a 的语义:意为:一个事物 由 什么组合而成,也就是包含的意思。

继承表示is-a的语义:意为:一个事物 是 一个什么事物的概念。

总结

本篇文章就到这里了,希望能够给你带来帮助,也希望您能够多多关注我们的更多内容!

(0)

相关推荐

  • 一篇文章带你入门Java继承

    目录 Java中继承 什么是继承: 为什么要用继承: 学习总结: 继承关键字:extends 总结 Java中继承 什么是继承: 继承就是子类继承父类的特征和行为,使得子类对象(实例)具有父类的实例域和方法,或子类从父类继承方法,使得子类具有父类相同的行为. 为什么要用继承: 可以去掉重复代码,方便后期维护 举个列子,大家应该都玩过英雄联盟,每个英雄都是一个类,如果说不用继承的话每次都要重复定义每个英雄的成员属性,如下图我举了一个MF,一个EZ的列子 public class MissFortu

  • Java初学之继承与多态

    目录 在程序中声明包的语法: Java继承语法格式: 什么是重写呢?: 多态应用: 引用变量的强制类型转换 instanceof 运算符 总结 首先我们如果要使用Java中存在的包,可以程序中使用import语句导入包.包说通俗点就是一个 文件夹,为了方便管理. 在程序中声明包的语法: package <包名> 注意:声明一个包的语句必须写在类中的第一行. 在程序中导入包的格式: import <包名>.<类名> 重点来了,继承! 继承是面向对象程序设计的一个重要特征,

  • Java继承的问题引导和测试代码

    目录 1.1.定义 1.2.创建子类 1.3.继承的基本规则 1. 子类可以继承除父类构造函数以外的一切成员 2. 虽然子类继承了父类的私有成员,但子类并不能直接访问,如果想要访问私有成员必须借助父类的公共接口. 3. 只支持单一继承,不支持多重继承,但支持多层继承 1.4.阻止继承 1.4.1.final修饰符 1. final 修饰的类不能被继承 2. final 修饰的方法不能被覆盖 3. final 修饰的变量(成员变量和局部变量)必须显式初始化,且只能初始化一次. 4. 常量定义的标准

  • 详解Java并发包基石AQS

    一.概述 AQS是一个用来构建锁和同步器的框架,使用AQS能简单且高效地构造出应用广泛的大量的同步器,比如我们提到的ReentrantLock,Semaphore,其他的诸如ReentrantReadWriteLock,SynchronousQueue,FutureTask等等皆是基于AQS的.当然,我们自己也能利用AQS非常轻松容易地构造出符合我们自己需求的同步器. 本章我们就一起探究下这个神奇的东东,并对其实现原理进行剖析理解 二.基本实现原理 AQS使用一个int成员变量来表示同步状态,通

  • Java基础之匿名内部类、包装类

    目录 1.匿名内部类 2.Object类简介 2.1 取得对象信息toString() 2.2 对象的比较equals() 2.3 Object接口引用数据类型 3.包装类 3.1 装箱与拆箱 3.2 字符串与基本数据类型的转换 3.3 包的定义 3.4 包的导入 4.访问控制权限 5.jar命令 1.匿名内部类 内部类:在一个类的内部定义了另外的类,称为内部类,匿名内部类指的是没有名字的内部类.为了清楚内部类的主要作用,下面首先观察一个代码. interface IMessage{ publi

  • Java 包装类型及易错陷阱详解

    目录 一.预备知识 1.1 Java内存管理 1.2 基本数据类型的包装类 1.3 包装类的构造方法 1.4 包装类的优缺点 1.5 包装类易错点 二.自动拆/装箱 三.整形池 四.优先选择基本数据类型 一.预备知识 1.Java把内存划分成两种:一种是栈内存,另一种是堆内存. 2.int是基本类型,直接存数值:而 Integer是类,产生对象时用一个引用指向这个对象. 3.包装器(wrapper)--这是<JAVA核心技术>一书中对Integer这类对象的称呼. 4.包装器位于java.la

  • Java语言之包和继承详解

    目录 一.包 包名 类的导入与静态导入 在包中添加类 包访问权限 二.继承 类.超类与子类 重写方法(override) this与super的区别: 子类构造器 protected关键字 阻止继承:final关键字 组合 总结 一.包 包名 在讲包名前,我们先来了解一下,包是用来干什么的? Java中允许使用包(package),包将类组织在一个集合中.借助包可以方便管理组织自己的代码,并将自己的代码与别人的提供的代码库分开管理. 包是组织类的一种方式.使用包的主要目的就是保证类的唯一性. 在

  • Java语言实现数据结构栈代码详解

    近来复习数据结构,自己动手实现了栈.栈是一种限制插入和删除只能在一个位置上的表.最基本的操作是进栈和出栈,因此,又被叫作"先进后出"表. 首先了解下栈的概念: 栈是限定仅在表头进行插入和删除操作的线性表.有时又叫LIFO(后进先出表).要搞清楚这个概念,首先要明白"栈"原来的意思,如此才能把握本质. "栈"者,存储货物或供旅客住宿的地方,可引申为仓库.中转站,所以引入到计算机领域里,就是指数据暂时存储的地方,所以才有进栈.出栈的说法. 实现方式是

  • Java关于jar包的知识详解

    在学习jar包之前,要先弄懂Java包,以及关于Java包的相关概念. 一.包 为了更好地组织类,Java提供了包机制.包是类的容器,用于分隔类名空间.如果没有指定包名,所有的示例都属于一个默认的无名包. 格式为: package pkg1[.pkg2[.pkg3-]]: 代码实例: package cn.com.zhouzhou;//包名一定要由小写字母组成 public class Lession1 { public static void main(String[] args) { Sys

  • 基于Java语言的递归运算例题详解

    目录 一.实例演示:递归求N的阶乘 二. 递归调用练习 递归求1+2+3+……10的和 顺序打印一个数字的每一位 返回一个数组成本身的数字之和 求解汉诺塔问题 求斐波那契数列第N项 递归定义:一个方法在执行过程中调用自身, 就称为 "递归". 递归的必要条件: 1. 将原问题划分成其子问题,注意:子问题必须要与原问题的解法相同. 2. 递归出口. 一.实例演示:递归求N的阶乘 public class fac { public static int factorial(int x){

  • Java面向对象编程之类的继承详解

    本文实例讲述了Java面向对象编程之类的继承.分享给大家供大家参考,具体如下: 继承:特殊类拥有一般类的全部属性与行为. 继承好处: 1.提高了代码的复用性 2.让类与类之前产生了关系,有了这个关系才有多态的特性.继承是类和类之前的关系. 注意事项: 1.java只支持单继承,不支持多继承.因为多继承有安全隐患:当多个父类定义相同的函数,但是功能不同时,子类不知道运行哪一个. 2.子类继承父类时,继承了父类的所有方法和属性,可直接使用. 3,java支持多层继承,即:孙-子-父的关系 语法: [

  • 关于为何说JAVA中要慎重使用继承详解

    前言 这篇文章的主题并非鼓励不使用继承,而是仅从使用继承带来的问题出发,讨论继承机制不太好的地方,从而在使用时慎重选择,避开可能遇到的坑. JAVA中使用到继承就会有两个无法回避的缺点: 打破了封装性,子类依赖于超类的实现细节,和超类耦合. 超类更新后可能会导致错误. 继承打破了封装性 关于这一点,下面是一个详细的例子(来源于Effective Java第16条) public class MyHashSet<E> extends HashSet<E> { private int

  • R语言ggplot2包之坐标轴详解

    引言 我们还可以对图形中的坐标轴进行处理,包括x.y轴对换.设定坐标轴范围.刻度线修改与去除等等.要想对图形玩得转,坐标轴处理精通不可或缺. 坐标轴对换 我们使用coord_flip()函数来对换坐标轴. library(ggplot2) library(gcookbook) ggplot(PlantGrowth, aes(x=group, y=weight)) + geom_boxplot() ggplot(PlantGrowth, aes(x=group, y=weight)) + geom

  • Java中的重要核心知识点之继承详解

    目录 一.继承 1.概念 2.语法 3.父类成员的访问 (1)子类中访问父类成员变量 (2)子类中访问父类成员方法 4.super关键字 5.子类构造方法 6.super和this 7.代码块执行顺序 8.父类成员在子类中的可见性 9.继承方式 10.final关键字 11.组合 一.继承 1.概念 继承(inheritance)机制:是面向对象程序设计使代码可以复用的最重要的手段,它允许程序员在保持原有类特 性的基础上进行扩展,增加新功能,这样产生新的类,称派生类.继承呈现了面向对象程序设计的

  • java编程小白进阶包的作用详解

    目录 步骤 1  工具包里面有很多个工具类 步骤 2  StringUtil 步骤 3  目前的情况 步骤 4  CLASSPATH 步骤 5  具体配置 步骤 6  package 步骤 7  验证 步骤 8  亲自做一遍 步骤 9  为什么现在用Editplus运行报错了? 步骤 10  说白了 步骤 11  包的作用 包的作用,1是为了防止类和方法的重名,2是为了管理众多的java类. 步骤 1  工具包里面有很多个工具类 之前讲了打印数据的方法:System.out.println,写这

  • Java三大特性之继承详解

    目录 概述 由来 定义 好处 继承的格式 继承后的特点—成员变量 成员变量不重名 成员变量重名 继承后的特点—成员方法 成员方法不重名 成员方法重名—重写(Override) 重写的应用 注意事项 继承后的特点—构造方法 概述 由来 多个类中存在相同属性和行为时,将这些内容抽取到单独一个类中,那么多个类无需再定义这些属性和行为,只要继承那一个类即可.如图所示: 其中,多个类可以称为子类,单独那一个类称为父类.超类(superclass)或者基类. 继承描述的是事物之间的所属关系,这种关系是: i

随机推荐