封装

封装可以认为是一个保护屏障,防止该类中的某些属性或者是方法被暴露出去,也就是不允许外部类随意访问,如果想要访问该类中的数据,必须使用指定的方式;适当的封装可以让代码更容易理解与维护,也加强了代码的安全性。其原则就是将属性隐藏起来,若需要访问某个属性,提供公共方法对其访问。

封装的实现

  • 步骤一:使用private关键字修饰所要封装的数据
  • 步骤二:对于需要访问的数据,分别提供set和get方法

private讲解

  • 含义:private是一个权限修饰符,只有本类中的方法可以调用
  • 格式:private 数据类型 变量名;
  • 代码:
public class Car {
	private String name;
	/**
	 * @return the name
	 */
	public String getName() {
		return name;
	}
	/**
	 * @param name the name to set
	 */
	public void setName(String name) {
		this.name = name;
	}
}

封装中的构造方法

当一个对象被创建时候,构造方法用来初始化该对象,给对象的成员变量赋初始值。

小贴士:无论你与否自定义构造方法,所有的类都有构造方法,因为Java自动提供了一个无参数构造方法,一旦自己定义了构造方法,Java自动提供的默认无参数构造方法就会失效。

  • 构造方法的格式
修饰符 构造方法名(参数列表){  
	// 方法体 
}

构造方法的写法上,方法名与它所在的类名相同。它没有返回值,所以不需要返回值类型,甚至不需要void。使用构造方法后,代码如下:

public class Car {
	private String name;
	public Car(String name) {
		this.name = name;
	}
	/**
	 * @return the name
	 */
	public String getName() {
		return name;
	}
	/**
	 * @param name the name to set
	 */
	public void setName(String name) {
		this.name = name;
	}
}

  • 注意
  1. 如果你不提供构造方法,系统会给出无参数构造方法。
  2. 如果你提供了构造方法,系统将不再提供无参数构造方法。
  3. 构造方法是可以重载的,既可以定义参数,也可以不定义参数。

封装的好处

  • 封装提高了数据的安全性
  • 操作简单
  • 隐藏了实现

继承

现实生活中的继承,孩子继承父辈的财产,孩子可以直接拿父辈的财产来使用,Java中的继承是指在现有类的基础上定义一个新的类,现有类称为父类,新的类称为子类,子类会自动拥有父类的可继承的内容多个类中存在相同属性和行为时,将这些内容抽取到单独一个类中,那么多个类无需再定义这些属性和行为,只要继承那一个类即可。
20181026222307315.png
其中,多个类可以称为子类,单独那一个类称为父类、超类(superclass)或者基类。
继承描述的是事物之间的所属关系,这种关系是: is-a 的关系。例如,图中兔子属于食草动物,食草动物属于动物。可见,父类更通用,子类更具体。我们通过继承,可以使多种事物之间形成一种关系体系。

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

  • 继承优点

  1. 提高代码的复用性
  2. 类与类之间产生了关系,是多态的前提
  • 继承的格式
class 父类 {  ...  }  class 子类 extends 父类 {  ...  }
  • 不可继承的部分
  1. 被private修饰的
  2. 构造方法不能继承
  • 继承后的特点——成员变量
  1. 成员变量不重名:访问是没有影响
  2. 成员变量重名:访问是有影响
  • 继承后的特点——成员方法
  1. 成员方法不重名:没有任何影响
  2. 成员方法重名:对父类方法进行重写
  • super和this的含义
    super :代表父类的存储空间标识(可以理解为父亲的引用)。
    this :代表当前对象的引用(谁调用就代表谁)。
  1. super和this的用法
访问成员
this.成员变量 ‐‐ 本类的 
super.成员变量 ‐‐ 父类的 

this.成员方法名() ‐‐ 本类的 
super.成员方法名() ‐‐ 父类的

访问构造方法
this(…) ‐‐ 本类的构造方法  
super(…) ‐‐ 父类的构造方法
  • 继承的特点
  1. Java只支持单继承,不支持多继承
  2. 个类可以有多个子类
  3. Java支持多层继承(继承体系)
  4. 子类和父类是一种相对的概念

多态

  • 多态的定义
    多态: 是指同一行为,具有多个不同表现形式。

前提

  1. 继承或者实现【二选一】
  2. 方法的重写【意义体现:不重写,无意义】
  3. 父类引用指向子类对象【格式体现】
  • 多态的格式
父类类型 变量名 =  new 子类对象; 
变量名.方法名();
  • 多态的优点
    可以使程序编写的更简单,并有良好的扩展

  • 向上转型
    向上转型:多态本身是子类类型向父类类型向上转换的过程,这个过程是默认的。

当父类引用指向一个子类对象时,便是向上转型。

使用格式:

	父类类型  变量名 = new 子类类型();
	如:Animal a = new Cat();
  • 向下转型
    向下转型:父类类型向子类类型向下转换的过程,这个过程是强制的。

一个已经向上转型的子类对象,将父类引用转为子类引用,可以使用强制类型转换的格式,便是向下转型。

使用格式:

	子类类型 变量名 = (子类类型) 父类变量名;
	如:Cat c =(Cat) a; 
  • 为什么要转型
    当使用多态方式调用方法时,首先检查父类中是否有该方法,如果没有,则编译错误。也就是说,不能调用子类拥有,而父类没有的方法。编译都错误,更别说运行了。这也是多态给我们带来的一点"小麻烦"。所以,想要调用子类特有的方法,必须做向下转型。
    转型演示,代码如下:
定义类:
abstract class Animal { 
    abstract void eat(); 
} 
class Cat extends Animal { 
    public void eat() { 
        System.out.println("吃鱼"); 
    } 
    public void catchMouse() { 
        System.out.println("抓老鼠"); 
    } 
} 
class Dog extends Animal { 
    public void eat() { 
        System.out.println("吃骨头"); 
    } 
    public void watchHouse() { 
        System.out.println("看家"); 
    } 
}

			
定义测试类:
public class Test {
    public static void main(String[] args) {
        // 向上转型 
        Animal a = new Cat(); 
        a.eat();  // 调用的是 Cat 的 eat               
        // 向下转型 
        Cat c = (Cat)a;      
        c.catchMouse();  // 调用的是 Cat 的 catchMouse        
    } 
}
  • 转型的异常
    转型的过程中,一不小心就会遇到这样的问题,请看如下代码:
public class Test {
	public static void main(String[] args) {
		// 向上转型
		Animal a = new Cat();
		a.eat(); // 调用的是 Cat 的 eat
		// 向下转型
		Dog d = (Dog) a;
		d.watchHouse(); // 调用的是 Dog 的 watchHouse 【运行报错】
	}
}

这段代码可以通过编译,但是运行时,却报出了 ClassCastException ,类型转换异常!这是因为,明明创建了Cat类型对象,运行时,当然不能转换成Dog对象的。这两个类型并没有任何继承关系,不符合类型转换的定义。
为了避免ClassCastException的发生,Java提供了 instanceof关键字,给引用变量做类型的校验,格式如下:

变量名 instanceof 数据类型
如果变量属于该数据类型,返回true。
如果变量不属于该数据类型,返回false。

所以,转换前,我们最好先做一个判断,代码如下:

public class Test {
    public static void main(String[] args) {
        // 向上转型 
        Animal a = new Cat(); 
        a.eat();               // 调用的是 Cat 的 eat
        // 向下转型 
        if (a instanceof Cat){
            Cat c = (Cat)a;      
            c.catchMouse();        // 调用的是 Cat 的 catchMouse
        } else if (a instanceof Dog){
            Dog d = (Dog)a; 
            d.watchHouse();       // 调用的是 Dog 的 watchHouse
        }
    } 
}


标题:Java中的封装继承多态
作者:XxwGit
地址:http://xxwgit.cn/solo/articles/2020/01/14/1578971986559.html