面向对象

时间:2019-03-15
本文章向大家介绍面向对象,主要包括面向对象使用实例、应用技巧、基本知识点总结和需要注意事项,具有一定的参考价值,需要的朋友可以参考一下。

面向对象

面向对象(指挥者)概述

  • Java语言是一种面向对象的程序设计语言,这里的对象泛指现实中一切事物,每种事物都具备自己的属性(成员变量)和行为(成员方法)。

  • 面向对象思想就是在计算机程序设计过程中,参照现实中事物,将事物的属性特征、行为特征抽象出来,描述成计算机事件的设计思想。

  • 它区别于面向过程思想,强调的是通过调用对象的行为来实现功能,而不是自己一步一步的去操作实现。

面向对象语言的三大基本特征

封装、继承和多态。

类与对象

是一组相关属性和行为的集合。可以看成是一类事物的模板。
描述一类事物:
属性:就是该事物的状态信息;
行为:就是该事物能够做什么。

对象

是一类事物的具体体现。对象是类的一个实例,必然具备该类事物的属性和行为。

类和对象的关系

类是对一类事物的描述,是抽象的。
对象是一类事物的实例,是具体的。
类是对象的模板,对象是类的实体。

类的定义格式

public class ClassName{
    //成员变量
    //成员方法
}

定义类:就是定义类的成员,包括成员变量和成员方法。
成员变量:和以前定义变量几乎是一样的。只不过位置发生了改变。在类中,方法外。
成员方法:和以前定义方法几乎是一样的。只不过把static去掉。

对象的使用格式

创建对象:

类名 对象名 = new 类名();

使用对象访问类中的成员:

对象名.成员变量; 
对象名.成员方法();

成员变量的默认值

成员变量和局部变量的区别

对象作为参数

当一个对象作为参数,传递到方法中时,实际上传递的是对象的地址值

对象作为返回值

public static Phone getPhone() {
        Phone one = new Phone();
        one.brand = "苹果";
        one.price = 8388.0;
        one.color = "玫瑰金";
        return one;         //地址值
    }

当使用一个对象类型作为方法的返回值时,返回值就是地址值

封装

封装性在Java当中的体现:

  1. 方法就是一种封装
  2. 关键字private也是一种封装

封装就是将一些细节信息隐藏起来,对于外界不可见。

封装原则

将属性隐藏起来,若需要访问某个属性,提供公共方法对其访问。

封装步骤

  1. 使用 private 关键字来修饰成员变量。
  2. 对需要访问的成员变量,提供对应的一对 getXxx 方法 、 setXxx 方法

举例

问题描述:定义Person的年龄时,无法阻止不合理的数值被设置进来
解决方案:用private关键字将需要保护的成员变量进行修饰。

一旦使用了private进行修饰,那么本类当中仍然可以随意访问。
但是!超出了本类范围之外就不能再直接访问了。

间接访问private成员变量,就是定义一对儿Getter/Setter方法

必须叫setXxx或者是getXxx命名规则。
对于Getter来说,不能有参数,返回值类型和成员变量对应;
对于Setter来说,不能有返回值,参数类型和成员变量对应。

右键Generatealt + insert(fn+Enter)可以自动生成

public void setAge(int num){
    if( num < 100 && num >= 0)
      { age = num;} 
    else 
      { System.out.println("数据不合理");}
}

public int getAge(){
    return age;
}

注意:布尔类型的Getter不是用getXxx(),而是isXxx();Setter不变

This

当方法的局部变量和类的成员变量重名的时候,根据“就近原则”,优先使用局部变量。
如果需要访问本类当中的成员变量,需要使用格式:

this.成员变量名

“通过谁调用的方法,谁就是this。” this -- 地址

​ Person Person.name

构造方法

public 构造方法名(参数列表){
     // 方法体
}

构造方法是专门用来创建对象的方法,用new创建对象,其实是调用构造方法。

  • 构造方法的写法上,方法名与它所在的类名相同。

  • 它没有返回值,所以不需要返回值类型,甚至不需要void

  • 构造方法不能return一个具体的返回值

  • 如果没有没有编写任何构造方法,那么编译器会默认赠送一个构造方法,没有参数,方法体什么也不做。

  • 一旦编写了至少一个构造方法,那编译器不再赠送

  • 构造方法可重载(名称相同,参数列表不同)

构造方法和成员方法的区别

标准代码——JavaBean

一个标准的类通常要拥有下面四个组成部分:

  1. 所有的成员变量都要使用private关键字修饰
  2. 为每一个成员变量编写一对儿Getter/Setter方法
  3. 编写一个无参数的构造方法
  4. 编写一个全参数的构造方法

这样标准的类也叫做Java Bean

打印想要格式的数组

import java.util.Arrays;
System.out.println(Arrays.toString(arr));

ctrl + 点toString可以看系统里这个方法是怎么写的

导包

指出需要使用的类,在什么位置

import 包名称.类名称;

对于和当前类属于同一个包的情况,可以忽略导包语句不写。

如果调用不同包的成员变量

在那个包的成员变量前 + public
比如:

public String name

继承 extends

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

在继承的关系中,“子类就是一个父类”。也就是说,子类可以被当做父类看待。
例如父类是员工,子类是讲师,那么“讲师就是一个员工”。关系:is-a。

定义父类的格式:(一个普通的类定义)

public class 父类名称 {
    // ...
}

定义子类的格式:

public class 子类名称 extends 父类名称 {
    // ...
}

成员变量重名

子父类中出现了同名的成员变量时,在子类中需要访问父类中非私有成员变量时,需要使用 super 关键字,修饰父类成员变量,类似于之前学过的 this 。

使用格式:

super.父类成员变量名

通常编码时,我们遵循封装的原则,使用private修饰成员变量,那么如何访问父类的私有成员变量呢?对!可以在父类中提供公共的getXxx方法和setXxx方法。

注意事项:
无论是成员方法还是成员变量,如果没有都是向上找父类,绝对不会向下找子类的。

在父子类的继承关系当中,如果成员变量重名,则创建子类对象时,访问子类成员变量有两种方式:

直接通过子类对象访问成员变量:
等号左边是谁,就优先用谁,没有则向上找。
间接通过成员方法访问成员变量:
该方法属于谁,就优先用谁,没有则向上找。

成员方法重名——重写(Override)

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

重写(Override):方法的名称一样,参数列表【也一样】。覆盖、覆写。
重载(Overload):方法的名称一样,参数列表【不一样】。

特点:创建的是子类对象,则优先子类方法。如果没有都是向上找父类,绝对不会向下找子类的。

应用:子类可以根据需要,定义特定于自己的行为。既沿袭父类的功能名称,又根据子类的需要重新实现父类方法,从而进行扩展增强。
super.父类成员方法,表示调用父类的成员方法。

注意:

  1. 子类方法覆盖父类方法,必须要保证子类权限大于等于父类权限。
  2. 子类方法覆盖父类方法,返回值类型、函数名和参数列表都要一模一样。

方法重写的注意事项

  1. 必须保证父子类之间方法的名称相同,参数列表也相同。
    @Override:写在方法前面,用来检测是不是有效的正确覆盖重写。
    这个注解就算不写,只要满足要求,也是正确的方法覆盖重写。

  2. 子类方法的返回值必须【小于等于】父类方法的返回值范围。 ???
    小扩展提示:java.lang.Object类是所有类的公共最高父类(祖宗类),java.lang.String就是Object的子类。

  3. 子类方法的权限必须【大于等于】父类方法的权限修饰符。
    小扩展提示:public > protected > (default) > private
    备注:(default)不是关键字default,而是什么都不写,留空。

大部分情况下,方法重写 重写的方法 修饰符、返回值类型都是一样的

设计原则

对于意见投入使用的类,尽量不要进行修改。
推荐定义一个新的类,来重复利用其中的共用功能,并且添加新功能。

父子类构造方法的访问特点

  1. 子类构造方法当中有一个默认隐含的“super()”调用,所以一定是先调用的父类构造,后执行的子类构造。父类空间优先于子类对象产生
  2. 子类构造可以通过super关键字来调用父类重载构造。
  3. super的父类构造调用,必须是子类构造方法的第一个语句。不能一个子类构造调用多次super构造。

总结:

​ 子类必须调用父类构造方法,不写则赠送super();写了则用写的指定的super调用,super只能有一个,还必须是第一个。

super 和 this

  • super :代表父类的存储空间标识(可以理解为父亲的引用)。

  • this :代表当前对象的引用(谁调用就代表谁)。

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

1、访问成员
this.成员变量   ‐‐ 本类的
super.成员变量   ‐‐ 父类的
this.成员方法名()  ‐‐ 本类的
super.成员方法名() ‐‐ 父类的

2、访问构造方法
this(...)     ‐‐ 本类的构造方法
如:本类的无参构造,调用本类的有参构造
super(...)    ‐‐ 父类的构造方法
例:super(20); // 在调用父类重载的构造方法

继承的特点

  • Java只支持单继承,不支持多继承

  • Java支持多层继承(继承体系)。

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

  • 子类和父类是一种相对的概念。

抽象类

抽象类:抽象方法所在的类,必须是抽象类才行。在class之前写上abstract即可。

定义格式:

abstract class 类名字{

}

代码举例:

public abstract class Animal {
    public abstract void run(); 
}

抽象方法

抽象方法:在不确定对象的前提下,要求确定行为。就是加上abstract关键字,然后去掉大括号,直接分号结束。

定义格式:

修饰符 abstract 返回值类型 方法名 (参数列表);

代码举例:

public abstract void run();

如何使用抽象类和抽象方法

  1. 不能直接创建new抽象类对象。
  2. 必须用一个子类来继承抽象父类。
    否则,该子类也必须声明为抽象类。最终,必须有子类实现该父类的抽象方法
  3. 子类必须覆盖重写抽象父类当中所有的抽象方法。
    覆盖重写(实现):子类去掉抽象方法的abstract关键字,然后补上方法体大括号。
  4. 创建子类对象进行使用。

一个抽象类不一定含有抽象方法,只要保证抽象方法所在的类是抽象类即可。

这样没有抽象方法的抽象类,也不能直接创建对象,在一些特殊场景下有用途。

注意事项

  1. 抽象类不能创建对象,如果创建,编译无法通过而报错。只能创建其非抽象子类的对象。
  2. 抽象类中,可以有构造方法,是供子类创建对象时,初始化父类成员使用的。
  3. 抽象类中,不一定包含抽象方法,但是有抽象方法的类必定是抽象类。
  4. 抽象类的子类,必须重写抽象父类中所有的抽象方法,否则,编译无法通过而报错。除非该子类也是抽象类。

接口

一种引用类型,方法的集合,接口的内部主要就是封装了方法,包含:

  • 抽象方法(JDK7及以前)

  • 默认方法和静态方法(JDK8)

  • 私有方法(JDK9)

接口的定义

与定义类相似,但是使用interface关键字。它也会被编译成.class,但它不是类。

定义格式(接口名称大驼峰)

public interface 接口名称 {
    //抽象方法
    //默认方法
    //静态方法
    //私有方法
}

含有抽象方法

抽象方法:

  1. 使用abstract关键字修饰,可以省略。没有方法体。该方法供子类实现使用。
  2. 接口中,有多个抽象方法时,实现类必须重写所有抽象方法。如果抽象方法有重名的,只需要重写一次。
public interface InterFaceName{
    public abstract void method();
}

含有默认方法和静态方法

默认方法

使用default修饰,不可省略。

  1. 接口的默认方法,可以通过接口实现类对象,直接调用。
  2. 接口的默认方法,也可以被接口实现类进行覆盖重写。
  3. 接口中,有多个默认方法时,实现类都可以继承使用。如果默认方法有重名的,必须重写一次。

静态方法

使用static修饰,供接口直接调用。
注意事项:不能通过接口实现类的对象来调用接口当中的静态方法。
正确用法:通过接口名称,直接调用其中的静态方法。
调用格式:

接口名称.静态方法名(参数);
public interface InterFaceName{
    public default void method(){
        //执行语句
    }
    public static void method2(){
        //执行语句
    }
}

接口中,存在同名的静态方法并不会冲突,原因是只能通过各自接口名访问静态方法。

含有私有方法和私有静态方法

私有方法:使用private修饰,供接口中的默认方法调用。
私有静态方法:默认方法和静态方法可以调用。

public interface InterFaceName{
    private void method(){
        //执行语句
    }
    private static method(){
        //执行语句
    }
}

接口的使用

​ 接口不能创建对象,但是可以被实现(implements,像继承)。一个实现接口的类(可以看作是接口的子类),需要实现接口中所有的抽象方法(alt+enter),创建该类对象,就可以调用方法了,否则它必须是一个抽象类。

class 类名 implements 接口名{
    //重写接口中抽象方法【必须】 alt+enter
    //重写接口中默认方法【可选】
}

接口的多实现

一个类可以实现多个接口,这叫做接口的多实现。一个类的直接父类是唯一的,但是一个类可以同时实现多个接口。

public class MyInterfaceImpl implements MyInterfaceA, MyInterfaceB {
    // 覆盖重写所有抽象方法
}

优先级的问题。父类是亲爸爸,接口是干爸爸。

一个类如果直接父类当中的方法,和接口当中的默认方法产生了冲突,优先用父类当中的方法。

接口继承

​ 一个接口能继承另一个或者多个接口。接口的继承使用extends关键字。如果父接口中的默认方法有重名的,那么子接口需要重写一次。

  • 子接口重写默认方法时,default关键字可以保留。
  • 子类重写默认方法时,default关键字不可以保留。

    ​接口当中也可以定义“成员变量”,但是必须使用public static final三个关键字进行修饰。
    ​从效果上看,这其实就是接口的【常量】。

public static final 数据类型 常量名称 = 数据值;

备注:
一旦使用final关键字进行修饰,不可改变,必须赋值。

注意事项:

  1. 接口当中的常量,可以省略public static final,注意:不写也照样是这样。
  2. 接口当中的常量,必须进行赋值;不能不赋值。
  3. 接口中常量的名称,使用完全大写的字母,用下划线进行分隔,如NUM_OF_MY_CLASS。(推荐命名规则)

ctrl+shift+U :大小写替换

调用:

接口名称.常量名称

其他特点

接口是没有静态代码块或者构造方法的。

多态

多态是指同一行为,具有多个不同表现形式。

前提【重点】

1、继承或者实现【2选1】
2、方法的重写【不重写,无意义】
3、父类引用指向子类对象【格式体现】
格式:

父类名称 对象名 = new 子类名称();

或者:

接口名称 对象名 = new 实现类名称();
变量名.方法名();

访问成员变量的两种方式

  1. 直接通过对象名称访问成员变量:看等号左边是谁,优先用谁,没有则向上找。
  2. 间接通过成员方法访问成员变量:看该方法属于谁,优先用谁,没有则向上找。

编译看左边,运行看右边

当使用多态方式调用方法时,首先检查父类中是否有该方法,如果没有,则编译错误;如果有,执行的是子类重写后的方法。

在多态的代码当中,成员方法的访问规则是:
看new的是谁,就优先用谁,没有则向上找。

口诀:编译看左边,运行看右边。

对比一下:

  • 成员变量:编译看左边,运行还看左边。
  • 成员方法:编译看左边,运行看右边。

引用类型转换

向上转型【多态写法】

多态本身就是子类类型向父类类型向上转换的过程,这个过程是默认的。
当父类引用指向一个子类对象时,便是向上转型。
使用格式:

父类类型 变量名 = new 子类类型();

向上转型一定是安全的,没有问题的,正确的。但是也有一个弊端:
对象一旦向上转型为父类,那么就无法调用子类原本特有的内容。

解决方案:用对象的向下转型【还原】。

向下转型

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

子类类型 变量名 = (子类类型)父类变量名

instanceof关键字

为避免ClassCastException的发生,Java提供了instanceof关键字,给引用变量做类型的校验。
格式:

变量名 instanceof 数据类型

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

上一页 下一页

原文地址:http://www.manongjc.com/article/73133.html