- 面向对象
- 主要特征
- a.封装
- b. 继承
- c.多态
- 重载
- 覆写
- 对象间作用
- Object类常用方法
- 访问控制修饰符
- 类的组合
封装也称为信息隐藏,是利用抽象数据类型将数据和基于数据的操作封装在一起,使其构成一个不可分割的独立实体,数据被保护在抽象数据类型的内部,尽可能地隐藏内部的细节,只保留一些对外接口使之与外部发生联系。系统的其它部分只有通过包裹在数据外面的被授权的操作来与这个抽象数据类型交流与交互。也就是说,用户无需知道对象内部方法的实现细节,但可以根据对象提供的外部接口(对象名和参数)访问该对象。
特点:
数据和基于数据的操作方法构成一个统一体。类的操作方法实现细节被隐藏起来,只是通过操作接口名称进行调试,操作内部的变动不会影响接口的使用。高内聚,松耦合
实现:
- 设置访问权限
- 创建 get/set 方法
- 在 get/set 方法中加入属性控制语句
- 创建类的实例、调用构造函数
用途:
b. 继承用户无需知道对象内部的细节,但可以通过对象对外提供的接口来访问该对象,有利于安全操作。
通过extends关键字来实现,使两个类发生继承关系
继承只有单继承(与C++不同)
is-a 关系
用途:
c.多态这是进行复用的重要手段,并为引用带来了新的特点。
重载一个程序中同名但不同方法共存,提供两种机制——重载(overloading) 与 覆写(overriding)
- 方法间名字相同,参数列表不同(包括参数顺序、个数、类型等)
- 必须是同一个类内
- 方法功能和目的相同,但具体细节有所不同
class StuManage {
public int getScore(){
return 3;
}
public int getScore(int i){
return i;
}
// 注释内的都不属于重载
public int getScore(Integer i){
return i;
}
//可变参数,i实质上是数组int[]
public int getScore(int ... i){
return 3;
}
}
覆写
- 子类对父类的同名方法(方法名称相同,参数相同,返回类型相同)重新进行定义,即在子类中定义与父类中已定义的同名而内容不同的方法。
- 子类继承父类之后,当子类有不同于父类的业务需求时,子类可以使用方法覆盖
覆写条件:
- 覆写之后的方法和之前的方法具有相同的返回值类型,相同的方法名,相同的参数列表,(同名方法不一定就是覆写,可能是重载),严格一致
- 覆写子类的访问修饰符权限应等于或大于父类,不能变小
- 覆写子类的返回类型能够向上转型成为父类的返回类型
- 覆写方法的异常要能向上转型为父类的异常
- 覆写只能针对非静态、非final、非构造方法
用途:
满足多样的子类需求,具有可推广性
class Parent {
Number getScore(int a) {
return new Integer(7);
}
}
class Son extends Parent {
@Override //所有的覆写方法需注明
Number getScore(int b){
return new Integer(8);
}
}
public class RunSon{
public static void main(String args[]){
Son s = new Son();
System.out.println(s.getScore());
}
}
对象间作用
作用方式:
对象之间可以通过组合,继承以及一个对象直接在其内部创建另一个对象。
作用条件:
Object类常用方法两个对象彼此之间要是可见的。
Object类是所有类的共同祖先,即使定义类时没有写extents Object。
在Object当中定义了许多方法,这些方法都可以被所有子类所继承。
| 方法名 | 说明 |
|---|---|
| Class getClass() | 获得当前对象的类对象 |
| String toString() | 得到代表这个对象的字符串 |
| Object clone() | 将当前对象克隆,默认是浅拷贝 |
| void finalize() | 对象被释放时使用,已弃用 |
| int hashCode() | 得到代表对象的一个整数,这个整数在应用程序运行时保持不变 |
| Boolen equals(Object obj) | 判断两个引用是否指向同一对象,其参数不能为普通数据类型 |
| void notify() | 用于线程同步中唤醒等待的线程 |
| void wait() | 应用于线程同步中的线程等待 |
| 类属性成员与方法修饰符类前修饰符 | public | 默认 |
|---|---|---|
| public | A | B |
| protected | B(对象引用)/B+C(类定义) | B |
| 默认 | B | B |
| private | D | D |
访问权限首先取决于类前的修饰符,在类能被访问的前提下,再看类属性/方法前的修饰符。(根据上面的表格和图)
以下是对于部分访问权限的一些代码测试:(结果在代码注释中)
1:
// 在resource 包中设计 FightPlane 类
package com.resource;
public class FightPlane {
protected String name;
protected int missileNum;
public void fire(){
if(missileNum > 0){
System.out.println("now fire a missile!");
missileNum -= 1;
}else{
System.out.println("No missile left!");
}
}
}
// 在run包中设计RunPlane类,且继承FightPlane类
package com.run;
import com.resource.*;
public class RunPlane extends FightPlane {
private void init(){
name = "wppf";
missileNum = 6; // 可以访问另一个包中protected属性
}
public static void main (String[] args){
RunPlane fp = new RunPlane();
fp.init();
fp.fire();
}
}
2:
// 在resource 包中设计 FightPlane 类
package com.resource;
class FightPlane { // 缺省,设置为包访问权限
protected String name;
protected int missileNum;
public void fire(){
if(missileNum > 0){
System.out.println("now fire a missile!");
missileNum -= 1;
}else{
System.out.println("No missile left!");
}
}
}
// 在run包中设计RunPlane类,且继承FightPlane类
package com.run;
import com.resource.*;
public class RunPlane extends FightPlane {
private void init(){
name = "wppf";
missileNum = 6; // 可以访问另一个包中protected属性
}
public static void main (String[] args){
RunPlane fp = new RunPlane();
fp.init();
fp.fire();
}
}
// 报错:java: com.resource.FightPlane在com.resource中不是公共的; 无法从外部程序包中对其进行访问
3:
class FightPlane {
private String name;
protected int missileNum;
public void fire(){
if(missileNum > 0){
System.out.println("now fire a missile!");
missileNum -= 1;
}else{
System.out.println("No missile left!");
}
}
}
public class RunPlane extends FightPlane {
private void init(){
name = "wppf"; // 报错:java: name 在 com.run.FightPlane 中是 private 访问控制
missileNum = 6;
}
public static void main (String[] args){
RunPlane fp = new RunPlane();
fp.init();
fp.fire();
}
}
类的组合
在一个类里面使用已经定义好的类对象的引用,并通过发消息的形式调用该对象的属性和方法
has-a,包含关系,有别于继承关系
作用:
- 不破坏封装,类与类之间相互独立,使用其他类的方法使功能更强大
- 使对象间耦合性较为松散
class FighterPlane{
String name;
int missileNum;
public FighterPlane(String _name,int _missileNum){
name = _name;
missileNum = _missileNum;
}
public void fire(){
if (missileNum>0){
System.out.println("now fire a missile !");
missileNum -= 1;
}
else{
System.out.println("No missile left !");
}
}
}
class A{
FighterPlane fp;
public A(FighterPlane fpp){
this.fp = fpp; //A对象中拥有了FighterPlane对象的引用
}
public void invoke(){
//A中对象发送消息给FighterPlane的对象
System.out.println(fp.name);
}
}
public class RunPlane{
public static void main(String[] args)
{
FighterPlane ftp = new FighterPlane("su35",10);
//产生A对象,并将ftp对象引用作为参数传入
A a = new A(ftp);
//发送消息,产生调用关系
a.invoke();
}
}
注:试验代码参考自教材



