@

茫茫人海千千万万,感谢这一秒你看到这里。希望我的文章能对你的有所帮助!共勉!

愿你在未来的日子,保持热爱,奔赴山海!

Java基础知识(封装和继承)

一. 封装

那封装是什么呢?

在面向对象程式设计方法中,封装(英语:Encapsulation)是指一种将抽象性函式接口的实现细节部分包装、隐藏起来的方法。

1.1 封装的目的

  • 直接通过操控类对象来达到目的,不需要对具体实现十分了解,使类属性和方法的具体实现对外不可见。不但方便还起到了保护作用。
  • 封装最主要的功能在于我们能修改自己的实现代码,而不用修改那些调用我们代码的程序片段。
  • 适当的封装可以让程式码更容易理解与维护,也加强了程式码的安全性。

1.2 封装的好处

  • 良好的封装能够减少耦合。
  • 类内部的结构可以自由修改。
  • 可以对成员变量进行更精确的控制。
  • 隐藏信息,实现细节。

1.3 封装的步骤

  1. 修改属性的可见性来限制对属性的访问(一般限制为private),例如:

    public class Person {
    private String name ; // 姓名
    private String gender ; // 性别
    private int age; // 年龄
    }

    这段代码中,将 namesexage 属性设置为私有的,只能本类才能访问,其他类都访问不了,如此就对信息进行了隐藏。

  2. 对每个值属性提供对外的公共方法访问,也就是创建一对赋取值方法,用于对私有属性的访问,例如:

    public class Person {
    private String name ; // 姓名
    private String gender ; // 性别
    private int age; // 年龄 public void setName(String name) {
    this.name = name;
    } public String getName() {
    return name;
    } public void setGender(String gender) {
    this.gender = gender;
    } public String gender(){
    return gender;
    } public void setAge(int age) {
    this.age = age;
    } public int getAge() {
    return age;
    }
    }

    采用 this 关键字调用本类中的属性,也就是类中的成员变量。主要为了解决实例变量(private String name)和局部变量(setName(String name)中的name变量)之间发生的同名的冲突。

1.4 封装的例子

  • 创建一个用户类User:

    代码如下:

    package com.nz.pojo;
    
    public class User {
    private String username; // 用户名
    private String password; // 密码 public String getUsername() {
    return username;
    } public void setUsername(String username) {
    this.username = username;
    } public String getPassword() {
    return password;
    } public void setPassword(String password) {
    this.password = password;
    }
    }
  • 编写测试User的demo:EncapsulationDemo

    代码如下:

    package com.nz;
    
    import com.nz.pojo.User;
    
    public class EncapsulationDemo {
    public static void main(String[] args) {
    User user = new User();
    user.setUsername("太子爷哪吒");
    user.setPassword("520");
    System.out.println("username: " + user.getUsername() + "-----------"
    + "password: " + user.getPassword());
    }
    }

    执行结果如下:

    username:太子爷哪吒-----------password520

1.5 小结

封装实际上是将类的某些信息隐藏在类的内部,不允许外部程序直接访问,而是通过该类提供的方法来实现对隐藏信息的访问和操作。就是把我们想提供给外界的一些方法给暴露出来,以便外界能调用到我们。

二. 继承

2.1 继承的介绍

继承是java面向对象编程技术的一块基石,因为它允许创建分等级层次的类。描述的是事物之间的所属关系,这种关系是:is-a 的关系。

继承:就是子类继承父类的属性行为,使得子类对象(实例)可以直接具有与父类相同的属性、相同的行为。子类可以直接访问父类中的非私有的属性和行为。

2.2 生活中的继承

兔子和长颈鹿属于食草动物类,老虎和狮子属于食肉动物类。而食草动物和食肉动物又是属于动物类。

那是不是兔子、长颈鹿、老虎、狮子都属于动物类呢?答案是没错滴!虽然食草动物和食肉动物都是属于动物,但是两者的属性和行为上有差别,所以子类会具有父类的一般特性也会具有自身的特性。我们就可以再多个类中存在相同属性和行为时,我们可以将这些内容抽取到单独一个类中,那么多个类无需再定义这些属性和行为,只要继承那一个类即可。

2.3 继承的好处

  1. 提高代码的复用性(减少代码冗余,相同代码重复利用)。
  2. 使类与类之间产生了关系。
  3. 子类拥有父类非 private 的属性、方法。
  4. 子类可以拥有自己的属性和方法,即子类可以对父类进行扩展。
  5. 子类可以用自己的方式实现父类的方法。
  6. 提高了类之间的耦合性(继承的缺点,耦合度高就会造成代码之间的联系越紧密,代码独立性越差)。
  7. Java 的继承是单继承,但是可以多重继承,单继承就是一个子类只能继承一个父类,多重继承就是,例如 B 类继承 A 类,C 类继承 B 类,所以按照关系就是 B 类是 C 类的父类,A 类是 B 类的父类,这是 Java 继承区别于 C++ 继承的一个特性。

2.4 继承的格式

在Java当中会通过extends关键字可以申明一个类是从另外一个类继承而来的,一般形式如下:

class 父类 {
} class 子类 extends 父类 {
}

需要注意一点: Java 不支持多继承,但支持多重继承。就如下:

class A {
} class B extends A { (对的)
} class C extends A, B { (错的)
} class C extends B { (对的)
}

顶层父类是Object类。所有的类默认继承Object,作为父类。

2.5 继承的demo

  • 编写一个父类极其对应的子类信息

    结构如下:

    代码如下:

    父类Person:

    package com.nz.pojo;
    
    public class Person {
    private String name ;
    private int age ; public String getName() {
    return name;
    } public void setName(String name) {
    this.name = name;
    } public int getAge() {
    return age;
    } public void setAge(int age) {
    this.age = age;
    }
    }

    子类Student没有额外的属性和方法:

    package com.nz.pojo;
    
    /**
    * 继承了Person特有的name, age,
    * 没有额外的独有属性和方法
    */
    public class Student extends Person{
    }

    子类Teacher多了一个工资的属性和独有的教书方法:

    package com.nz.pojo;
    
    /**
    * 继承了Person特有的name, age,
    * 多了自己独有的工资属性还有独有的教书方法
    */
    public class Teacher extends Person{ // 工资
    private double salary ; // 特有方法
    public void teach(){
    System.out.println("老师在认真教书!");
    } public double getSalary() {
    return salary;
    } public void setSalary(double salary) {
    this.salary = salary;
    }
    }
  • 编写测试代码:

    package com.nz;
    
    import com.nz.pojo.Student;
    import com.nz.pojo.Teacher; public class InheritDemo {
    public static void main(String[] args) {
    Teacher teacher = new Teacher();
    teacher.setName("太子爷哪吒");
    teacher.setAge(18);
    teacher.setSalary(1999.99);
    System.out.println(teacher.getName());
    System.out.println(teacher.getAge());
    System.out.println(teacher.getSalary());
    teacher.teach(); Student student = new Student();
    student.setName("哪吒");
    student.setAge(12);
    //student.setSalary(1999.99); // student没有工资属性,报错!
    System.out.println(student.getName());
    System.out.println(student.getAge());
    }
    }

    结果如下:

    太子爷哪吒
    18
    1999.99
    老师在认真教书!
    哪吒
    12

    从结果来看,子类继承父类,就可以直接得到父类的成员变量和方法。而子类可以编写一些特有的属性和方法,但是是否可以继承所有成分呢?

2.6 子类不能继承的内容

并不是父类的所有内容都可以给子类继承的:

2.6.1 super 与 this 关键字

这里先将这两个关键字,super和this在继承关系中,运用比较频繁。

  • super关键字:我们可以通过super关键字来实现对父类成员的访问,用来引用当前对象的父类。

  • this关键字:指向自己本类的引用。

    super和this完整的用法如下:

    this.成员变量    	--    本类的
    super.成员变量 -- 父类的 this.成员方法名() -- 本类的
    super.成员方法名() -- 父类的
  • 具体演示,创建测试InheritDemo2:

    package com.nz;
    
    public class InheritDemo2 {
    public static void main(String[] args) {
    Animal a = new Animal();
    a.eat();
    Cat cat = new Cat();
    cat.eatFish();
    }
    } class Animal {
    void eat() {
    System.out.println("animal : eat");
    }
    } class Cat extends Animal {
    void eat() {
    System.out.println("cat : eat");
    }
    void eatFish() {
    this.eat(); // this 调用自己的方法
    super.eat(); // super 调用父类方法
    }
    }

    调用结果如下:

    animal : eat
    cat : eat
    animal : eat
  • 注意:

    子类的每个构造方法中均有默认的super(),调用父类的空参构造。手动调用父类构造会覆盖默认的super()。

    super() 和 this() 都必须是在构造方法的第一行,所以不能同时出现。

2.6.2 构造器不能被继承

  • 子类不能继承父类的构造器(构造方法或者构造函数),它只是调用(隐式或显式)。因为子类有自己的构造器。值得注意的是子类可以继承父类的私有成员(成员变量,方法),只是子类无法直接访问而已,可以通过getter/setter方法访问父类的private成员变量。

  • 如果父类的构造器带有参数,则必须在子类的构造器中显式地通过super 关键字调用父类的构造器并配以适当的参数列表。

  • 如果父类构造器没有参数,则在子类的构造器中不需要使用 super 关键字调用父类构造器,系统会自动调用父类的无参构造器。

  • 演示过程:

    package com.nz;
    
    public class InheritDemo3  {
    public static void main(String[] args) {
    System.out.println("------Teacher 类继承------");
    Teacher teacher = new Teacher();
    Teacher teacher2 = new Teacher("张三");
    System.out.println("------Student 类继承------");
    Student student = new Student();
    Student student2 = new Student("张三三");
    }
    }
    // 父类
    class Person {
    private String name;
    Person(){
    System.out.println("调用了父类的无参构造器: Person()");
    }
    Person(String name) {
    System.out.println("调用了父类的带参构造器: Person(String name)");
    this.name = name;
    }
    }
    // Teacher子类继承Person
    class Teacher extends Person{
    private String name;
    Teacher(){
    // 自动调用父类的无参数构造器 因为会有默认super();
    System.out.println("Teacher");
    } public Teacher(String name){
    super("太子爷哪吒"); // 调用父类中带有参数的构造器
    System.out.println("Teacher(String name):"+name);
    this.name = name;
    }
    }
    // Student子类继承Person
    class Student extends Person{
    private String name; Student(){
    super("heihei"); // 调用父类中带有参数的构造器
    System.out.println("SubClass2");
    } public Student(String name){ // 自动调用父类的无参数构造器
    System.out.println("Student(String name):"+name);
    this.name = name;
    }
    }

    结果如下:

    ------Teacher 类继承------
    调用了父类的无参构造器: Person()
    Teacher
    调用了父类的带参构造器: Person(String name)
    Teacher(String name):张三
    ------Student 类继承------
    调用了父类的带参构造器: Person(String name)
    SubClass2
    调用了父类的无参构造器: Person()
    Student(String name):张三三

2.6.3 final修饰的类不能被继承

final 关键字主要用在三个地方:变量、方法、类。

  1. 修饰类:表示该类不能被继承;
  2. 修饰方法:表示方法不能被重写;
  3. 修饰变量:表示变量只能一次赋值以后值不能被修改(常量)。

final 的特点:

  • 对于一个 final 变量,如果是基本数据类型的变量,则其数值一旦在初始 化之后便不能更改;如果是引用类型的变量,则在对其初始化之后便不 能再让其指向另一个对象。
  • 当用 final 修饰一个类时,表明这个类不能被继承。final 类中的所有成员 方法都会被隐式地指定为 final 方法。
  • 使用 final 方法的原因有两个。第一个原因是把方法锁定,以防任何继承 类修改它的含义;第二个原因是效率。在早期的 Java 实现版本中,会将 final 方法转为内嵌调用。但是如果方法过于庞大,可能看不到内嵌调用 带来的任何性能提升(现在的 Java 版本已经不需要使用 final方法进行这些优化了)。类中所有的 private 方法都隐式地指定为 final。

我们测试下修饰类后到底能不能继承:

package com.nz;

public class InheritDemo4 {
} // 父类
final class Fu {
private String name;
} //class Zi extends Fu{ // Cannot inherit from final 'com.nz.Fu' 会显示没办法继承Fu
//}

结果:可以看出来在被final修饰的Fu类没办法继承,而且在编译期间就会报错了,没办法通过运行。

2.7 方法重写

2.7.1 介绍

子类中出现与父类一模一样的方法时(返回值类型,方法名和参数列表都相同),会出现覆盖效果,也称为重写或者复写。声明不变,重新实现

2.7.2 使用场景与案例

发生在子父类之间的关系。

子类继承了父类的方法,但是子类觉得父类的这方法不足以满足自己的需求,子类重新写了一个与父类同名的方法,以便覆盖父类的该方法。

写个测试案例:

package com.nz;

public class InheritDemo5 {

    public static void main(String[] args) {
// 创建子类对象
Cat lanMao = new Cat();
// 调用父类继承而来的方法
lanMao.run();
// 调用子类重写的方法
lanMao.sing(); }
} class Animal{
public void sing(){
System.out.println("动物都可以唱歌!");
}
public void run(){
System.out.println("动物都可以跑!");
}
} class Cat extends Animal {
public void sing(){
System.out.println("我们一起学猫叫,一起喵喵喵!让我们一起撒个娇");
}
}

运行结果:

动物都可以跑!
我们一起学猫叫,一起喵喵喵!让我们一起撒个娇

可以看出,蓝猫调用了重写后的sing方法。

2.7.2 @Override重写注解

  • @Override:注解,重写注解校验

  • 这个注解标记的方法,就说明这个方法必须是重写父类的方法,否则编译阶段报错。

  • 建议重写都加上这个注解,一方面可以提高代码的可读性,一方面可以防止重写出错!

    加上后的子类代码形式如下:

    class Cat extends Animal {
    // 声明不变,重新实现
    // 方法名称与父类全部一样,只是方法体中的功能重写了!
    @Override
    public void sing(){
    System.out.println("我们一起学猫叫,一起喵喵喵!让我们一起撒个娇");
    }
    }

2.7.3 注意事项

  1. 方法重写是发生在子父类之间的关系。
  2. 子类方法覆盖父类方法,必须要保证权限大于等于父类权限。
  3. 子类方法覆盖父类方法,返回值类型、函数名和参数列表都要一模一样。

2.8 小结

继承是使用已存在的类的定义作为基础建立新类的技术,新类的定义可以增加新的数据或新的功能,也可以用父类的功能,但不能选择性地继承父类。通过使用继承我们能够非常方便地复用以前的代码。

注: 如果文章有任何错误和建议,请各位大佬尽情留言!如果这篇文章对你也有所帮助,希望可爱亲切的您给个三连关注下,非常感谢啦!也可以微信搜索太子爷哪吒公众号进行私聊我,感谢各位大佬!

Java基础-封装和继承的更多相关文章

  1. Java面向对象封装和继承

    面向对象 什么是面向过程.面向对象? 面向过程与面向对象都是我们编程中,编写程序的一种思维方式. 面向过程的程序设计方式,是遇到一件事时,思考“我该怎么做”,然后一步步实现的过程.例如:公司打扫卫生( ...

  2. Java之封装,继承,多态

    一,前言 ​ 今天总结一下关于Java的三大特性,封装,继承,多态.其实关于三大特性对于从事编程人员来说都是基本的了,毕竟只要接触Java这些都是先要认识的,接下来就系统总结一下. 二,封装 ​ 先来 ...

  3. Java基础笔记-抽象,继承,多态

    抽象类: abstract修饰 抽象方法必须定义在抽象类中,抽象类不能创建对象. 在抽象方法中可以不定义抽象方法,作用是:让该类不能建立对象. 特点是: 1.定义在抽象类中 2.方法和类都用abstr ...

  4. Java基础学习笔记七 Java基础语法之继承和抽象类

    继承 继承的概念 在现实生活中,继承一般指的是子女继承父辈的财产.在程序中,继承描述的是事物之间的所属关系,通过继承可以使多种事物之间形成一种关系体系. 例如公司中的研发部员工和维护部员工都属于员工, ...

  5. Java基础教程(18)--继承

    一.继承的概念   继承是面向对象中一个非常重要的概念,使用继承可以从逻辑和层次上更好地组织代码,大大提高代码的复用性.在Java中,继承可以使得子类具有父类的属性和方法或者重新定义.追加属性和方法. ...

  6. java中封装,继承,多态,接口学习总结

    ### 一:封装java中封装是指一种将抽象性函式接口的实现细节部分包装.隐藏起来的方法. 封装可以被认为是一个保护屏障,防止该类的代码和数据被外部类定义的代码随机访问.要访问该类的代码和数据,必须通 ...

  7. Java基础系列 - 抽象类继承和接口实现

    package com.inter; /** * 继承和接口的关系,单继承,多接口 * java不支持多继承,但可通过接口实现多重继承 */ public class test2 { public s ...

  8. Java基础第一天--继承、修饰符

    继承 继承的概述: 继承是面向对象三大特征之一.可以使得子类具有父类的属性和方法,还可以在子类中重新定义,追加属性和方法. //创建父类 public class Fu{ public void sh ...

  9. java基础(六)之继承初探

    什么是继承? 一个类得到了另一个类当中的成员变量和成员方法.java只支持单继承.一个子类只允许继承一个父类,一个父类可以被多个子类继承. 比如下面的一个例子, 先创建一个Person类 class ...

随机推荐

  1. 不同规模的企业对CRM的需求是否相同?

    CRM客户管理系统在我们的认知中往往是中大型企业的选择.如今,越来越多中小规模企业开始使用CRM系统.CRM的功能随着发展变得越来越实用,可以满足不同行业不同业务规模的企业的需求.同时,CRM功能类型 ...

  2. goland mod模式下不从vendor文件夹查找依赖

    goland使用vendor作为获取依赖源 软件版本: system:windows10 1709 terminal: wsl ubuntu1804 goland:201903 goland 打开项目 ...

  3. [算法] O(n^2)排序算法的效率比较

    选择.插入排序 main.cpp 1 #include <iostream> 3 #include "SortTestHelper.h" 4 5 using names ...

  4. Spark SQL 之 RDD、DataFrame 和 Dataset 如何选择

    引言 Apache Spark 2.2 以及以上版本提供的三种 API - RDD.DataFrame 和 Dataset,它们都可以实现很多相同的数据处理,它们之间的性能差异如何,在什么情况下该选用 ...

  5. 10.20 host:域名查询工具

    host命令 是用于查询DNS的工具,它可以将指定主机名称转换为IP地址. host命令的参数选项及说明 -a 显示详细的DNS信息-t 指定查询的域名信息类型,可以是"A".&q ...

  6. Centos 7常见问题——SMBus Host Controller not enabled!

    在使用虚拟机Centos7操作系统偶尔会遇到,重启开机过程中出现如下图情况,无法正常开机 出现这种情况的可能原因就是你在虚拟机中添加了网卡或硬盘,还有给内存添加了容量之类就会导致开机有这种报错 解决方 ...

  7. unity用json和服务器数据交互

    第一种类型:服务器json数据是个对象 /// <summary> /// 获取用户信息初始化信息 /// </summary> void InitUserMessage() ...

  8. 论鸿蒙OS在某些人眼中的样子

    对于鸿蒙OS,博客园有一篇文章<为鸿蒙OS说两句公道话(我对鸿蒙OS的一些看法)>.有兴趣的可以看看. 在这篇文章中,个人觉得最精彩的不是文章本身,而是评论内容. 下面我挑一些出来,和大家 ...

  9. [leetcode] 72. 编辑距离(二维动态规划)

    72. 编辑距离 再次验证leetcode的评判机有问题啊!同样的代码,第一次提交超时,第二次提交就通过了! 此题用动态规划解决. 这题一开始还真难到我了,琢磨半天没有思路.于是乎去了网上喵了下题解看 ...

  10. Nginx 配置实例-配置虚拟主机

    Nginx 配置实例-配置虚拟主机 配置基于域名的虚拟主机 1. 配置域名为 aaa.domain.com 的虚拟主机 1.1 nginx 中虚拟主机的配置 1.2 相关目录及文件的创建 1.3 验证 ...