Java的三大特性(封装,继承,多态)

封装

封装指的是属性私有化,根据需要提供setter和getter方法来访问属性。即隐藏具体属性和实现细节,仅对外开放接口,控制程序中属性的访问级别。

封装目的:增强安全性和简化编程,使用者不必在意具体实现细节,而只是通过外部接口即可访问类的成员。


继承

继承时子类继承父类的特征和行为,使得子类对象(实例)具有父类的属性,或子类从父类继承方法,使得子类具有与父类相同的行为。

  1. B类 继承 A类,则称 A类 为超类、父类、基类,B类则称为子类、派生类、扩展类。
  2. java 中的继承只支持单继承,不支持多继承,C++中支持多继承,这也是 java 体现简单性的一点,换句话说,java 中不允许这样写代码:class B extends A,C{ }。
  3. 虽然 java 中不支持多继承,但有的时候会产生间接继承的效果,例如:class C extends B,class B extends A,也就是说,C 直接继承 B,其实 C 还间接继承 A。
  4. java 中规定,子类继承父类,除构造方法和被 private 修饰的数据不能继承外,剩下都可以继承。
  5. java 中的类没有显示的继承任何类,则默认继承 Object 类,Object 类是 java 语言提供的根类,也就是说,一个对象与生俱来就有Object 类型中所有的特征。
  6. 继承也存在一些缺点,例如:CreditAccount 类继承 Account 类会导致它们之间的耦合度非常高,Account 类发生改变之后会马上影响CreditAccount 类。

继承目的:是为了代码的复用性

方法重载

在同一个类当中,如果功能相似,尽可能将方法名定义的相同,这样方便调用的同时代码也会美观。那么,代码满足什么条件的时候能够构成方法重载呢?只要在同一个类当中,方法名相同,参数列表不同(类型、个数、顺序),即构成方法重载。

方法覆盖

猫调用 speak()方法希望输出的结果是“喵!”,狗调用 speak()方法更希望输出的结果是“汪!”,可见 猫 和 狗 从父类中继承过来的 speak()方法已经不够子类使用了,此时就需要使用方法覆盖机制了。

方法覆盖的条件及注意事项(掌握)那么,当程序具备哪些条件的时候,就能构成方法覆盖呢?
① 方法覆盖发生在具有继承关系的父子类之间,这是首要条件;
② 覆盖之后的方法与原方法具有相同的返回值类型、相同的方法名、相同的形式参数列表;
另外,在使用方法覆盖的时候,需要有哪些注意事项呢?
① 由于覆盖之后的方法与原方法一模一样,建议在开发的时候采用复制粘贴的方式,不建议手写,因为手写的时候非常容易出错,比如在 Object 类当中有 toString()方法,该方法中的 S 是大写的,在手写的时候很容易写成小写 tostring(),这个时候你会认为toString()方法已经被覆盖了,但由于方法名不一致,导致最终没有覆盖,这样就尴尬了;
② 私有的方法不能被继承,所以不能被覆盖;
③ 构造方法不能被继承,所以也不能被覆盖;
④ 覆盖之后的方法不能比原方法拥有更低的访问权限,可以更高(学习了访问控制权限修饰符之后你就明白了);
⑤ 覆盖之后的方法不能比原方法抛出更多的异常,可以相同或更少(学习了异常之后就明白了);
⑥ 方法覆盖只是和方法有关,和属性无关;
⑦ 静态方法不存在覆盖(不是静态方法不能覆盖,是静态方法覆盖意义不大,学习了多态机制之后就明白了);


多态

多态就是“同一个行为”发生在“不同的对象上”会产生不同的效果。,比如叫,猫是喵喵,狗是汪汪。

多态的体现(转型一定要有继承关系)在 java 中允许这样的两种语法出现:一种是向上转型(Upcasting),一种是向下转型(Downcasting),向上转型是指子类型转换为父类型,又被称为自动类型转换,向下转型是指父类型转换为子类型,又被称为强制类型转换。

public class Animal {
	public void move(){
		System.out.println("Animal move!");
	}
}

public class Cat extends Animal{
	//方法覆盖
	public void move(){
		System.out.println("走猫步!");
	}
	//子类特有
	public void catchMouse(){
		System.out.println("抓老鼠!");
	}
}

public class Bird extends Animal{
	//方法覆盖
	public void move(){
		System.out.println("鸟儿在飞翔!");
	}
	//子类特有
	public void sing(){
 		System.out.println("鸟儿在歌唱!");
	}
}

public class Test {
	public static void main(String[] args) {
		Animal a1 = new Cat();
		a1.move();
		Animal a2 = new Bird();
		a2.move();
	}
}

运行结果:

走猫步
鸟儿在飞翔

java 中之所以有多态机制,是因为 java 允许一个父类型的引用指向一个子类型的对象。也就是说允许这种写法:Animal a2 = new Bird(),因为 Bird is a Animal 是能够说通的。其中 Animal a1 = new Cat()或者 Animal a2 = new Bird()都是父类型引用指向了子类型对象,都属于向上转型(Upcasting),或者叫做自动类型转换。

java 程序包括编译和运行两个阶段,分析 java 程序一定要先分析编译阶段,然后再分析运行阶段,在编译阶段编译器只知道 a1 变量的数据类型是 Animal,那么此时编译器会去 Animal.class字节码中查找 move()方法,发现 Animal.class 字节码中存在 move()方法,然后将该 move()方法绑定到 a1 引用上,编译通过了,这个过程我们可以理解为“静态绑定”阶段完成了。紧接着程序开始运行,进入运行阶段,在运行的时候实际上在堆内存中 new的对象是 Cat 类型,也就是说真正在 move 移动的时候,是 Cat 猫对象在移动,所以运行的时候就会自动执行 Cat 类当中的 move()方法,这个过程可以称为“动态绑定”。但无论是什么时候,必须先“静态绑定”成功之后才能进入“动态绑定”阶段。

public class Test {
	public static void main(String[] args) {
		Animal a = new Cat();
		a.catchMouse();
	}
}

“Animal a = new Cat();”在编译的时候,编译器只知道 a 变量的数据类型是 Animal,也就是说它只会去Animal.class 字节码中查找 catchMouse()方法,结果没找到,自然“静态绑定”就失败了,编译没有通过。就像以上描述的错误信息一样:在类型为 Animal 的变量 a 中找不到方法catchMouse()。

解决方法:

public class Test04 {
	public static void main(String[] args) {
		//向上转型
		Animal a = new Cat();
		//向下转型:为了调用子类对象特有的方法
		Cat c = (Cat)a;
		c.catchMouse();
	}
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值