什么是面向对象?来看集合篇,看完你就了解什么是面向对象

目录

  • 前言
  • 一、面向对象(基础篇)
    • 1. 面向对象基础
    • 1.1 面向对象思想
      • 1.1.1 概述
      • 1.1.2 三大思想
      • 1.1.3 三大特征
    • 1.2 类与对象
      • 1.2.1 两者的关系
      • 1.2.2 类的定义格式
      • 1.2.3 属性与方法
      • 1.2.4 对象的创建与使用
    • 1.3 构造方法
      • 1.3.1 概述
      • 1.3.2 构造方法的格式
      • 1.3.3 构造方法设计
    • 1.4 方法的重载
    • 1.5 构造方法的重载
    • 1.6 匿名对象
  • 二、面向对象(进阶篇)
    • 2 面向对象进阶
    • 2.1 封装 private
    • 2.2 this
    • 2.3 static
      • 2.3.1 概述
    • 2.4 代码块
      • 2.4.1 普通代码块
      • 2.4.2 构造代码块
      • 2.4.3 静态代码块
    • 2.5 包
      • 2.5.1 包介绍
      • 2.5.2 包的命名规则
      • 2.5.3 import 关键字
    • 2.6 权限修饰符
  • 三、面向对象(高级篇)
    • 3 面向对象高级
    • 3.1 继承
    • 3.2 super
    • 3.3 重写
    • 3.4 final
    • 3.5 抽象类
      • 3.5.1 概念
      • 3.5.2 抽象方法
      • 3.5.3 不能被实例化
      • 3.5.4 常见问题
      • 3.5.5 抽象类和普通类的区别
    • 3.6 接口
      • 3.6.1 概念
      • 3.6.2 面向接口编程思想
      • 3.6.3 全局常量和抽象方法的简写
      • 3.6.4 接口的实现
      • 3.6.5 接口的继承
      • 3.6.6 接口和抽象类的区别
    • 3.7 多态
      • 3.7.1 多态的体现
      • 3.7.2 多态的使用
      • 3.7.3 instanceof
    • 3.8 Object类
      • 3.8.1 概念
      • 3.8.2 Object的多态
      • 3.8.3 toString
      • 3.8.4 equals
    • 3.9 内部类
      • 3.9.1 概念
      • 3.9.2 成员内部类
      • 3.9.3 局部内部类
      • 3.9.4 匿名内部类
      • 3.9.5 静态内部类
    • 3.10 包装类
      • 3.10.1 概述
      • 3.10.2 装箱和拆箱操作
  • 总结

前言

学习了一周面向对象,一开始对于面向对象的概念我也觉得很抽象、很模糊,后来接触了一些项目后,才慢慢搞懂。下面是我整理出来关于面向对象的一些基础知识。

一、面向对象(基础篇)

1. 面向对象基础

Java是一种面向对象的编程语言。面向对象编程,英文是Object-Oriented Programming,简称OOP。

1.1 面向对象思想

1.1.1 概述

面向对象(Object Oriented)是相对面向过程(procedure Oriented)来说的,它们都是软件开发的一种方式。

面向对象的概念和应用已超越了程序设计和软件开发,是一种对现实世界理解和抽象的方法,是计算机编程技术发展到一定阶段后的产物。

那什么又是面向过程呢?

面向过程是关注流程的,每解决一个程序问题,都需要程序员逐步分析,然后再逐步实现。

举个例子:
小A饿了,需要吃饭。那么他就要自己去买菜、洗菜、淘米、煮饭、炒菜,最后吃饭,这是一个吃饭,解决饿的过程。在这个过程里呢,小A需要一步一步的去完成,最后才能吃到饭,解决饿的问题。这就是面向过程。

对于这种复杂的过程,面向对象就能更好的解决复杂问题。

面向对象是相对于面向过程来讲的,指的是把 相关的数据和方法组织为一个整体来看待,从更高的层次来进行系统建模,更贴近事物的自然运行模式。

举个例子:
小B饿了,需要吃饭。小B呢,不想自己做饭了,去饭店吃饭,解决饿的问题。小B不需要知道饭菜怎么做,只管好吃不好吃,能不能填饱肚子,这就是面向对象。

面向过程到面向对象思想层面的转变:

面向过程关注的是执行的过程,面向对象关注的是具备功能的对象。

面向过程到面向对象,是程序员思想上 从执行者到指挥者的转变。

1.1.2 三大思想

面向对象思想从概念上讲分为以下三种:OOA、OOD、OOP

  • OOA:面向对象分析(Object Oriented Analysis)

  • OOD:面向对象设计(Object Oriented Design)

  • OOP:面向对象程序(Object Oriented Programming)

1.1.3 三大特征

面向对象有三大特征:封装、继承、多态

  • 封装性:所有的内容对外部不可见

  • 继承性:将其他的功能继承下来继续发展

  • 多态性:方法的重载本身就是一个多态性的体现

1.2 类与对象

1.2.1 两者的关系

类表示一个共性的产物,是一个综合的特征;
而对象,是一个个性的产物,是一个个体的特征。
(相当于设计图纸与实物的概念)
比如说建一栋房子,你得先有设计图吧,有了设计图,工人才能根据设计的内容进行建造。那么设计图纸就相当于编程里的类,工人就相当于编程里的对象。

类必须通过对象才能使用,对象所有操作都在类中定义。
类由属性和方法组成:

  • 属性:就相当于人的一个个的特征(如:勤劳、懒惰、忠诚)

  • 方法:就相当于人的一个个的行为(如:吃饭、睡觉、学习)

1.2.2 类的定义格式

类定义写在“ .java ”文件中
类的定义格式:

class 类名称{
成员属性
成员方法
}

一个“ .java ”文件中,可以存在N个类,但是只能存在一个public修饰的类
代码示例:

class Person{//属性 - 特征String name;//定义了一个字符串属性为name的特征int age;//定义了一个整型属性为age的特征char sex;//定义了一个字符型属性为sex的特征
}

一个

1.2.3 属性与方法

属性定义格式:

数据类型 属性名;

属性定义并赋值的格式:

数据类型 属性名 = 初始化值;

代码示例:

int age = 18;

方法定义格式:

返回值类型 方法名称(形式参数列表){
//方法体 :方法被调用时执行的代码
return 返回值;

关于方法:

1)返回值:方法体内向方法体外返回的数据内容,通过return关键字完成。如果一个方法一旦执行了return语句,就立即结束。返回值类型为void时,不用写return语句。
2) 返回值类型:返回值的数据类型,必须在方法定义时提前声明,可以是基本数据类型,也可以是引用型数据类型。如果不需要返回值,可以写void
3) 方法名称:需要给不同的方法赋予不同的名称。
4)形式参数列表:定义方法时,可以声明方法执行时所需的外部参数。参数可以多个,看具体方法需要。一个方法在定义时,还未被调用,所以是形式上的参数列表。参数格式:数据类型 名称 。当有多个参数时,用逗号隔开。
5)方法体:是方法中包含的多条程序语句。可以使用成员变量。

代码示例:

//返回类型为整型int 方法名为 sum 形式参数为整型a和b
int sum(int a,int b) {  int c = a + b;//方法体 对a和b求和,然后赋值给creturn c;//返回值为整型int“ c ”}

1.2.4 对象的创建与使用

对象的创建格式如下:

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

对象创建完,就可以使用对象的属性和方法了,使用格式如下:

给类中属性赋值:对象名.成员变量名称 = 值;

访问类中的属性:对象名.成员变量名称
调用类中的方法:对象名.方法(实际参数列表)

下面编写一个拥有颜色(color)、品牌(brand)和价格(price)属性,并包含介绍方法(introduction)的汽车类(Car)。
首先是定义类

//汽车类(Car)
class Car{//属性String color;   //颜色String brand;   //品牌//介绍的方法void show(){System.out.println("汽车的品牌为:"+brand);System.out.println("汽车的颜色为:"+color);}
}

定义类后,编写一个入口程序来创建一个汽车(对象)

public class Object_01 {public static void main(String[] args) {Car car = new Car();    //创建一个汽车对象,对象名为carcar.color = "白色";      //给汽车car设置颜色color为"白色"car.brand = "宝马";      //给汽车car设置品牌brand为"宝马"//调用汽车car类show的方法car.show();}
}

程序运行结果:

1.3 构造方法

构造方法也叫构造器,顾名思义就是构造一个方法,用构造方法去构造对象,并给对象的属性进行赋值。

在下面代码右侧Person后面出现的小括号, 其实就是在调用构造方法 !

Person p = new Person();

1.3.1 概述

接下来说一下构造方法的作用、执行时机、特点等。
作用:用于对象初始化。
执行时机:在创建对象时,自动调用。
特点

  • 所有的java类中都会至少存在一个构造方法。

  • 如果一个类中没有明确的编写构造方法,则编译器会自动生成一个无参的构造方法,构造方法中没有任何的代码。

  • 如果自行编写了任意一个构造器,则编辑器不会再自动生成无参的构造方法。

1.3.2 构造方法的格式

构造方法的格式与普通方法基本相同,区别在于构造方法的方法名与类的名称完全相同,且构造方法无返回值类型的声明。格式如下:

修饰符 类名(参数列表){
//方法体
}

代码如下(示例):

public class Demo1 {public static void main(String[] args) {Person p = new Person();//打印一次Person p1 = new Person();//打印一次Person p2 = new Person();//打印一次}
}
//类名
class Person{//属性String name;int age;//无参数构造方法public Person(){System.out.println("创建对象时,就已经被调用了。");}//全属性有参数构造方法public Person(String name1, int age1) {name = name1;age = age1;}
}

1.3.3 构造方法设计

建议自定义无参构造方法,不要对编译器形成依赖,避免程序错误发生。

  • 当类中有非常量成员变量(属性)时,建议提供两个版本的构造方法,一个是无参构造方法,一个是全属性做参数的构造方法

  • 当类中所有成员变量都是常量或者没有成员变量时,建议不提供任何版本的构造。

1.4 方法的重载

一个类中定义的方法名称相同就是方法的重载
特点:

  • 1、方法名称相同。

  • 2、参数列表长度 或 参数类型 或 参数顺序不同。

  • 3、方法的重载与返回值无关。

  • 4、可以让程序在不同的需求下,通过传递不同的参数调用方法来完成某些具体的功能。

代码如下(示例):

public class Demo1 {public static void main(String[] args) {Math math = new Math();//创建对象int sum1 = math.sum(2, 3);//赋值int型数据double sum2 = math.sum(5.1,6.8);//赋值double型数据System.out.println(sum1);//5System.out.println(sum2);//11.899999999999999}
}
//创建类
class Math{//方法名为sum,参数类型为intint sum(int a,int b){int c = a + b;return c;}//方法名为sum,参数类型为doubledouble sum(double a,double b){double c = a + b;return c;}//方法名相同,参数列表类型不同double sum(int b,double a){double c = a + b;return c;}
}

注意方法重载与返回值类型无关

1.5 构造方法的重载

构造方法的重载其实和方法的重载很像。
一个类,可以存在多个构造方法。
参数列表的长度或类型不同即可完成构造方法的重载。
可以在不同的创建对象需求下,调用不同的方法来完成对象的初始化。

代码如下(示例):

public class Demo2 {public static void main(String[] args) {Person2 p = new Person2("张三",20);p.show();//姓名:张三 年龄:20Person2 p1 = new Person2("李四");p1.show();//姓名:李四 年龄:0}
}
//类名为:Person2
class Person2{//属性String name;//姓名int age;//年龄//构造方法1(无参数形式)public Person2(){}//构造方法2(一个参数形式)public Person2(String name2) {name = name2;}//构造方法3(全属性参数形式)public Person2(String name2, int age2) {name = name2;age = age2;}//方法void show(){System.out.println("姓名:"+name+" 年龄:"+age);}
}

在类person2中,三个构造方法的参数类型或列表长度都不相同,但构造方法名称相同,这样的情况就是构造方法的重载。

1.6 匿名对象

顾名思义没有对象名称的对象,就是匿名对象

匿名对象只能使用一次,因为没有任何的对象引用,所以将称为垃圾,
等待被GC(垃圾回收器)回收。
只使用一次的对象可以通过匿名对象的方式完成。

代码如下(示例):

public class Demo3 {public static void main(String[] args) {//没有名字的对象,就是匿名对象new Person3("王五",25).show();//姓名:王五 年龄:25}
}class Person3{String name;int age;public Person3(String name3, int age3) {name = name3;age = age3;}void show(){System.out.println("姓名:"+name+" 年龄:"+age);}
}

注意:如果一个对象要使用两次以上,就必须给创建对象赋值名称。


二、面向对象(进阶篇)

2 面向对象进阶

2.1 封装 private

概述:封装的意义在于保护或者防止数据被其它数据随意访问,导致程序无意被破坏。

在编写程序代码时,首先考虑哪些数据可以封装为一个单位,将属性和方法确定后统一协调使用,大大优化模块间的相互作用。

封装原则:隐藏对象的属性和实现细节,仅对外公开访问法,并且控制访问级别。

为了便于理解,观察如下代码:

//描述人的类Person2
class Person2{//属性String name;//姓名int age;//年龄//说的方法void say(){System.out.println("我是:"+name+" 年龄:"+age);}
}

上面的代码将Person2封装为一个整体。

将上述代码放到程序入口类
如下面代码:

public class Demo2 {public static void main(String[] args) {Person2 p = new Person2();p.name = "小红";p.age = -99;p.say();}
}

运行结果为:

我是:小红,年龄:-99岁。进程已结束,退出代码 0

在上面这段代码中,整个流程下来程序是没有报错的,但是小红年龄-99岁,在现实中,显然是不合逻辑的。

那么针对这个问题,就可以选择用权限修饰符private(私有的)将类的”age“属性年龄私有化,也就是外部无法直接访问年龄。
再提供一些可供外部调用数据和验证数据的方法,外部相当于间接操作类的年龄,最终问题解决。

改进代码如下:

//描述人的类Person2
class Person2{//属性String name;//姓名//private修饰age,使其私有化,只有本类才能使用private int age;//年龄//可供外部调用的方式public void setAge(int age2) {//再通过传入的参数进行判断if (age2 < 0 || age2 > 150){age2 = 18;System.out.println("年龄设置不合理,已自动修正为默认值18。");}else {age = age2;}}//说的方法void say(){System.out.println("我是:"+name+",年龄:"+age+"岁。");}
}

程序入口:

public class Demo2 {public static void main(String[] args) {Person2 p = new Person2();p.name = "小明";//p.age = -99;//如果继续使用会报错p.setAge(-888);p.say();}
}

运行结果:

年龄设置不合理,已自动修正为默认值18。
我是:小明,年龄:18岁。进程已结束,退出代码 0

提示:在以后的开发中,为了避免出现类似的逻辑错误,建议对所有属性进行封装,也就是加以private(私有的),并为其提供SetterGetter方法进行设置和取得数据操作。

2.2 this

在Java基础中,this关键字是一个最重要的概念。 使用this关键字可以完成一下操作:

  • 调用类中的属性

  • 调用类中的方法或构造方法

  • 表示当前对象

观察下面一段代码(示例):

public class Person{private int age;public void setAge(int age){age = age;}
}

在setAge方法体中,我们的想通过方法参数的age传进来赋值给属性age。
但是在执行过程中呢,其实是方法的参数age传给本身参数age,那么这段代码是没有意义的。
那么如何解决这个问题呢。那就是使用Java中的关键字this来表示当前对象,调用当前对象的属性。

添加this后代码如下(示例):

public class Person{private int age;public void setAge(int age){this.age = age;}
}

2.3 static

2.3.1 概述

static表示“静态”的意思,可以用来修饰成员变量和成员方法。
static的主要作用在与创建独立于具体对象的域变量或者方法。

通俗来说:
static关键字修饰的方法或者变量不需要依赖于对象来进行访问
只要类被加载了,就可以通过类名去进行访问
并且不会因为对象的多次创建,而在内存中建立多份数据。

代码如下(示例):

public class Demo3 {public static void main(String[] args) {Person p1 = new Person("小明","北京");Person p2 = new Person("小三","北京");Person p3 = new Person("小李","北京");Person p4 = new Person("小红","北京");p1.say();p2.say();p3.say();p4.say();}
}
class Person{String name;//姓名String place;//地方public Person(String name,String place) {this.place = place;this.name = name;}void say() {System.out.println("姓名:"+name+",居住:"+place);}
}

运行结果是这样的:

姓名:小明,居住:北京
姓名:小三,居住:北京
姓名:小李,居住:北京
姓名:小红,居住:北京进程已结束,退出代码 0

观察代码就会发现,这些人都在“北京”这个地方,那么同一个地方就引用了4次,这显然会造成内存浪费。针对这个问题,就可以用static去解决了。

格式:

类名.静态成员变量 = 数值;

类名.静态方法名();

添加static后的代码(示例):

public class Demo3 {public static void main(String[] args) {//不需要创建对象就能调用placPerson.place = "北京";Person p1 = new Person("小明");Person p2 = new Person("小三");Person p3 = new Person("小李");Person p4 = new Person("小红");p1.say();p2.say();p3.say();p4.say();}
}
class Person{private String name;//姓名//只要类被加载,就可以访问被static修饰的成员变量static String place;//地方public Person(String name,String place) {this.place = place;this.name = name;}public Person(String name){this.name = name;}void say() {System.out.println("姓名:"+name+",居住:"+place);}
}

static修饰方法名也是同理:

添加static后的方法代码(示例):

public class Demo3 {public static void main(String[] args) {//不需要创建对象就能调用类的方法Person.say();}
}
class Person{  //用static修饰方法名static void say() {System.out.println("床前明月光,疑是地上霜。");}
}

注意:

  1. 静态成员,在加载类时加载并初始化。

  2. 无论一个类存在多少个对象,对象的属性,在内存永远中只有一份

  3. 在调用时,静态不能访问非静态,非静态可以访问静态。

2.4 代码块

代码块就是在程序中编写代码的区域,通常用大括号{}表示代码块。
代码块又分为普通代码块、构造代码块、静态代码块等。

2.4.1 普通代码块

在执行的流程中出现的代码块,称其为普通代码块。
代码(示例):


public class Demo1 {public static void main(String[] args) {{/*** 编写在执行顺序的代码流程中的代码块* 就是普通代码块*/}}
}

2.4.2 构造代码块

在类中的成员代码块,称其为构造代码块,在每次对象创建时执行,执行在构造方法之前。
代码(示例):

class Person1{private String name;private int age;//构造代码块,随着对象的每次创建,执行一次//且执行在构造方法之前{System.out.println("这里是构造代码块");}//无参构造方法public Person1(){System.out.println("创建对象时执行");}//全参构造方法public Person1(String name, int age) {this.name = name;this.age = age;}
}

构造代码块区别于构造方法的是:
无论你调用哪一个构造方法来创建对象,构造代码块都必须执行一次。

2.4.3 静态代码块

在类中使用static修饰的成员代码块,称其为静态代码块。
在类加载时,静态代码块执行。
每次程序启动到关闭,只要类被加载了,就始终只执行一次静态代码块。
代码(示例):

public class Demo1 {public static void main(String[] args) {{/*** 编写在执行顺序的代码流程中的代码块* 就是普通代码块*/}Person1 p;Person1 p0 = new Person1();Person1 p1 = new Person1();Person1 p2 = new Person1();}
}class Person1{private String name;private int age;//构造代码块{System.out.println("这里是构造代码块");}static {System.out.println("静态代码块执行且执行一次");}//无参构造方法public Person1(){System.out.println("创建对象时执行");}//全参构造方法public Person1(String name, int age) {this.name = name;this.age = age;}
}

运行结果:

静态代码块执行且执行一次
这里是构造代码块
创建对象时执行
这里是构造代码块
创建对象时执行
这里是构造代码块
创建对象时执行进程已结束,退出代码 0

重点:
构造方法构造代码块以及静态代码块的执行顺序:

静态代码块 > 构造代码块 > 构造方法

2.5 包

设包是Java语言提供的一种组织代码文件和管理代码文件的技术。

2.5.1 包介绍

  1. 把功能相似或相关的类或接口组织在同一个包中,方便类的查找和使用。

  2. 包就跟文件夹一样,不同的包中的类的名字是可以相同的,当同时调用两个不同包中相同类名的类时,应该加上包名加以区别。这样就可以避免一些类名字冲突的情况。

  3. 包也限定了访问权限,拥有包访问权限的类才能访问某个包中的类。

2.5.2 包的命名规则

包的命名规则遵循标识符命名规则,同时包名也有自己的命名规范:

  1. 通常由多个单词组成。

  2. 包名单词全部小写

  3. 如果有多个单词,单词之间使用英文( . )分割。

包中java文件的定义:
在.java文件的首部,必须编写类所属哪个包。
格式:

package 包名;

注意:
如果想要跨包访问某个类的成员,
则此类的成员需要使用权限修饰符“public

Java中默认的导入包是“java.lang”包,其中包含了“String”类、“System”类、“Math”类等常用类。

2.5.3 import 关键字

格式:
import 包名.类名;

代码(示例):

package test725;import java.util.Scanner;public class outTest {public static void main(String[] args) {Scanner input = new Scanner(System.in);}
}

在上面一段代码中,如果需要从控制台获取用户输入内容时,就需要导入Scanner包。

2.6 权限修饰符

权限修饰符可以访问我们在Java需要的资源,比如类的方法、类的属性、构造方法等。
下面是4种权限修饰符的一些使用范围。

修饰符 子类 其他包
public
protected ×
default × ×
private × × ×

三、面向对象(高级篇)

3 面向对象高级

3.1 继承

继承是java面向对象编程技术的一块基石,因为它允许创建等级层次的类。
继承就是子类继承父类的特征和行为
使得子类对象(实例)具有父类的实例域和方法
或子类从父类继承方法,使得子类具有父类相同的行为

继承格式:

//格式:
class 父类{}
class 子类 extends 父类{}

代码(示例):

public class Demo4 {public static void main(String[] args) {//创建子类的对象Student4 s = new Student4();s.setName("小明");//调用父类的setName设置姓名s.setAge(18);//调用父类的setAge设置年龄s.say();//调用父类的方法}
}//格式:
class Person4{private String name;private int age;public  Person4(){super();}public Person4(String name, int age) {super();this.name = name;this.age = age;}public String getName() {return name;}public void setName(String name) {this.name = name;}public int getAge() {return age;}public void setAge(int age) {this.age = age;}public void say(){System.out.println("你好!我是:"+name+", 今年:"+age+"岁。");}
}/*** 继承用到 extends关键字*/
class Student4 extends Person4{//子类可以继承父类的特征和行为
}

继承的限制:
Java中只有单继承、多重继承,没有多继承。

3.2 super

super是在子类对象被创建时,先在内存创建父类对象,创建完父类对象后会在子类自动创建super
super就相当于是父类对象的内存地址,子类通过super也就是内存地址去访问父类对象相关资源。
如下图所示:Person作为父类对象,Student作为子类对象,在Student中自动生成super,而super对应父类对象的内存地址0x123,这样子类就可以通过super去访问父类对象的属性name和age了。

通过super

可以访问父类构造方法属性方法

调用super构造方法的代码,必须写在子类构造方法的第一行。
代码(示例):

class Student4 extends Person4{//子类构造方法public Student4(){//super必须写 在构造方法第一行super("张三",18);//访问构造方法super.sex = "男";//访问属性(父类的属性不能是private)super.say();//访问方法}
}

3.3 重写

重写主要是用在子类继承父类的方法时,父类的方法不符合某些要求,需要对该方法进行重写。

重写(override)规则:

  1. 参数列表必须完全与被重写方法的相同;

  2. 返回类型必须完全与被重写方法的返回类型相同;

  3. 访问权限不能比父类中被重写的方法的访问权限更低;

  4. 父类的成员方法只能被它的子类重写;

  5. 声明为staticprivate的方法不能被重写,但是可以再次声明。

代码(示例):

public class Demo5 {public static void main(String[] args) {Student s = new Student();s.say();//输出:西出阳关无故人}
}
//父类
class Person{public void say(){System.out.println("锄禾日当午,汗滴禾下土。");}
}
//子类
class Student extends Person{//重写父类say()public void say(){System.out.println("西出阳关无故人");}
}

重点:

重写与重载的区别:

区别 重写(Override) 重载(Overload)
发生的位置 字父类中 一个类中
参数列表限制 必须相同 必须不同
返回值类型 必须一致 无关
访问权限 子类不能小于父类 无关
异常处理 范围更小,不能抛出新的异常 无关

3.4 final

final关键字:

1.final用于修饰属性、变量

变量成为了常量,无法对其再次进行赋值

final修饰的局部变量,只能赋值一次(也可先声明后赋值一次)

final修饰的是成员属性,必须在声明时赋值

代码(示例):

final int a = 10;
final int b;//先声明
b = 20;//只能赋值一次

2.final用于修饰类

final修饰的类,不可以被子类继承

代码(示例):

final class Person{//被final修饰后,Person不能被继承
}

3.final用于修饰方法

final修饰的方法,不能被子类重写

代码(示例):

class Person{//被final修饰的方法,不能被子类声明final public void say(){System.out.println("锄禾日当午,汗滴禾下土。");}
}

3.5 抽象类

3.5.1 概念

抽象类必须使用abstract class声明
一个抽象类中可以没有抽象方法。
抽象方法必须写在抽象类或接口中。

代码格式:

abstract class 类名{//抽象类
}

3.5.2 抽象方法

只声明而未实现的方法成为抽象方法
未实现指的是:没有{}方法体。
抽象方法必须使用abstract关键字声明。

代码格式:

abstract class 类名{//抽象类//抽象方法,只声明,不实现具体内容public abstract void 方法名();

3.5.3 不能被实例化

在抽象类的使用中有几个原则:

  • 抽象类本身是不能直接进行实例化操作的,即:不能只用关键字new完成。

  • 一个抽象类必须被子类所继承,被继承的子类(如果不是抽象类)则必须覆写(重写)抽象类中的全部抽象方法。

3.5.4 常见问题

1、抽象类能否使用final声明?

答:不能。因为final属于修饰的类是不可以被继承,即不饿有子类的,而抽象类必须有子类才有意义,所以不能使用final声明。

2、抽象类能否有构造方法?

答:有构造方法。而且子类对象实例化的流程与普通类的继承是一样的,都是要先调用父类中的构造方法,之后再调用子类自己的构造方法。

3.5.5 抽象类和普通类的区别

1、抽象类必须用publicprotected修饰,如果为private修饰,那么子类则无法继承,也就无法实现其抽象方法。

2、抽象类不可以使用new关键字创建对象,但是在子类创建对象时,抽象父类也会被JVM实例化。

3、如果一个子类继承抽象类,那么必须实现其所有的抽象方法。
如果有未实现的抽象方法,那么子类也必须定义为abstract类。

3.6 接口

3.6.1 概念

如果一个类中的全部方法都是抽象类,全部属性都是全局常量,那么此时就可以将这个类定义成一个接口

定义格式:

interface 接口名称{全局常量;抽象方法;
}

3.6.2 面向接口编程思想

这种思想是定义(规范、约束)与实现(名实分离的原则)的分离。

优点:

  1. 降低程序的耦合性

  2. 易于程序的扩展

  3. 有利于程序的维护

3.6.3 全局常量和抽象方法的简写

因为接口本身都是由全局常量和抽象方法组成,所以接口中的成员定义可以简写:
1、全局常量编写时,可以省略public static final 关键字
例如:

public static final String NAME = "张三";

简写后:

String NAME = "张三";

2、抽象方法编写时,可以省略public abstract 关键字,
例如:

public abstract void say();

简写后:

void say();

3.6.4 接口的实现

接口的实现跟抽象很类似,但是又不完全同于抽象。
在接口的实现中,需要用到implemnts关键字。
接口可以进行多实现操作:
格式:

class 子类 implements 父接口1,父接口2...{}

以上的代码成为接口的实现,那么如果一个类即要实现接口,又要继承抽象类的话,则按照以下的格式编写即可:

class 子类 extends 父类 implements 父接口1,父接口2...{}

3.6.5 接口的继承

接口因为都是抽象抽象部分,不存在具体的实现,所以允许多继承。

例如:

interfacce C extends A,B{}

注意:
一个接口想要使用,必须依靠子类。
子类(如果不是抽象类的话)要实现接口中的所有抽象方法。

3.6.6 接口和抽象类的区别

1、抽象类要被子类继承,接口要被类实现。
2、接口只能声明抽象方法,抽象类中可以声明抽象方法,也可以写非抽象方法。
3、接口里定义的变量只能是公共的静态常量,抽象类种的变量是普通变量。
4、抽象类使用继承来使用,无法多继承。接口使用实现来使用,可以多实现。
5、抽象类中可以包含static方法,但是接口中不允许。(静态方法不能被子类重写,因此接口中不能声明静态方法)
6、接口不能有构造方法,但是抽象类可以有。

这里写一个简单的代码示例:

接口1(Person):

//接口
public interface Person {void say();
}

接口2(Person1):

public interface Person1 {String name = "张三";int age = 18;
}

子类1(单实现):

public class Docter implements Person {@Overridepublic void say() {System.out.println("我是医生");}
}

子类2(多实现):

public class Student4 implements Person,Person1{@Overridepublic void say() {System.out.println("我叫:"+name+",今年"+age);}
}

程序入口测试:

public class Demo4 {public static void main(String[] args) {Student4 s = new Student4();say(s);}public static void say(Person p){p.say();}
}

运行结果:

我叫:张三,今年18
我是医生Process finished with exit code 0

3.7 多态

多态就是对象的多种表现形式。

3.7.1 多态的体现

对象的多态性,从概念上非常好理解,在类中有子类和父类之分,子类就是父类的一种形态,对象多态性就是这样来的。

注意:
方法的重载和重写也是多态的一种,不过是方法的多态。
重载:一个类中方法的多态性体现。
重写:子父类中方法的多态性体现。

3.7.2 多态的使用

多态的使用也就是对象的类型转换。
格式1:
向上转型:将子类实例变为父类实例

父类 父类对象 = 子类实例;//代码(示例):
Student s = new Student();
Person p = s;
p.say();

格式2:
向下转型:将父类实例变为子类实例

子类 子类对象 = 父类实例(子类)//代码(示例):
Student s = new Student();
Person p1 = s;
Student s1 = (Student)p1;
s1.say();

3.7.3 instanceof

instanceof关键字:
作用:判断某个对象是否是指定类的实例,则可以使用instanceof关键字

格式:

实例化对象 instanceof 类 //此操作返回boolean类型的数据

代码(示例):


public class Demo4 {public static void main(String[] args) {//创建学生类Student4 s = new Student4();say(s);//打印:我叫:张三,今年18//创建医生类Docter d = new Docter();say(d);//打印:必须传进Student4形态类可以。//因为医生类是跟学生类同一级,故不能把医生类强制转换为学生类//只能把医生类转化为Person类,而不能转为Student类。}public static void say(Person p){//判断传入的对象是此类的哪种形态if(p instanceof Student4){Student4 s = (Student4)p;s.say();}else{System.out.println("必须传进Student4形态类可以。");}}
}

3.8 Object类

3.8.1 概念

Object类是所有类的父类,如果一个类没有明确的继承某一个具体的类,则将默认继承Object类。

例如我们定义一个类:

public class Person{}

当没有其它继承时,它其实在使用过程中是这样的:

public class Person extends Object{}

3.8.2 Object的多态

使用Object可以接受任意的引用数据类型

代码(示例):

public class Demo1 {public static void main(String[] args) {String name = "张三";say(name);int age = 18;say(18);}//使用Object可以接收任何数据public static void say(Object o){System.out.println(o);}
}

简单的说,Object是Java中的万物,它在java语言中有很多方法、比如toString()、equals()、hashCode()等等。

3.8.3 toString

在程序中,一般建议在所有类中都去重写Object中的toString方法。
此方法的作用:返回对象的字符串表示形式。
ObjecttoString方法,返回对象的内存地址。

代码(示例):

public class Person6 {private String name;private int age;//toString方法@Override//重写后可以根据自己下需求去更改方法public String toString() {return "Person6{" +"name='" + name + '\'' +", age=" + age +'}';}
}

小提示:
在IDEA编辑器中使用快捷键Alt+Insert可快速找到toString方法,如下图,
在eclipse中的快捷键是Alt+Shift+s

3.8.4 equals

建议重写Object中的equals(Object obj)方法。
此方法的作用:指示某个其他对象是否“等于”此对象。

Objectequals方法:
实现了对象上最具区别的可能等价关系;
也就是说,对于任何非空引用值x和y,
当且仅当x和y引用同一对象(x == y具有值true)时,此方法返回true

equals方法重写时的五个特性:

自反性:对于任何非空的参考值x, x.equals(x)应该返回true

对称性:对于任何非空引用值x和y,x.equals(y)应该返回true当且仅当y.equals(x)回报true

传递性:对于任何非空引用值x,y和z,如果x.equals(y)回报true,而y.equals(z)回报true,那么有x.equals(z)同样返回true

一致性:对于任何非空引用值x和y,多次调用x.equals(y)始终返回true或始终返回false,前提是未修改对象上equals上比较中使用的属性。

非空性:对于任何非空的参考值x,x.equals(null)应该返回false

案例:使用equals()完成随机数的比较

3.9 内部类

3.9.1 概念

在Java中,可以将一个类定义在另一个类里面或者一个方法里面,这样的类称为内部类

广泛意义上的内部类一般来说包括这四种:

  1. 成员内部类
  2. 局部内部类
  3. 匿名内部类
  4. 静态内部类

3.9.2 成员内部类

成员内部类是最普通的内部类,它的定义为:
位于另一个类的内部

代码(示例):

class Outer {private String name = "张三";private int age = 18;public Outer(String s){this.s = s;}//内部类class Inner {//内部类的写法和外部类没有太大的区别private String name = "李四";private int age = 20;public void say() {            System.out.println("我叫:"+name+",今年"+age+"岁");System.out.println("我叫:"+Outer.this.name+",今年"+Outer.this.age+"岁");}}
}

特点:
成员内部类可以无条件访问外部类的所有成员属性和成员方法,包括private成员和静态成员。

注意:
当成员内部类拥有和外部类同名的成员变量或者方法时,会发生隐藏现象,也就说在访问同名情况下,调用的是成员内部类的成员。

如果需要访问外部类的同名成员,需要以下面的形式进行访问:

外部类.this.成员变量
外部类.this.成员方法

外部使用成员内部类格式:

Outer o = new Outer();
Outer.Inner i = o.new Inner();

代码(示例):

public class Demo8 {public static void main(String[] args) {Outer o = new Outer();Outer.Inner i = o.new Inner();i.say();}
}

运行结果:

我叫:李四,今年20岁
我叫:张三,今年18岁

3.9.3 局部内部类

局部内部类是定义在一个方法或者一个作用域里面的类。

它和成员内部类的区别:
在于局部内部类的访问仅限于方法内或者该作用域内。

class Person7{public Person7(){}
}
class Man{public Man(){}public Person7 getPerson(){class Student7 extends Person7{//局部内部类String name = "王五";}return new Student7();}
}

注意:
局部内部类就像是方法里面的一个局部变量一样,
是不能有publicprotectedprivate、以及static修饰符的。

3.9.4 匿名内部类

匿名内部类由于没有赋予名字,所有它的创建方式有点奇怪
创建格式:

new 父类构造器(参数列表) |实现接口(){//匿名内部类
}

在这里我们看到使用匿名内部类,必须要继承一个父亲类或者实现一个接口,当然也仅能只继承一个父类或者实现一个接口。同时它也是没有class关键字,这是因为匿名内部类是直接使用new来生成一个对象的引用。

在使用匿名内部类的过程中,我们需要注意以下几点:

  1. 使用匿名内部类时,我们必须是继承一个类或者实现一个接口,但是两者不可兼得,同时也只能继承一个类或者实现一个接口。
  2. 匿名内部类中是不能定义构造函数的。
  3. 匿名内部类中不能存在任何的静态成员变量和静态方法。
  4. 匿名内部类为局部内部类,所以局部内部类的所有限制同样对匿名内部类生效。
  5. 匿名内部类不能是抽象的,它必须要实现继承的类或者实现的接口的所有抽象方法。
  6. 只能访问final型的局部变量。

3.9.5 静态内部类

静态内部类也是定义在另一个类里面的类,只不过在类的前面多了一个关键字static。
静态内部类是不需要依赖于外部类对象的,这点和类的静态成员属性有点类似,并且他不能使用外部类的非static成员变量或者方法。

格式:

class Outer{public Outer(){}static class Inner{//静态内部类public Inner(){}}
}

3.10 包装类

3.10.1 概述

在Java中有一个设计的原则“一切皆对象”,那么这样一来Java中的一些基本数据类型,就完全不符合这种设计思想,因为Java中的八种基本数据类型并不是引用数据类型,所以Java中为了解决这样的问题,引入了八种基本数据类型的包装类。

序号 基本数据类型 包装类
1 int Integer
2 char Character
3 float Float
4 double Double
5 boolean Boolean
6 byte Byte
7 short Short
8 long Long

以上的八种包装类,可以将基本数据类型按照类的形式进行操作。
上面八种包装类又分为两种大的类型Number和Object。

  • Number:Integer、Short、Long、Double、Float、Byte都是Number的子类表示是一个数字。
  • Object:Character、Boolean都是Object的直接子类。

3.10.2 装箱和拆箱操作

将一个基本数据类型变为包装类,那么这样的操作称为装箱操作
将一个包装类变为一个基本数据类型,这样的操作称为拆箱操作

总结

以上就是我对面向对象知识整理做一些笔记,或许有些地方写得还没有那么全面,欢迎指出,给出合理性的建议。

这篇算是我第一次做知识方面的笔记,希望在某些知识点上可以帮到大家。

什么是Java面向对象(实例详解)相关推荐

  1. Java面向对象知识详解——三大基本特征

    文章目录 前言 什么是面向过程? 什么是面向对象? 三大基本特征 封装 继承 多态 Java中的多态 最后 前言 相信很多程序员在最初接触Java的时候就听过,Java中一切皆对象那么什么是面向对象呢 ...

  2. java ee实例详解_Java EE企业级编程开发实例详解

    第1章 javaee开发基础 9 q5 @! t4 \9 t. }: K# R1 }1.1 javaee6简介 / p* T1 g! F  K3 ^4 j3 |1.1.1学习 javaee的意义 5 ...

  3. Java 线程池详解及实例代码

    转载自  Java 线程池详解及实例代码 这篇文章主要介绍了Java 线程池的相关资料,并符实例代码,帮助大家学习参考,需要的朋友可以参考下 线程池的技术背景 在面向对象编程中,创建和销毁对象是很费时 ...

  4. mongodb java查询_java操作mongoDB查询的实例详解

    java操作mongo查询的实例详解 前言: MongoDB是一个基于分布式文件存储的数据库.由C++语言编写.旨在为WEB应用提供可扩展的高性能数据存储解决方案. MongoDB是一个介于关系数据库 ...

  5. java异常例子_java 异常的实例详解

    java 异常的实例详解 1.异常的定义:程序在运行时出现不正常情况. 异常的划分: Error:严重的问题,对于error一般不编写针对性的代码对其进行处理. Exception:非严重的问题,对于 ...

  6. java写exe程序实例,java实现可安装的exe程序实例详解

    java实现可安装的exe程序实例详解 通过编写java代码,实现可安装的exe文件的一般思路: 1.在eclipse中创建java项目,然后编写java代码,将编写好的java项目导出一个.jar格 ...

  7. java测试类 main方法_Java使用agent实现main方法之前的实例详解

    Java使用agent实现main方法之前的实例详解 创建Agent项目 PreMainExecutor 类,在main方法之前执行此方法 public class PreMainExecutor { ...

  8. java中匿名内部类详解_java 中匿名内部类的实例详解

    搜索热词 java 中匿名内部类的实例详解 原来的面貌: class TT extends Test{ void show() { System.out.println(s+"~~~哈哈&q ...

  9. java objectoutputstream怎么用_java序列化与ObjectOutputStream和ObjectInputStream的实例详解...

    java序列化与ObjectOutputStream和ObjectInputStream的实例详解 一个测试的实体类: public class Param implements Serializab ...

  10. java 静态 编译_Java中的动态和静态编译实例详解

    Java中的动态和静态编译实例详解 首先,我们来说说动态和静态编译的问题. Q: java和javascript有什么区别? 总结了一下:有以下几点吧: 1.首先从运行环境来说java代码是在JVM上 ...

最新文章

  1. php启用日志记录,PHP SDK启用日志功能报错
  2. 对象存储与块存储、文件存储等对比
  3. 如果我有jQuery背景,那么“ AngularJS中的思考”吗? [关闭]
  4. vb和python-vb与python
  5. Hadoop on Mac with IntelliJ IDEA - 3 解决MRUnit - No applicable class implementing Serialization问题...
  6. chart绑定mysql数据源_MSChart图表之Chart组件 学习一篇(5个主要属性+数据源绑定)...
  7. php自动转换和强制转换,Java数据类型转换(自动转换和强制转换)
  8. c语言开发 .c .h,求助C语言大佬 , 只会写到一个.c文件里 ,不会用.h头文件
  9. [上下界网络流][二分] Bzoj P2406 矩阵
  10. Application Fundamentals
  11. python双线性插值函数_双线性插值法原理 python实现
  12. 有赞零售财务中台架构设计与实践
  13. 查看电脑已安装的cuda版本
  14. 比赛记录——记录一次失败的比赛,九坤量化验证码识别大赛
  15. linux 入门 及一些常用命令及常用软件安装
  16. Piggy Back
  17. 苹果cms用宝塔定时采集+添加百度推送教程
  18. 8 月最新编程语言排行榜
  19. nas文件服务器web接口,nas配置web服务器
  20. EasyPoi快速入门

热门文章

  1. C/C++中 sizeof 详解
  2. 《RISC-V on T-Core》学习笔记
  3. 英伟达RTX4090又火了?这次是真的着火了
  4. 百度输入法开启AI时代,突破方言、中英文混合识别难题
  5. 创建个人中心页面(下)
  6. 以太网学习之二 物理介质(10Base、100Base-T、100Base-TX等)
  7. 用ISO-8859-1解决Python ‘utf-8‘ codec can‘t decode bytes in position 924-925问题
  8. 【计算机系统结构】第5章 存储层次问答题
  9. UiBot 鼠标点击目标
  10. JSP/Servlet基础——ServletMVC小例子