初识Java - 概念与准备

本笔记参考自: 《On Java 中文版》


目录

写在第一行

Java的迭代与发展

Java的迭代

Java的参考文档

对象的概念

抽象

接口

访问权限

复用实现

继承

基类和子类

A是B和A像B

多态

单根层次结构

集合

参数化类型

对象的创建和生命周期


写在第一行

         作为一门派生语言,Java的诞生离不开C++。也正因如此,Java继承了来自于C++“面向对象”(Small-Talk)的概念。而后来,这种面向对象的概念被证明是有些激进的。而正如每一门语言都有的一样,Java也存在着自身的局限,但知晓一门语言的不足也同样重要。

(例如Java中那些设计存在缺陷的库及语言。)

    很显然,将一切都封装成对象过于激进,但完全抛弃它也不免浪费。因此在Java一些面向初学者的书中,对于对象这一概念的态度是折中的(笔者:合理地利用)。本笔记参考的《On Java 中文版》既是如此。

Java的迭代与发展

Java的迭代

        发展至今,Java已经迭代了很久。除去早期版本的版本号,现在的Java一般每6个月发布一个新版本,并且使用整数作为其版本号。值得注意的是,Java在新发布的版本中往往会包含一些试用功能,但难以保证这些功能长期存在的,所有写代码时最好别依赖它。

        Java提供了两种不同的支持:短期支持(STS)与长期支持(LTS,常见的Java 8就是该版本)。但同样地,它们都会提供不同的功能试用。

    在每一版的Java中,都会包含不同的功能试用,可以分为三类:实验(Experimental)、预览(Preview)、孵化中(Incubating)。

Java的参考文档

        Java的开发工具集(即JDK)带有电子在线文档,该文档对于每个类的描述都很详细。在进行Java开发的时候可以参考该文档。

对象的概念

抽象

        如果说计算机是一种表达的媒介,编程语言是一种思维模式(就好比不同的语言最终影响了我们的衣食住行一样),那么面向对象编程,就是对使用计算机这一媒介的一次尝试

        要解释上面这句话,就要提到抽象任何编程语言都是一种抽象,有的是对于计算机结构的抽象,有的是对特定问题的抽象。这些不同的语言会在不同的问题上展现自己的优势,但同样的,它们往往都存在无能为力的地方。因此,面向对象编程应运而生。

        在面向对象编程中,对象可以是某种生物,某个建筑或者某种服务,而我们进行抽象的对象不再是计算机,而是实际的问题。通过这种方式,我们将程序转变为一段用来描述问题的文字。(注:对象与计算机之间的联系可以通过“状态”进行体现,因为每一个对象都有自己的行为和特征)

        Alan Kay曾经总结过SmallTalk(一种面向对象语言)的基本特征,其同样适用于其他面向对象的编程:

  1. 万物皆对象。
  2. 一段程序实际上就是多个对象通过发送消息来通知彼此要干什么。
  3. 从内存角度而言,每一个对象都是由其他更为基础的对象组成的。
  4. 每一个对象都有类型。
  5. 同一类型的对象可以接收相同的信息。

接口

        在拥有了对象这一概念后,我们将对象进行了分类,因此就诞生了类型。我们把状态不同而结构相同的对象分为“同一类对象”,而反过来,每一个对象所归属的类就决定了对象具有的行为特征。

    在很多面向对象的编程语言中,存在着class(即:类)这一关键字。可以说,这一关键字就代表着type(即:类型)。而事实上,由于类描述了对象的相同特征行为,这和数据类型很相似,所以也有这样的说法:类就是数据类型。

        但此时依旧存在着一个麻烦的问题,那就是对象能够接受什么请求。这就是由“接口”决定的,对象归属的类定义了这些接口。在面向对象的操作中,我们会向对象发出特定的请求,而如何处理请求是由对象来决定的。例如,下方图片展示了一个名为Light的类型:

Light A = new Light();    //A是一个引用,使用new关键字新建一个对象
A.on();                   //调用这一对象的接口

||| “实现”的概念: 用于响应请求的代码,以及与之相关的数据,它们的总和被称为“实现”。

    在开发面向对象的程序时,我们应该将对象想象为一个“服务的提供者”,对象应该能够,且只能够做好一件事(每个对象都只提供一种服务)。

访问权限

        一般,可以将程序员分为两类,分别是“类的创建者”和“客户程序员”,一方负责创建数据类型,而另一方则使用各种类。这意味着,“类的创建者”只为“客户程序员”提供必要的类的接口。这种做法当然是有意义的:

    一方面,这种做法可以提高安全性,因为这可以使得“客户程序员”无法解除那些本不允许他们接触的内容;而另一方面,当创建者想要修改类的内容时,由于修改的内容处于内部,因此不会影响使用该类的“客户程序员”。

        Java为了实现这种对访问权限的控制,设置了3个显式关键字,分别是publicprivateprotected,不同的修饰有不同的权限:

关键字访问权限
public可以被所有人访问
private只能被类的创建者通过该类自身的方法访问(其余人不可访问)
protected类似于private,但被protected修饰的类,其子类可以访问protected的成员
若不使用上述任意一种访问修饰符,Java也有默认的访问权限,即“包访问”,这一权限运行一个类访问其同一个包内的其他类,但不影响外部访问。

复用实现

        在理想的情况下,我们希望我们创建的对象能够有效,且应该是可以复用的。但现实情况是,这种可复用的对象设计更为少见。

        复用一个类有不同的方式,如果是利用已有的类组合成一个新的类,这种方式被称为“组合”(若组合是动态的,则被称为“聚合”)。组合代表的通常是一种“有”的关系,例如:“汽车有发动机”。

    组合是一种很灵活的复用方式,这是因为通过组合形成的新类,其内部的对象通常具有private属性,因此它即安全,又方便创建者修改这些内部对象。也因此,在创建新类时可以优先考虑组合。

继承

基类和子类

        在实际面对问题时,我们有时会发现:可能需要两个功能及其相似的类。如果因此大费周章,就太麻烦了。而继承(复制现有的类,在复制类上进行增补)就可以对此进行处理。通常,我们把被复制的类称为“基类(“超类”或“父类”),而把被修改的“复制”类称为“子类(“派生类”或“继承类”)

    继承的缺点是:若基类发生变化,则子类也会跟着变化。

        继承的这种思路使得我们可以有基类来阐述核心的思想,而众多的子类则是这一核心思想的不同实现方式。例如:如果现在需要绘制一个图形,把“形状”(Shape)作为基类,每个具体的形状都有具体的信息(大小、颜色)和行为(绘制、上色),那么圆形(Circle)、矩形(Square)、三角形(Triangle)等就是被派生出的子类。

        由继承产生的新类不仅会继承基类的所有成员(private成员除外),还会继承基类的接口。也就是说,基类对象能够接收的消息,子类也一样可以接收。从这一点上看,子类和基类拥有相同的类型。

        子类和基类会因为两种不同的方式产生区别:第一种方式是为子类添加新的方法。

        而另一种方式则是修改基类的已有方法,即“重写”。想要重写一个方法,只需在子类中对该方法进行重新定义即可。

A是B和A像B

        若子类和基类的接口一模一样,这也就意味着子类和基类的类型是完全相同的。在这种情况下,我们说基类和子类之间存在的关系是“A是B”,就比如“圆是一个形状”。此时,可以直接用子类的对象替代基类的对象

        但还有另一类“A像B”的情况,在这种情况下,子类除了拥有基类接口外,还有一些独立的接口。这时无法通过基类的接口获取子类的新方法。这时之前提到的那种替换通用性就会有所下降,显得并不这么合适。此时如果需要迎合子类,比较好的方法是从设计层面进行更改(增添功能)。

多态

        在涉及类型层次(即子类和基类结构)时,通常会将对象视为其基类的一个实例。通过派生子类的方式,可以轻松扩展程序设计。在这种方式中,我们并不需要关心具体执行的代码,因为对象能够根据类型执行对应正确的代码。

    这里存在着这样的一个问题:既然我们并不知道对象的具体类型,那么应该怎么为这一对象匹配正确的处理呢(毕竟它仅仅调用了接口)?

    答案来自于继承机制的一种重要技巧:编译器不是通过传统方式来调用方法。这种机制被称为“后期绑定”,这种机制要求程序直到运行时才确定代码的地址。而在Java中,方法都默认具有后期绑定特性,这使得我们不需要使用额外代码来实现多态。

    与“后期绑定”对应的就是“前期绑定”,对于非面向对象编译器而言,其生成的函数调用会触发“前期绑定”,此时编译器会生成一个具体方法名的调用,再通过该方法决定被执行代码的绝对地址。

        除此之外,这里还会涉及一个“向上转型”的概念,即将子类视为基类。如果我们为基类编写一个方法do(),那么这个方法也将适用于该基类的任意的一个子类,而do()发送给基类的信息也可以发送给子类。例如,还是以Shape为例:

单根层次结构

        在Java中,面向对象中的所有类都默认继承自一个终极基类Object。这种“单根层次结构”的使得所有对象都具有了共同的接口,这就提高了Java的兼容性。单根层次结构的另一个好处就是垃圾收集器,因为所有对象都有类型信息(Object),所以在对这些信息处理时,不需要费尽心思去考虑处理对象的类型。

集合

        有时,在面对一些问题时,我们会遇到对象个数不明,数量不明,存在时间不明的情况。在程序开始执行前,我们无法得知上述情报。很显然,这对开辟空间是一个巨大的阻力。

        在面向对象设计中,为了解决上述情况,通常都会用到集合(其实也可以使用数组)。集合是一种对象,这种对象通过保存其他对象的引用来解决问题,并且会根据放入的内容来调整空间。Java提供了一些集合,例如List类、Map类、Set类等,还有一些队列、栈和树。

    当然,无论集合的类型多么丰富,我们需要的都是能够解决问题的集合。比如List有两种基础的集合:ArrayListLinkedList。二者会因为结构的不同而在执行效率上有所区别。(不过由于两者都是基于List接口的子类,因此可以通过改动代码进行切换)

参数化类型

        在Java 5之前的版本中,集合只支持通用类型Object。这意味着,如果我们将对象添加到集合中,那么我们使用的对象将向上转型Object,从而失去自身的特征。这无疑加大了从集合中提取对象的难度。

     与“向上转型”相反,存在着“向下转型”的概念。当然,这种转型其实不太安全,因为一个基类可以有多个子类,若不声明确切的对象类型,那么在选择子类上就会可能出现安全问题。

        “参数化类型”的概念,为创建的集合明确其中包含的对象类型,成为了上述问题的解决方案。一个被参数化的类型是一个特殊的类,可以让编译器自动为其适配类型。例如:一个被定义为存放Shape类型的集合,也只能从中取出Shape类型。

        Java 5新增了一个特性用于支持参数化类型,或者说“泛型”。如果需要创建一个Shape对象的ArrayList,只需要在下方尖括号内加上类名,就可以定义泛型:

ArrayList<Shape> shapes = new ArrayList<>();

对象的创建和生命周期

        每个对象的创建都要消耗内存资源,当不需要使用该对象时,回收其占据的资源无疑是必要的行为。但随着问题复杂度的上升,当系统的某一部分不再需要一个对象时,该系统的其他部分可能还在使用该对象。这就使得一些使用显式删除对象的编程语言(例如C++)的程序员要耗费精力去解决这一问题。

        C++将对生命周期的处理交给了程序员,通过对栈区和堆区的选择比较效率和灵活性。而Java只运行动态分配内存,通过new操作符来创建一个对象的动态实例(不过也有特例,就是基本类型)。当然,Java也不需要手动释放内存,因为通过垃圾收集器机制,Java能够自动销毁无用对象。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/16826.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

从SQL注入绕过最新安全狗WAF中学习fuzz

前言 SQL注入并不是很精通&#xff0c;通过实战绕过WAF来进行加强SQL注入能力&#xff0c;希望对正在学习的师傅能有一丝帮助。 安装 安装前言 我是本地搭建的环境进行测试的 环境是windows11phpstudy2018sqli-labs phpstudy的安装我不再复述&#xff0c;这里简单说一下安全…

PDF文件忘记密码,怎么办?

PDF文件设置密码分为打开密码和限制密码&#xff0c;忘记了密码分别如何解密PDF密码&#xff1f; 如果是限制编辑密码忘记了&#xff0c;我们可以试着将PDF文件转换成其他格式来避开限制编辑&#xff0c;然后重新将文件转换回PDF格式就可以了。 如果因为转换之后导致文件格式…

【100天精通python】Day20:文件及目录操作_os模块和os.psth模块, 文件路径拼接,目录操作

目录 专栏导读 1 文件的目录操作 os模块的一些操作目录函数​编辑 os.path 模块的操作目录函数 2 相对路径和绝对路径 3 路径拼接 4 判断目录是否存在 5 创建目录、删除目录、遍历目录 专栏导读 专栏订阅地址&#xff1a;https://blog.csdn.net/qq_35831906/category_12…

Day03-作业(AxiosElementUI)

作业1&#xff1a; 根据需求完成如下页面数据列表展示 需求&#xff1a;Vue挂载完成后,通过axios发送异步请求到服务端,获取学生列表数据,并通过Vue展示在页面上 获取数据url&#xff1a;http://yapi.smart-xwork.cn/mock/169327/student 素材&#xff1a; <!DOCTYPE html…

springboot2实现图片文件上传与mysql存储路径并回显

环境介绍 技术栈 springbootmybatismysql 软件 版本 mysql 8 IDEA IntelliJ IDEA 2022.2.1 JDK 1.8 Spring Boot 2.7.13 mybatis 2.3.1 springboot是基于spring 4.0&#xff0c;springboot2是基于spring5.0,springboot2由pivotal公司在2018发布,这个框架主要用来…

螺旋矩阵 II——力扣59

文章目录 题目描述法一 模拟 题目描述 法一 模拟 初始化一个二维向量&#xff0c;名为matrix&#xff0c;它有n行和n列。向量的每个元素都是一个整数&#xff0c;初始化为0。初始化二维向量的语法如下&#xff1a;vector<vector<int>> matrix(n, vector<int>…

WPS本地镜像化在线文档操作以及样例

一个客户项目有引进在线文档操作需求&#xff0c;让我这边做一个demo调研下&#xff0c;给我的对接文档里有相关方法的说明&#xff0c;照着对接即可。但在真正对接过程中还是踩过不少坑&#xff0c;这儿对之前的对接工作做个记录。 按照习惯先来一个效果&#xff1a; Demo下载…

【phaser微信抖音小游戏开发002】hello world!

执行效果&#xff1a; 将以下代码文本内容&#xff0c;放入到game.js中即可。目录结构如下图 import ./js/libs/weapp-adapter import ./js/libs/symbolGameGlobal.window.scrollTo () > { };//防止真机出错 import Phaser from ./js/phaser//引入Phaservar {windowWidth, …

vue项目环境 搭建

1、安装nodejs 2、安装vue-cli, npm i -g vue/cli-init 3、初始化项目 vue init webpack test 4、运行 cd test npm run dev

无人机影像配准并发布(共线方程)

无人机影像 DEM 计算四个角点坐标&#xff08;刚性变换&#xff09; 像空间坐标&#xff08;x,y,-f&#xff09; 像空间坐标畸变纠正 deltax,deltay 已知(x,y)&#xff0c;求解(X,Y, Z)或者(Lat,Lon) 这里的Z是DEM上获取的坐标和Zs为相机坐标的高程&#xff0c;如果均为已…

应用无线鼠标中的2.4GHz无线收发芯片

无线键盘和无线鼠标作为现代办公环境中常见的工具&#xff0c;为我们的工作带来了便利。无线键盘和无线鼠标的工作原理都是基于无线技术实现的&#xff0c;其中常见的是2.4GHz无线技术。让我们一起来详细了解一下它们的工作原理。 无线鼠标的原理非常简单,鼠标部分工作与传统鼠…

html富文本编辑器

接了个单子&#xff0c;需要添加一个文章模块&#xff0c;一看用到的技术这么老&#xff0c;人傻了&#xff0c;纯html css js 。 在普通页面中 <!DOCTYPE html> <html lang"en"><head><meta charset"UTF-8"><meta name"…

为Win12做准备?微软Win11 23H2将集成AI助手:GPT4免费用

微软日前确认今年4季度推出Win11 23H2&#xff0c;这是Win11第二个年度更新。 Win11 23H2具体有哪些功能升级&#xff0c;现在还不好说&#xff0c;但它会集成微软的Copilot&#xff0c;它很容易让人想到多年前的“曲别针”助手&#xff0c;但这次是AI技术加持的&#xff0c;Co…

一些高频的C++ cache line面试

C那些事之False Sharing与Cache line 最近看到一段代码&#xff0c;手动做的对齐&#xff0c;于是研究一下不对齐又会带来什么影响&#xff1f; template <typename T> class AtomicWithPadding {private:static constexpr int kCacheLineSize 64;uint8_t padding_befor…

牛客网Verilog刷题——VL46

牛客网Verilog刷题——VL46 题目解析答案 题目 根据题目提供的双口RAM代码和接口描述&#xff0c;实现同步FIFO&#xff0c;要求FIFO位宽和深度参数化可配置。电路的接口如下图所示。   双口RAM端口说明&#xff1a; 同步FIFO端口说明&#xff1a; 双口RAM代码如下&#xff…

网络安全 Day24-select高级用法和多表连接

select高级用法和多表连接 1. select 多子句单表高级实践1.1 select 多子句高级语法1.2 聚合函数1.3 group by 实践1.4 having 筛选1.5 order by 排序1.6 limit 2. 多表连接 1. select 多子句单表高级实践 1.1 select 多子句高级语法 where 和 having 区别是后者是分组后进行…

邪恶版ChatGPT来了!

「邪恶版」ChatGPT 出现&#xff1a;每月 60 欧元&#xff0c;毫无道德限制&#xff0c;专为“网络罪犯”而生。 WormGPT 并不是一个人工智能聊天机器人&#xff0c;它的开发目的不是为了有趣地提供无脊椎动物的人工智能帮助&#xff0c;就像专注于猫科动物的CatGPT一样。相反&…

【C++入门到精通】C++入门 —— 类和对象(构造函数、析构函数)

目录 一、类的6个默认成员函数 二、构造函数 ⭕构造函数概念 ⭕构造函数的特点 ⭕常见构造函数的几种类型 三、析构函数 ⭕析构函数概念 ⭕析构函数的特点 ⭕常见析构函数的几种类型 四、温馨提示 前言 这一篇文章是上一篇的续集&#xff08;这里有上篇链接&#xff09;…

Flink非对齐checkpoint原理(Flink Unaligned Checkpoint)

Flink非对齐checkpoint原理&#xff08;Flink Unaligned Checkpoint&#xff09; 为什么提出Unaligned Checkpoint&#xff08;UC&#xff09;&#xff1f; 因为反压严重时会导致Checkpoint失败&#xff0c;可能导致如下问题 恢复时间长-服务效率低非幂等和非事务会导致数据…

5分钟快手入门laravel邮件通知

第一步&#xff1a; 生成一个邮件发送对象 php artisan make:mail TestMail 第二步&#xff1a; 编辑.env 添加/修改&#xff08;没有的key则添加&#xff09; MAIL_DRIVERsmtp MAIL_HOSTsmtp.163.com &#xff08;这里用163邮箱&#xff09; MAIL_PORT25 &#xff08;163邮箱…