Java基础(7):面向对象三大特性—封装、继承和多态的详解

一、封装(encapsulation)

从表面意思来看就是封闭的包装。而Java中,一个类有属性和方法,但是不可能想修改就修改,毫无安全性可言,而且有的类只适用于某一场景,其内部的方法和属性不对外开放。这就是封装的作用,用来设置访问权限。

下图为Java的访问权限符和其作用域

访问范围从大到小:public --> proetected --> default --> private

public:修饰之后,能被所有类访问,访问权限最宽松。

protected: 作用域只在同类、同包和子类中,protected使用最多场景就是父类方法给子类重写。

default: 作用域只在同类和同包中。未使用权限修饰符,默认采用。

private: 作用域只在同一个类中。常用的就是成员变量私有化,只有同一个类中才能访问。即暴露出来的setter 和 getter方法来访问,保证了安全性。还有对构造器私有化。工厂模式或者单例模式中有用到。注意,默认构造器私有时,其子类的构造器无法使用,这涉及到子类初始化时会对父类初始化。


import 与 package 关键字的区别:

package 表示当前类属于那个包中。从作用域来看,包也是一种权限,不同包的类是无法相互访问的,包的作用域和default差不多。

import是用来导入别的包。比如要使用Math类,但Math类不属于同一个包中,那相当于不存在,所以无法使用。这就需要import 来导入一个Math类所在的包,这样才可以使用该包中的类。

在Java中,java.lang包是默认导入的,里面都是java的核心类,如String 类等。

二、继承(extend)

使用继承,子类可以得到父类所有字段和方法,除了private所修饰的。继承增加了代码的复用。而且继承是多态实现的基础。
多说一下,继承只能单继承,但是接口却可以实现多个,接口相当于是多继承。但是接口是一个特别抽象类,只提供规范,不提供具体实现。而且接口中只能定义常量。
下面代码可以看出继承和包权限的作用:
package com.test1; //使用com.test1 包
//A类作为父类
public class A {
	private int a; //私有化
	protected int b; //子类能访问
	public int c;//访问权限最高
	public static int d = 10086; //A的静态变量
	
	public static void infoPub() {System.out.println("A类的public方法 :" + new A().a);} //a是私有的,在同类中可以访问
	protected static void infoPro() {System.out.println("A类的protected方法");}
	private static void infoPri() {System.out.println("A类的private方法");}
}
package com.test2;//使用com.test2 包
import com.test1.A; //A类不在同包中,所以要导入。

//继承A类
public class B extends A {
	
	//调用继承A类的方法
	public void testB() {
		infoPro(); //A类的protected修饰的方法
		infoPub(); //A类的public修饰的方法
		System.out.println(d);//子类也能获得父类的类变量
	}
	//在B中类中启动主方法来测试
	public static void main(String[] args) {
		B b = new B();
		//B类中只能得到A类的 b变量和c变量 
		//b 是 protected修饰的,子类中能访问
		//c 是public修饰的,哪里都能访问
		System.out.println(b.b);
		System.out.println(b.c);
		b.testB();
	}
}
使用另一个非子类来测试,可以看到只有c变量能被访问到,而b变量已经无法访问了,因为b变量是protected修饰。
下图会看到有equals() 、getClass()、hasCode()等方法 。这是因为在Java中,有一个基类,那就是Object类,他是所有类的父类,只要创建一个类就默认继承了Object类,所以会得到Object类的方法。在类型转换中,所有类都可以转换成Object类。





三、多态(Ploymorphism)

多态的定义:指允许不同类的对象对同一消息做出响应。即同一消息可以根据发送对象的不同而采用多种不同的行为方式。

按个人理解,就是做同样的事情,呈现不同的结果。而且多态提高了代码的通用性和灵活性,在面向对象中,多态是重点。

要实现多态的前提:
一、要有继承关系;
二、子类对父类进行重写;
三、父类引用指向子类对象
下面给上一个简单的多态实现代码:
package com.test.polymorphsim;
//父类
public class Father {
	public int a;
	protected Father() {System.out.println("Father类的默认构造器");}
	//看书
	protected void  readBook() {
		System.out.println("Father喜欢看科学书");
	}
	
	//玩游戏
	protected void playGame() {
		System.out.println("Father喜欢玩体育游戏");
	}
}

//大儿子类
class Son1 extends Father{
	public Son1() {System.out.println("Son1默认构造器");}
	//重写父类方法
	@Override
	protected void readBook() {
		System.out.println("大儿子喜欢看游戏书");
	}
	//如果Son1类不重写父类的playGame(),多态时调用就会调用父类的该方法
	@Override
	protected void playGame() {
		// TODO Auto-generated method stub
		super.playGame();
	}
}

//二儿子类
class Son2 extends Father{
	public Son2() {System.out.println("Son2默认构造器");}
	@Override
	public void readBook() {
		System.out.println("二儿子看编程书");
	}
	@Override
	public void playGame() {
		System.out.println("二儿子喜欢玩单机游戏");
	}
	
}

//三儿子类
class Son3 extends Father{
	public Son3() {System.out.println("Son3默认构造器");}
	@Override
	protected void readBook() {
		System.out.println("三儿子看数学书");
	}
	@Override
	protected void playGame() {
		System.out.println("三儿子玩数字游戏");
	}
}
package com.test.polymorphsim;

public class Test {
	public static void main(String[] args) {
		//父类引用指向子类对象
		Father son1 = new Son1();
		Father son2 = new Son2();
		Father son3 = new Son3();
		
		//传入上面参数
		show(son1);
		show(son2);
		show(son3);
	}
	
	//根据传入的Father对象,呈现不同结果
	//传入一个Father类型参数,调用Father类中的方法。
	public static void show(Father fa) {
		fa.readBook();
		fa.playGame();
	}
}
//输出结果
Father类的默认构造器
Son1默认构造器
Father类的默认构造器
Son2默认构造器
Father类的默认构造器
Son3默认构造器
大儿子喜欢看游戏书
Father喜欢玩体育游戏
二儿子看编程书
二儿子喜欢玩单机游戏
三儿子看数学书
三儿子玩数字游戏
在show()方法中,只要传入一个Father参数,就可以调用其中的readBook() 和 playGame() 方法。也就是方法是固定的,但是根据我们传入的参数,会出现不同的结果。这就是多态的灵活性和通用性。

在输出结果中会看到出现三次Father类的默认构造器。这是因为在Java中,只要创建一个类的对象,就意味着该类会被初始化。
这要提到Java的类加载机制,步骤简要分为三步,加载--连接--初始化,一般情况都是直接完成三步。在初始化一个类时,会先初始化该类的父类,保证一整个继承体系都初始化完成,才能开始使用该类。
在上面代码中创建了三个子类对象,所以父类的无参构造器会被调用三次。






  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值