如何讲清楚 Java 面向对象的问题与知识?(类与对象,封装,继承,多态,接口,内部类...)

二 Java面向对象

  1. 类和对象
    1.1 什么是面向过程?什么又是面向对象?
    面向过程——步骤化

面向过程就是分析出实现需求所需要的步骤,通过函数(方法)一步一步实现这些步骤,接着依次调用即可

面向对象——行为化(概念相对抽象,可结合下面的例子理解)

面向对象是把整个需求按照特点、功能划分,将这些存在共性的部分封装成类(类实例化后才是对象),创建了对象不是为了完成某一个步骤,而是描述某个事物在解决问题的步骤中的行为

1.1.1 能举个例子谈谈你对面向过程和面向对象的理解吗
例如我们设计一个桌球游戏(略过开球,只考虑中间过程)
A:面向过程方式思考:
把下述的步骤通过函数一步一步实现,这个需求就完成了。(只为演示概念,不细究逻辑问题)。
① palyer1 击球 —— ② 实现画面击球效果 —— ③ 判断是否进球及有效 —— ④ palyer2击球
⑤ 实现画面击球效果 —— ⑥ 判断是否进球及有效 —— ⑦ 返回步骤 1—— ⑧ 输出游戏结果
B:面向对象方式思考:
经过观察我们可以看到,其实在上面的流程中存在很多共性的地方,所以我们将这些共性部分全集中起来,做成一个通用的结构

玩家系统:包括 palyer1 和 palyer2

击球效果系统:负责展示给用户游戏时的画面

规则系统:判断是否犯规,输赢等

在这里插入图片描述
我们将繁琐的步骤,通过行为、功能,模块化,这就是面向对象,我们甚至可以利用该程序,分别快速实现8球和斯诺克的不同游戏(只需要修改规则、地图和球色即可,玩家系统,击球效果系统都是一致的)
1.1.2 面向过程和面向对象的优缺点
A:面向过程
优点:性能上它是优于面向对象的,因为类在调用的时候需要实例化,开销过大。
缺点:不易维护、复用、扩展
用途:单片机、嵌入式开发、Linux/Unix等对性能要求较高的地方
B:面向对象
优点:易维护、易复用、易扩展,由于面向对象有封装、继承、多态性的特性,可以设计出低耦合的系统,使系统更加灵活、更加易于维护
缺点:一般来说性能比面向过程低

低耦合:简单的理解就是说,模块与模块之间尽可能的独立,两者之间的关系尽可能简单,尽量使其独立的完成成一些子功能,这避免了牵一发而动全身的问题。这一部分我们会在面向对象学习结束后进行系统的整理和总结。

总结:只通过教科书后的例题是无法体会到面向过程所存在的问题的,在一些小例程中,面向过程感觉反而会更加的简单,但是一旦面临较大的项目,我们需要编写N个功能相似的函数,函数越来越多,代码量越来越多,你就知道这是一场噩梦了。

说明:关于性能的问题,这里只是在笼统意义上来说,具体性能优劣,需要结合具体程序,环境等进行比对
1.2 说一说类、对象、成员变量和成员方法的关系和理解
类:一组相关的属性和行为的集合,是一个抽象的概念。
对象:该类事物的具体表现形式,具体存在的个体。
成员变量:事物的属性
成员方法:事物的行为
上面我们说了这几个概念,那么到底应该怎么理解呢?
类就是对一些具有共性特征,并且行为相似的个体的描述。
比如小李和老张都有姓名、年龄、身高、体重等一些属性,并且两人都能够进行聊天、运动等相似的行为。
由于这两个人具有这些共性的地方,所以我们把它抽象出来,定义为一个类——人类,而小李、老王正是这个类中的个体(对象),而每一个个体才是真正具体的存在,光提到人类,你只知道应该有哪些属性行为,但你不知道他具体的一些属性值,比如你知道他属于 “人类” 所以他应该拥有姓名,年龄等属性,但你并不知道他具体叫什么,年龄多大了。而小李和老王这两个具体的对象,却能够实实在在的知道老王今年30岁了、身高175等值。
所以可以得出结果:类是对象的抽象,而对象是类的具体实例。类是抽象的,不占用内存,而真正根据类实例化出具体的对象,就需要占用内存空间了。
1.3 成员变量和局部变量有什么区别?
A:在类中的位置不同

成员变量:类中方法外

局部变量:代码块,方法定义中或者方法声明上(方法参数)

B:在内存中的位置不同

成员变量:在堆中

局部变量:在栈中

C:生命周期不同

成员变量:随着对象的创建而存在,随着对象的消失而消失

局部变量:随着方法的调用而存在,随着方法的调用完毕而消失

D:初始化值不同

成员变量:有默认值(构造方法对它的值进行初始化)

局部变量:没有默认值,必须定义,赋值,然后才能使用

1.3.1 为什么局部变量存在于栈中而不是堆中
有一个问题,在我们学习 Java 中内存分配的时候,有这样一句话,“堆内存用来存放 new 创建的对象和数组”。 换句话说对象存在于堆中,而成员变量又存在于类中,而且对象是类具体的个体,所以成员变量也存在于堆中,那么问题就来了,同理,是不是方法也和成员变量一样存在于对象中,而局部变量又定义在方法中,岂不就是说,局部变量也存在于堆中呢?这明显与我们上面的定义有区别
解释:一个类可以创建 n 个不同的对象,当我们 new 一个对象后,这个对象实体,已经在堆上分配了内存空间,由于类的成员变量在不同的对象中各不相同(例如,小李和老王的姓名不同),都需要自己各自的存储空间,所以类的成员变量会随着对象存储在堆中,而由于类的方法是所有对象通用的,所以创建对象时,方法还未出现,只有声明,方法里面的局部变量也并没有被创建,只有等到对象使用方法的时候才会被压入栈。

补充:类变量(静态变量)存在于方法区,引用类型的局部变量声明在栈,存储在堆

1.4 访问权限修饰符 public、private、protected, 以及不写(默认)时的区别
在这里插入图片描述

访问权限类包子类其他包public√√√√protect√√√default√√private√

public:公共的,可以被项目中所有的类访问。
protected:受保护的,可以被这个类本身访问;被同一个包中的类访问;被它的子类(同一个包以及不同包中的子类)访问。
default:默认的,可以被这个类本身访问;被同一个包中的类访问。
private:私有的,只能被这个类本身访问。

1.5 类在初始化的时候做了些什么?

public class Student {
   
    private String name = "BWH_Steven";
    private Integer age = 22;
    
    // 是个无参构造,为了演示初始化顺序,特意加了两个赋值语句
    public Student (){
    
        name = "阿文";
        age = 30;
    }
}

public class Test {
   
    public static void main(String[] args) {
   
        Student stu = new Student(); 
    }
}
复制代码

例如: Student stu = new Student(); 其在内存中做了如下的事情:
首先加载 Student.class (编译成字节码文件)文件进内存,在栈内存为 stu 变量开辟一块空间,在堆内存为 Student 类实例化出的学生对象开辟空间,对学生对象的成员变量进行默认初始化(例如 name = null,age = 0 ),对学生对象的成员变量进行显示初始化( 例如name = “BWH_Steven”,age = 22),接着就会通过构造方法对学生对象的成员变量赋值(执行构造函数内,我们特意加的赋值语句 name = “阿文”,age = 30)学生对象初始化完毕,把对象地址赋值给 stu 变量
1.6 static 关键字修饰的作用?

static方法就是没有this的方法。在static方法内部不能调用非静态方法,反过来是可以的。而且可以在没有创建任何对象的前提下,仅仅通过类本身来调用static方法。这实际上正是static方法的主要用途。 —— 《Java编程思想》P86

可以知道,被 static 关键字修饰的方法或者变量不需要依赖于对象来进行访问,只要类被加载了,就可以通过类名去进行访问。也就是说,即使没有创建对象也可以进行调用(方法/变量)
static可以用来修饰类的成员方法、类的成员变量,另外可以编写static代码块来优化程序性能。
1.6.1 什么是静态方法
static 修饰的方法一般叫做静态方法,静态方法不依赖于对象访问,因此没有 this 的概念(this 代表所在类的对象引用),正因如此静态方法能够访问的成员变量和成员方法也都必须是静态的

例如在静态方法 A 中 调用了非静态成员 B,如果通过 类名.A 访问静态方法 A,此时对象还不存在,非静态成员 B 自然也根本不存在,所以就会有问题。调用非静态方法 C 也是如此,你不清楚这个方法 C 中是否调用了费静态变量

1.6.2 什么是静态变量
static 修饰的变量也称作静态变量,静态变量属于类,所以也称为类变量,存储于方法区中的静态区,随着类的加载而加载,消失而消失,可以通过类名调用,也可以通过对象调用。
1.6.3 什么是 静态代码块
静态代码块是在类中(方法中不行)使用static关键字和{} 声明的代码块

static {
   
	... 内容
}
复制代码

执行: 静态代码块在类被加载的时候就运行了,而且只运行一次,并且优先于各种代码块以及构造函数。
作用: 一般情况下,如果有些代码需要在项目启动的时候就执行,这时候 就需要静态代码块。比如一个项目启动需要加载的 很多配置文件等资源,我们就可以都放入静态代码块中。
1.6.3.1 构造代码块(补充)
概念:在java类中使用{}声明的代码块(和静态代码块的区别是少了static关键字)
执行: 构造代码块在创建对象时被调用,每次创建对象都会调用一次,但是优先于构造函数执行。
作用 :和构造函数的作用类似,都能对对象进行初始化,并且只创建一个对象,构造代码块都会执行一次。但是反过来,构造函数则不一定每个对象建立时都执行(多个构造函数情况下,建立对象时传入的参数不同则初始化使用对应的构造函数)。
因为每个构造方法执行前, 首先执行构造代码块,所以可以把多个构造方法中相同的代码可以放到这里,
2. 面向对象三大特征
2.1 封装
封装的概念
封装是指隐藏对象的属性和实现细节,仅对外提供公共访问方式

简单的来说就是我将不想给别人看的数据,以及别人无需知道的内部细节, “锁起来” ,我们只留下一些入口,使其与外部发生联系。

我们如何给我们的数据 “上锁” 呢?

我们使用,public、private、protected 等权限修饰符 在类的内部设定了边界,这些不同程度的 ”锁“ 决定了紧跟其后被定义的东西能够被谁使用。

封装的好处
隐藏实现细节,提供公共的访问方式,提高了代码的复用性,提高安全性
好处1:隐藏实现细节,提供公共的访问方式
隐藏实现细节怎么理解呢?

我们将一些功能封装到类中,而客户端的程序员,不需要知道类中的这个方法的逻辑原理,类程序员只需要给他一个对外的接口,客户端程序员只需要能够调用这个方法即可,

例如:夏天宿舍很热,我们(用户)只需要操作遥控器即可使用空调,并不需要了解空调内部是如何运行的

提供公共的访问方式又怎么理解呢?
我们先来看一段标准案例

public class Student {
   
	//定义成私有成员变量(private)
    private String name;
    private int age;
	
    //无参构造
    public Student() {
   
        super();
    }

    //带参构造
    public Student(String name, int age) {
   
        super();
        this.name = name;
        this.age = age;
    }
	
    //成员变量的set和get方法(与外界联系的桥梁)
    public void setName(String name) {
   
        this.name = name;
    }

    public String getName() {
   
        return name;
    }

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

    public int getAge() {
   
        return age;
    }
}
复制代码
public class StudentTest {
   
    public static void main
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值