JavaSE面向对象

面向对象


面向对象编程

1 什么是对象?
万物皆对象。
2 什么是面向对象?
面向对象就是指以特征/属性和行为的观点去分析现实世界中事物的方式。

3 什么是面向对象编程?
面向对象编程就是指先以面向对象的方式进行分析,然后采用一门面向对象的编程语言进行翻译的过程。
其中C语言是一门面向过程的编程语言;
其中C++语言是一门既面向过程又面向对象的编程语言;
其中Java语言是一门纯面向对象的编程语言;

4 为什么需要面向对象编程?
面向对象编程是软件产业化和规模化发展的需求。
5 如何学好面向对象编程?
深刻理解和琢磨面向对象编程的三大特性:封装、继承、多态。

Java类

如:
String name1 = "张三";  ... 
String name2 = "李四";  ...
String name3 = "王五";  ...
String name4 = "赵六";  ...
... ...
人类:
特性:姓名、年龄
行为:吃饭、学习

基本概念

对象是现实生活中的实体,在Java语言中本质上就是内存中的一块存储空间。
类简单来说就是”分类”,是多个对象共性提取的抽象描述,在Java中是一种引用数据类型,里面包含了描述特征的成员变量,以及描述行为的成员方法。

类的定义

(1)类定义的语法格式
class 类名{
类体;
}
如:
class Person{
}      

注意:
一般来说,当类名由多个单词组成时,要求每个单词的首字母都要大写。

(2)成员变量定义的语法格式
class 类名{

数据类型 成员变量名 = 初始值;   - 其中=初始值通常省略不写
}   
如:
class Person{
String name;
int age;
}
注意:
一般来说,当成员变量名由多个单词组成时,要求从第二个单词起首字母大写。

对象的创建

(1)语法格式
new 类名();
如:
new Person(); - 表示创建一个Person类型的对象
(2)使用方式
当定义类之后可以使用上述语法格式进行对象的创建/构造,这个过程叫做类的实例化,本质上会在堆区申请一块空间用于存放该对象独有的特征信息。

* 对象创建的过程(了解)*

1 单个对象创建的执行过程
- main()方法是程序的入口,当创建对象时会在堆区申请内存空间;
- 当没有指定成员变量的初始值时,则采用默认初始化进行;
- 当显式指定成员变量的初始值时,则先默认初始化再显式初始化;
- 执行构造块中的代码,可以对成员变量的数值进行更改;
- 执行构造方法体中的代码,可以对成员变量的数值进行更改;
- 此时对象创建完毕,继续执行后续的代码;

2 子类对象创建的执行过程
- main()方法是程序的入口,当创建子类对象时会在堆区申请内存空间;
- 先加载父类再加载子类,因此先执行父类的静态语句块,再执行子类的静态语句块;
- 先构造父类部分再构造子类部分,因此执行父类的构造块,执行父类的构造方法体;
- 执行子类的构造块,执行子类的构造方法体;
- 此时对象构造完毕,继续执行后续的代码;

引用

(1)基本概念
在Java中使用引用数据类型声明的变量叫做引用型变量,简称为"引用"。
(2)语法格式
类名 引用变量名;
如: 
Person p;  - 声明一个Person类型的引用p
(3)使用方式
声明引用变量可以记录对象在堆区中的地址信息,从而可以访问对象中的特征信息,具体方式如下:
引用名.成员变量名;
如:
Person p = new Person();
p.name = "zhangfei";
System.out.println(p.name);

成员方法

1 语法格式

class 类名{
    返回值类型 成员方法名称(形参列表){
        方法体;
    }
}      
如:
class Person{
    void eat(){
        System.out.println("蛋炒饭真好吃!");
    }
}
注意:
一般来说,当成员方法名称由多个单词组成时,要求从第二个单词起首字母大写。

2 方法的详解
(1)返回值类型

返回值主要指从方法体内向方法体外返回的数据内容。
返回值类型就是指返回值的数据类型,可以是基本数据类型,也可以是引用数据类型。

如:
当方法体中返回的数据内容是66时,则返回值类型写int即可;
当方法体中返回的数据内容是3.14时,则返回值类型写double即可;
当方法体中返回的数据内容是"hello"时,则返回值类型写String即可;
在方法体中使用return关键字负责返回数据内容,并结束当前方法。
如:
当返回的数据内容是66时,则方法体中写:return 66;
当返回的数据内容是变量num时,则方法体中写:return num;
当方法体中没有需要返回的数据内容时,则返回值类型写void即可;

(2)形参列表

形式参数主要用于将方法体外的数据内容带入方法体内进行使用,
格式:数据类型 形参变量名
形参列表就是指多个形参参数,语法格式:数据类型 形参变量1, 数据类型 形参变量2,…

如:
当传入的数据内容是66时,则形参列表写为:int i;
当传入的数据内容是3.14时,则形参列表写为:double d;
当传入的数据内容是"hello"时,则形参列表写为:String s;
当传入的数据内容是66和3.14时,则形参列表写为:int i, double d;
当传入的数据内容是66和"hello"时,则形参列表写为:int i, String s;
当不需要向方法体内传入任何数据时,则形参列表位置啥也不写即可;

(3)方法体
方法体主要用于描述该方法的功能,因此编写所有与功能有关的语句块;

方法的调用

(1)语法格式
引用.成员方法名(实参列表);
如:
p.eat();

(2)使用方式
实际参数列表主要用于对形式参数列表进行赋值操作,因此实参列表和形参列表的个数、类型以及先后顺序等必须保持一致。
实际参数可以传递 直接量、变量、表达式、方法的调用等;

构造方法及方法重载

1 构造方法

如:
    Person p = new Person();  - 表示声明Person类型的引用指向Person类型的对象
    p.show();                 - 表示调用Person类中名字为show()的方法
(1)语法格式
   class 类名{
      类名(形参列表){
         构造方法体;
      }
   }   
如:
   class Person{
       Person(){
          System.out.println("构造方法我来了!");
       }
   } 
(2)注意事项
   a.构造方法的名称与类名完全相同;
   b.构造方法没有返回值类型,连void都不能写;
   c.构造方法用于在创建对象时被自动调用,从而实现该对象成员变量的初始化工作;
(3)默认构造方法
   当一个类中没有提供任何形式的构造方法时,编译器会自动生成一个无参的空构造方法,叫做默认/缺省构造方法,如:Person(){}。
   若类中提供了自定义的构造方法,则编译器不再提供任何形式的构造方法。

2 方法的重载(重点)

(1)基本概念
   在Java语言中,允许出现方法名相同、参数列表不同的多个方法存在,这些方法之间构成重载关系(Overload)。

(2)主要形式
   方法重载的主要形式体现在:形参个数不同、形参类型不同、形参顺序不同,与形参变量名无关,与返回值类型无关,但建议返回值类型最好相同。
   判断方法能否构成重载的核心:判断调用该方法时能否加以区分。

(3)实际意义
   方法重载的实际意义就是为了让调用者使用方便,调用者只需要记住一个方法名就可以调用各种不同的版本从而实现各种不同的效果。
如:
   byte b1 = 10;
   System.out.println(b1);
   short s1 = 20;
   System.out.println(s1);
   int i1 = 30;
   System.out.println(i1);   

this关键字

1 基本概念

对于构造方法来说,this关键字就代表当前正在构造的对象;
对于成员方法来说,this关键字就代表当前正在调用的对象;

原理(尽量理解):
this关键字本质上就是构造方法和成员方法中隐含的形参变量,当不同的对象调用同一个方法时,本质上会将不同的对象作为实参传递给形参this,而在方法体中访问成员变量时,相当于this.(我的)的方式进行访问,此时this不同导致成员变量的数值随之不同。

2 使用方式

(1)当形参变量名和成员变量名同名时,在方法体中会优先选择形参变量使用,若希望明确
告诉编译器使用成员变量时,则需要在成员变量名的前面加上this.加以描述。
(2)使用this(实参)的方式在构造方法的第一行可以调用其他构造方法(了解)。

方法的传参和递归调用

8.1 方法的传参过程(尽量理解)

(1)main()方法是程序的入口,因此先为变量a、b、res分配内存空间并初始化;
(2)调用max()方法时,为max()方法的形参变量a、b分配内存空间;   
(3)将实参变量a、b的数值赋值给形参变量a、b;
(4)执行max()方法的方法体,方法结束时会释放形参变量a、b的内存空间;
(5)main()方法中的变量res得到max()方法的返回值,继续向下执行;

要求掌握的内容:

a.当参数类型为基本数据类型时,此时形参数值的改变不会影响到实参数值(独立空间);
b.当参数类型为引用数据类型时,此时若修改形参变量指向的内容会影响到实参数值,
  因为形参和实参指向同一块区域;
c.当参数类型为引用数据类型时,此时若修改形参变量的指向后再修改内容,那么不会
  影响到实参的数值,因为形参变量指向的区域与实参变量不同;

8.2 方法的递归调用(难点)

基本概念
递归就是指在方法体的内部调用该方法自身的形式。

案例:
   自定义成员方法计算参数n的阶乘并返回。
解析:
   5! = 5*4*3*2*1;
   4! = 4*3*2*1;
   ...
   1! = 1;

   5! = 5*4!;
   4! = 4*3!;
   3! = 3*2!;
   2! = 2*1!;
   1! = 1;

使用方式
a.使用递归必须要找到规律和退出条件;
b.使用递归必须使得问题简单化而不是复杂化;
c.若递归影响程序的执行性能,则应该使用递推取代之;

9 类加载机制

10 JVM内存结构 GC

封装


基本概念

通常情况下,在测试类中可以对成员变量进行访问,当给成员变量赋值合法但不合理的数据时,在编译阶段和运行阶段都不会报错或者给出提示,此时与现实生活不符。
为了避免上述问题,就需要对成员变量进行密封包装等处理,这种机制就叫做封装,换句话说,封装就是一种保证成员变量值合理的技术。

封装的流程

  • 私有化成员变量,使用private关键字修饰。
  • 提供公有的get和set成员变量方法,在方法体中进行合理值的判断。
  • 在构造方法中调用set成员变量的方法进行处理。

static关键字

基本概念

通常情况下,成员变量隶属于对象层级,也就是每个对象单独保存自己独有的特征信息,当所有对象中某个特征信息完全一样时还各自记录就会造成内存空间的浪费。
为了节省内存空间,此时可以使用static关键字修饰该成员变量表示静态的概念,所谓静态就是将该成员变量由对象层级提升到类层级,随着类的加载而准备就绪,与对象是否创建无关,建议使用类名.的方式来进行访问。
static关键字也可以修饰成员方法。

使用方式

  • 对于非静态的成员方法来说,既可以访问非静态的成员又可以访问静态的成员;
    (成员:成员变量 + 成员方法 静态成员被所有对象共享)
  • 对于静态的成员方法来说,只能访问静态的成员不能访问非静态的成员;
    (成员:成员变量 + 成员方法 静态的成员在使用时可能还没有创建对象)
  • 只有隶属于类层级被所有对象共享的内容才可以使用static修饰,不能滥用static关键字;

单例设计模式

基本概念

在某些特殊场合中,一个类对外提供一个且只能提供一个对象,这样的类叫做单例类。
设计单例类的思想和方式叫做 单例设计模式。

实现流程

  • 私有化构造方法,使用private关键字修饰;
  • 提供本类类型的引用指向本类类型的对象,并使用private static共同修饰;
  • 提供公有的get成员变量方法,将本类的对象返回出去;

实现方式

单例设计模式主要有:饿汉式 和 懒汉式,在以后的开发中推荐使用饿汉式;

/*
    编程实现Singleton类的封装
 */
public class Singleton{

    //2.提供一个本类类型的引用指向本类自己的对象
    //int cnt = 1;
    //private static Singleton sin = new Singleton();  //饿汉式
    private static Singleton sin = null;               //懒汉式

    //1.私有化构造方法,使用private关键字修饰
    //只能在本类的内部使用
    private Singleton(){
    }

    //3.提供一个公有的方法将sin的数值返回出去
    public static Singleton getInstance(){
         //return sin;
         if(sin == null){
             sin = new Singleton();
         } 
         return sin;
    }
}

继承

基本概念

当多个类之间有相同的特征和行为时,可以将共性的内容提取出来组成一个公共类,让这多个类分别吸收公共类中的特征和行为,而在各个类的内部只需要编写独有特征和行为的机制,叫做继承.
使用继承可以提高代码的复用性和可扩展性以及可维护性。
在Java语言中使用 extends 来表达继承的关系。

如:
public class Student extends Person{}  - 表示Student类继承自Person类
其中Person类叫做 超类/父类/基类。
其中Student类叫做 派生类/子类/孩子类。

注意事项
- 子类可以继承父类的成员变量和成员方法,包括私有的成员变量但不能直接使用;
子类不可以继承父类的构造方法 和 私有方法。
- 无论使用何种形式构造子类的对象时,都会自动调用父类的无参构造方法来初始化从
父类中继承下来的成员变量,相当于在子类构造方法的第一行增加代码:super();的效果。
- Java语言支持单继承不支持多继承,也就是一个子类只能有一个父类,一个父类可以有
多个子类。
- 使用继承必须满足以下逻辑关系: 子类 is a 父类,也就是不能滥用继承。

this和super的比较

基本概念
this代表 一个本类的对象;
super代表 一个父类的对象;

使用方式
使用this.的方式可以访问本类的成员;
使用super.的方式可以访问父类的成员;

使用this()的方式在构造方法的第一行表示调用本类中的其他构造方法;
使用super()的方式在构造方法的第一行表示调用父类的构造方法;

要求掌握的用法:

a.使用this.的方式区分同名的成员变量和局部变量;
b.使用super(实参)的方式调用父类的构造方法;
c.使用super.的方式可以调用父类中被重写的方法;

方法的重写

基本概念

当父类中继承下来的方法不足以满足子类的需求时,则需要在子类中重新写一个和父类一样的方法去覆盖从父类中继承下来的方法,这种方式叫方法的重写(Override)。

基本原则
- 要求方法名、参数列表、返回值类型相同,从jdk1.5开始允许返回子类类型;
- 要求访问权限不能变小,可以相同或者变大;
- 要求不能抛出更大的异常(异常机制);

访问控制


常见的访问控制符

public - 公有的
protected - 保护的
啥也不写 - 默认的
private - 私有的

访问控制符之间的比较

访问控制符 访问权限 本类 本包中的类 子类 其它包的类
public 公有的 Y Y Y Y
protected 保护的 Y Y Y N
默认的 Y Y N N
private 私有的 Y N N N

要求大家掌握的内容
- public修饰的成员可以在任意位置访问;
- private修饰的成员只能在本类的内部访问;
- 通常情况下,成员变量都使用private修饰,成员方法都使用public修饰;

3 包的定义

package 包名;  - 用于声明单层包
package 包名1.包名2...包名n; - 用于声明多层包,主要为了管理文件和区分同名文件

final关键字

基本概念
final本意为”最终的,不可更改的”,可以修饰类、方法以及成员变量。

使用方式
使用final修饰类体现在该类不能被继承;
- 为了防止滥用继承,如:String类、System类等。
使用final修饰方法体现在该方法不能被重写;
- 为了防止不经意间造成的重写,如:SimpleDateFormat类中的format()方法。
使用final修饰成员变量体现在该成员变量必须被初始化而且不能更改;
- 为了防止不经意间造成的修改,如:Thread类的MAX_PRIORITY。

注意:

在以后的开发中static和final关键字很少单独使用,通常使用public static final共同修饰表达常量的概念,常量的命名规范是:所有字母大写,不同单词之间使用下划线连接。
如:
public static final double PI = 3.14;

多态

基本概念
多态就是指同一种事物表现出来的多种形态**

如:
    饮料:可乐、雪碧、加多宝、乐虎、... 
    宠物:猫、狗、乌龟、鸟、小强、...
    整数:byte b1 = 10; short s1 = 10;  int i1 = 10; ...
    ... ...

语法格式

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

如:
Pet p = new Cat();
p.show(); 

原理:
在编译阶段p是Pet类型的引用,只能调用Pet类中的show()方法;
在运行阶段p真正指向的对象是Cat类型的,因此最终调用Cat类中重写的show()方法。

多态的效果

  • 使用父类的引用指向子类的对象时,父类的引用可以直接调用父类自己的方法;
  • 使用父类的引用指向子类的对象时,父类的引用不可以直接调用子类独有的方法;
  • 对于父子类都有的非静态成员方法来说,最终调用子类重写的版本;
  • 对于父子类都有的静态成员方法来说,最终调用父类中的版本,与所指向的对象无关;

引用数据类型之间的转换

  • 引用数据类型之间的转换分为两种:自动类型转换 和 强制类型转换。
    其中子类类型向父类类型之间的转换发生自动类型转换;
    其中父类类型向子类类型之间的转换发生强制类型转换;
  • 引用数据类型之间的转换必须发生在父子类之间,否则编译报错。
  • 若引用要强转的目标类型不是该引用真正指向的子类类型,则编译通过,运行阶段发生
    类型转换异常。
  • 为了避免上述错误的发生,以后在强制类型转换之前都应该进行类型的判断,如下:
    if(引用变量名 instanceof 目标类型)
    用于判断引用真正指向的对象类型是否为目标类型,若是则返回true,否返回false

多态的实际意义

多态的实际意义在于屏蔽不同子类之间的差异性实现通用的编程,从而带来不同的结果。

猜你喜欢

转载自blog.csdn.net/ym_ily/article/details/81266742