java面向对象基础概念

面向对象编程(Object-Oriented Programming OOP)是一种编程思维方式和编码架构。

1. 抽象

OOP 允许我们根据问题来描述问题,而不是根据运行解决方案的计算机,所以将问题空间中的元素以及它们在解决方案空间的表示抽象为“对象”(Object)。一个对象具有自己的状态,行为和标识。这意味着对象有自己的内部数据(提供状态)、方法 (产生行为),并彼此区分(每个对象在内存中都有唯一的地址)。

对象的五大基本特征是:

  1. 万物皆对象。你可以将对象想象成一种特殊的变量。它存储数据,但可以在你对其“发出请求”时执行本身的操作。理论上讲,你总是可以从要解决的问题身上抽象出概念性的组件,然后在程序中将其表示为一个对象。
  2. 程序是一组对象,通过消息传递来告知彼此该做什么。要请求调用一个对象的方法,你需要向该对象发送消息。
  3. 每个对象都有自己的存储空间,可容纳其他对象。或者说,通过封装现有对象,可制作出新型对象。所以,尽管对象的概念非常简单,但在程序中却可达到任意高的复杂程度。
  4. 每个对象都有一种类型。根据语法,每个对象都是某个“类”的一个“实例”。其中,“类”(Class)是“类型”(Type)的同义词。一个类最重要的特征就是“能将什么消息发给它?”。
  5. 同一类所有对象都能接收相同的消息。这实际是别有含义的一种说法,大家不久便能理解。由于类型为“圆”(Circle)的一个对象也属于类型为“形状”(Shape)的一个对象,所以一个圆完全能接收发送给"形状”的消息。这意味着可让程序代码统一指挥“形状”,令其自动控制所有符合“形状”描述的对象,其中自然包括“圆”。这一特性称为对象的“可替换性”,是OOP最重要的概念之一。

2. 接口

我们向对象发出的请求是通过它的“接口”(Interface)定义的,对象的“类型”或“类”则规定了它的接口形式。“类型”与“接口”的对应关系是面向对象程序设计的基础。

3. 封装

对程序进行封装来达到访问控制的目的,主要原因有以下两点:

  1. 让应用程序员不要触摸他们不应该触摸的部分。
  2. 使类库的创建者(研发程序员)在不影响后者使用的情况下完善更新工具库。

Java 有三个显式关键字来设置类中的访问权限:public(公开),private(私有)和protected(受保护):

  1. public(公开)表示任何人都可以访问和使用该元素;
  2. private(私有)除了类本身和类内部的方法,外界无法直接访问该元素。private 是类和调用者之间的屏障。任何试图访问私有成员的行为都会报编译时错误;
  3. protected(受保护)类似于 private,区别是子类可以访问 protected 的成员,但不能访问 private 成员;
  4. default(默认)如果你不使用前面的三者,默认就是 default 访问权限。default 被称为包访问,因为该权限下的资源可以被同一包(库组件)中其他类的成员访问。

4. 复用

代码和设计方案的复用性是面向对象程序设计的优点之一。可以通过重复使用某个类的对象来达到这种复用性。也可以将一个类的对象作为另一个类的成员变量使用。新的类可以是由任意数量和任意类型的其他对象构成。

组合(Composition)经常用来表示“拥有”关系(has-a relationship)。例如,“汽车拥有引擎”。

聚合(Aggregation)动态的组合。

5. 继承

6. 多态

我们在处理类的层次结构时,通常把一个对象看成是它所属的基类,而不是把它当成具体类。通过这种方式,我们可以编写出不局限于特定类型的代码。

7.集合

Java中存在着很多不同的集合,主要有以下两个原因:

  1. 集合可以提供不同类型的接口和外部行为。堆栈、队列的应用场景和集合、列表不同,它们中的一种提供的解决方案可能比其他灵活得多。
  2. 不同的集合对某些操作有不同的效率。例如,List 的两种基本类型:ArrayList 和 LinkedList。虽然两者具有相同接口和外部行为,但是在某些操作中它们的效率差别很大。在 ArrayList 中随机查找元素是很高效的,而 LinkedList 随机查找效率低下。反之,在 LinkedList 中插入元素的效率要比在 ArrayList 中高。由于底层数据结构的不同,每种集合类型在执行相同的操作时会表现出效率上的差异。

Java 5 泛型出来之前,集合中保存的是通用类型 Object。当我们往集合中添加元素时,元素便向上转型成了 Object,从而丢失自己原有的类型特性。这时我们再从集合中取出该元素时,元素的类型变成了 Object,要使用强制类型转换将其转为更具体的类型,这个过程称为对象的“向下转型”。通过“向上转型”,我们知道“圆形”也是一种“形状”,这个过程是安全的。可是我们不能从“Object”看出其就是“圆形”或“形状”,所以除非我们能确定元素的具体类型信息,否则“向下转型”就是不安全的。也不能说这样的错误就是完全危险的,因为一旦我们转化了错误的类型,程序就会运行出错,抛出“运行时异常”(RuntimeException)。减少集合元素“向下转型”的开销和可能出现的错误难道不好吗?这种解决方案就是:参数化类型机制(Parameterized Type Mechanism)。

8.对象的创建与生命周期

为了获得最大的运行时速度,程序员可以在编写程序时,通过将对象放在栈(Stack,有时称为自动变量或作用域变量)或静态存储区域(static storage area)中来确定内存占用和生存时间。这些区域的对象会被优先分配内存和释放。这 种控制在某些情况下非常有用。

第二种方法是在堆内存(Heap)中动态地创建对象。在这种方式下,直到程序运行我们才能确定需要创建的对象数量、生存时间和类型。什么时候需要,什么时候在堆内存中创建。 因为内存的占用是动态管理的,所以在运行时,在堆内存上开辟空间所需的时间可能比在栈内存上要长(但也不一定)。在栈内存开辟和释放空间通常是一条将栈指针向下移动和一条将栈指针向上移动的汇编指令。开辟堆内存空间的时间取决于内存机制的设计。

Java 使用动态内存分配。每次创建对象时,使用 new 关键字构建该对象的动态实例。这又带来另一个问题:对象的生命周期。较之堆内存,在栈内存中创建对象,编译器能够确定该对象的生命周期并自动销毁它;然而如果你在堆内存创建对象的话,编译器是不知道它的生命周期的。C++ 中你必须以编程方式确定何时销毁对象,否则可能导致内存泄漏。Java 的内存管理是建立在垃圾收集器上的,它能自动发现对象不再被使用并释放内存。垃圾收集器的存在带来了极大的便利,它减少了我们之前必须要跟踪的问题和编写相关代码的数量。因此,垃圾收集器提供了更高级别的保险,以防止潜在的内存泄漏问题,这个问题使得许多 C++ 项目没落。

9.异常处理

多数错误处理方案的主要问题是:它们依赖程序员之间的约定俗成而不是语言层面的限制。

异常处理机制将程序错误直接交给编程语言甚至是操作系统。“异常”(Exception)是一个从出错点“抛出”(thrown)后能被特定类型的异常处理程序捕获(catch)的一个对象。异常的发生是不会被忽略的,它终究会在某一时刻被处理。

10. 基本类型的存储

基本数据类型的创建并不是通过new关键字来产生的。通过new关键字产生的对象都是保存在堆内存中的,以此方式创建小而简单的基本类型变量往往是不划算的,而是使用一个“自动”变量。 这个变量直接存储"值",并置于栈内存中,因此更加高效。

Java通过规定每种基本类型的内存占用大小,这些大小不会像其他一些语言那样随着机器环境的变化而变化,这也是Java更具有可移植性。如果你希望在堆内存里表示基本类型的数据,就需要用到它们的包装类。基本类型自动转换成包装类型(自动装箱),包装类型转化为基本类型(自动拆箱)。

基本数据类型可以自动从较小的类型转换为较大的类型。如果从较大的类型强制转换为较小的类型,可能会出现精度丢失的情况。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-US3VUoFD-1619581812667)(https://raw.githubusercontent.com/zhaozhen197/my_markdown_img/master/image-20210427130834941.png)]

基本类型的默认值:

如果类的成员变量(字段)是基本类型,那么在类初始化时,这些类型将会被赋予一个初始值。但是方法中的局部变量需要在变量定义时进行手动赋值。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-5APNrot5-1619581812669)(https://raw.githubusercontent.com/zhaozhen197/my_markdown_img/master/image-20210427132628828.png)]

11. static关键字

类是对象的外观及行为方式的描述。通常只有在使用 new 创建那个类的对象后,数据存储空间才被分配,对象的方法才能供外界调用。这种方式在两种情况下是不足的。

  1. 有时你只想为特定字段(注:也称为属性、域)分配一个共享存储空间,而不去考虑究竟要创建多少对象,甚至根本就不创建对象。
  2. 创建一个与此类的任何对象无关的方法。也就是说,即使没有创建对象,也能调用该方法。

相比非静态的对象,static 属性改变了数据创建的方式。同样,当 static 关键字修饰方法时,它允许我们无需创建对象就可以直接通过类的引用来调用该方法。

无论创建多少个对象,静态数据都只占用一份存储区域。static 关键字不能应用于局部变量,所以只能作用于属性(字段、域)。如果一个字段是静态的基本类型,你没有初始化它,那么它就会获得基本类型的标准初值。如果它是对象引用,那么它的默认初值就是 null

每个 java 源文件中允许有多个类。同时,源文件的名称必须要和其中一个类名相同,否则编译器将会报错。每个独立的程序应该包含一个 main() 方法作为程序运行的入口。

12.方法重载

如何区分重载方法:每个被重载的方法必须有独一无二的参数列表。

一旦程序员显式的定义了构造器(无论是有参还是无参)编译器都不会自动为你创建无参构造器了。

this 关键字只能在非静态方法内部使用,static 方法中不会存在 this。当你调用一个对象的方法时,this 生成了一个对象引用。

在一个类中写了多个构造器,有时想在一个构造器中调用另一个构造器来避免代码重复。可通过 this 关键字实现这样的调用。但是只能通过 this 调用一次构造器,而且必须首先调用构造器,否则编译器会报错。

13. 垃圾回收器

java 中有垃圾回收器回收无用对象占用的内存。但现在考虑一种特殊情况:你创建的对象不是通过 new 来分配内存的,而垃圾回收器只知道如何释放用 new 创建的对象的内存,所以它不知道如何回收不是 new 分配的内存。为了处理这种情况,Java 允许在类中定义一个名为 finalize() 的方法。

它的工作原理"假定"是这样的:当垃圾回收器准备回收对象的内存时,首先会调用其 finalize() 方法,并在下一轮的垃圾回收动作发生时,才会真正回收对象占用的内存。finalize() 是一个潜在的编程陷阱,因为一些程序员(尤其是 C++ 程序员)会一开始把它误认为是 C++ 中的析构函数(C++ 在销毁对象时会调用这个函数)。在 Java 中,对象并非总是被垃圾回收,或者换句话说:

  1. 对象可能不被垃圾回收。
  2. 垃圾回收不等同于析构。
  3. 垃圾回收只与内存有关。

之所以有 finalize() 方法,是因为在分配内存时可能采用了类似 C 语言中的做法,而非 Java 中的通常做法。这种情况主要发生在使用"本地方法"的情况下,本地方法是一种用 Java 语言调用非 Java 语言代码的形式。在非 Java 代码中,也许会调用 C 的 malloc() 函数系列来分配存储空间,而且除非调用 free() 函数,不然存储空间永远得不到释放,造成内存泄露。但是,free() 是 C 和 C++ 中的函数,所以你需要在 finalize() 方法里用本地方法调用它。

在类中变量定义的顺序决定了类成员的初始化顺序。即使变量定义散布在方法定义之间,它们仍会在任何方法(包括构造器)被调用之前得到初始化。

14. 数组

Integer[] a = { 1, 2, 3, }; //只能用于数组定义处。

Integer[] b = new Integer[] {1, 2, 3, };//可以用在任何地方,甚至用在方法的内部

a = new int[rand.nextInt(20)]; //不确定数组中需要多少个元素时,定义数组

可变参数:

static void f(float i, Character… args) { System.out.println(“first”); }

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
面向对象是一种编程思想,通过这种思想可以将复杂的事物简化。它基于面向过程,强调结果而不是过程。面向对象的编程是将具有相似行为或属性的事物抽象或集合而成的。对象是的具体实例,是的模板。在Java语言,可以通过来描述现实世界的事物,将事物的属性作为成员变量,将行为作为成员方法。和对象的创建与使用可以通过class关键字创建,通过new关键字创建对象。与对象在内存的存储通过引用来实现。 Java面向对象基础知识还包括封装、构造方法、构造代码块、局部代码块、this关键字、继承、static关键字、多态、抽象、接口等。封装是面向对象的三大特征之一,可以用来保护的成员变量。构造方法用于创建对象的同时初始化对象的成员变量。构造代码块在创建对象时执行,并且在构造方法之前执行。局部代码块是在方法内部定义的代码块。this关键字指代当前对象。继承是面向对象重要特性,可以通过父和子之间的关系实现代码的复用。static关键字用于修饰成员变量和成员方法,可以实现数据的共享。多态是指一个对象可以有多种形态,能够根据上下文自动选择使用哪种形态。抽象和接口是抽象型的具体表现,可以提高程序的复用率和可维护性。 在Java,由于不允许多重继承,如果要实现多个的功能,则可以通过实现多个接口来实现。面向接口和面向抽象的编程是提高程序复用率和可维护性的重要手段。正确地使用接口和抽象面向对象编程的关键。 总结一下,Java面向对象基础知识包括与对象、封装、构造方法、构造代码块、局部代码块、this关键字、继承、static关键字、多态、抽象、接口等概念和特性。掌握这些知识可以帮助我们更好地进行面向对象的编程。<span class="em">1</span><span class="em">2</span><span class="em">3</span><span class="em">4</span>

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值