book1 – javase


title: book1 – javase
toc: true
categories:
abbrlink: 703048b3
date: 2021-02-04 16:59:14
tags: Java
top: 1

这里是记录Java入门需要的一些基础知识 !

(一)了解Java

1. 计算机语言

1.1 机器语言

  • 0和1

1.2 汇编语言

  • 助记符

1.3 高级语言

  • C语言, 具有指针, 可以操作内存

  • Java

2. Java发展史

  • 前生是sun公司开发Oak
  • 诞生在1995年5月23日

3. Java的特点

3.1 Java语言的主要特点

  1. 简单

Java最初是为对家用电器进行集成控制而设计的一种语言,因此它必须简单明了。Java语言的简单性主要体现在以下三个方面:

1) Java的风格类似于C++,因而C++程序员是非常熟悉的。从某种意义上讲,Java语言是C及C++语言的一个变种,因此,C++程序员可以很快就掌握Java编程技术。

2) Java摒弃了C++中容易引发程序错误的地方,如指针和内存管理。

3) Java提供了丰富的类库。

  1. 面向对象

面向对象可以说是Java最重要的特性。Java语言的设计完全是面向对象的,它不支持类似C语言那样的面向过程的程序设计技术。Java支持静态和动态风格的代码继承及重用。单从面向对象的特性来看,Java类似于Small Talk,但其它特性、尤其是适用于分布式计算环境的特性远远超越了Small Talk。

  1. 分布式

Java包括一个支持HTTP和FTP等基于TCP/IP协议的子库。因此,Java应用程序可凭借URL打开并访问网络上的对象,其访问方式与访问本地文件系统几乎完全相同。为分布环境尤其是Internet提供的动态内容无疑是一项非常宏伟的任务,但Java的语法特性却使我们很容易地实现这项目标。

  1. 健壮

Java致力于检查程序在编译和运行时的错误。类型检查帮助检查出许多开发早期出现的错误。Java自已操纵内存减少了内存出错的可能性。Java还实现了真数组,避免了覆盖数据的可能。这些功能特征大大缩短了开发Java应用程序的周期。Java提供Null指针检测数组边界检测异常出口字节代码校验。

  1. 结构中立

另外,为了建立Java作为网络的一个整体,Java将它的程序编译成一种结构中立的中间文件格式。只要有Java运行系统的机器都能执行这种中间代码。现在,Java运行系统有Solaris2.4(SPARC),Win32系统(Windows95和WindowsNT)等.Java源程序被编译成一种高层次的与机器无关的byte-code格式语言,这种语言被设计在虚拟机上运行,由机器相关的运行调试器实现执行。

  1. 安全

Java的安全性可从两个方面得到保证。一方面,在Java语言里,象指针和释放内存等C++功能被删除,避免了非法内存操作。另一方面,当Java用来创建浏览器时,语言功能和浏览器本身提供的功能结合起来,使它更安全。Java语言在你的机器上执行前,要经过很多次的测试。它经过代码校验,检查代码段的格式,检测指针操作,对象操作是否过分以及试图改变一个对象的类型。

  1. 可移植的

这句话一直是Java程序设计师们的精神指标,也是Java之所以能够受到程序设计师们喜爱的原因之一,最大的功臣就是JVM的技术。大多数编译器产生的目标代码只能运行在一 种CPU上(如Intel的x86系列),即使那些能支持多种CPU的编译器也不能同时产生适合多 种CPU的目标代码。如果你需要在三种CPU( 如x86、SPARC 和MIPS)上运行同一程序, 就必须编译三次。

但JAVA编译器就不同了。JAVA编译器产生的目标代码(J-Code) 是针对一种并不 存在的CPU–JAVA虚拟机(JAVA Virtual Machine),而不是某一实际的CPU。JAVA虚拟机能掩盖不同CPU之间的差别,使J-Code能运行于任何具有JAVA虚拟机的机器上。

虚拟机的概念并不AVA 所 特 有 的:加州大学几年前就提出了PASCAL虚拟机的概念;广泛用于Unix服务器的Perl脚本也是产生与机器无关的中间代码用于执行。但针对Internet应用而设计的JAVA虚拟机的特别之处在于它能产生安全的不受病毒威胁的目标代码。正是由于Internet对安全特性的特别要求才使得JVM能够迅速被人们接受。 当今主 流的操作系统如OS/2、MacOS、Windows95/NT都已经或很快提供对J-Code的支持。

作为一种虚拟的CPU,JAVA 虚拟机对于源代码(Source Code) 来说是独立的。我们不仅可以用JAVA语言来生成J-Code,也可以用Ada95来生成。事实上,已经有了针对若干种源代码的J-Code 编译器,包括Basic、Lisp 和Forth。源代码一经转换成J-Code以后,JAVA虚拟机就能够执行而不区分它是由哪种源代码生成的。这样做的结果就是CPU可移植性。 将源程序编译为J-Code的好处在于可运行于各种机器上,而缺点是它不如本机代码运行的速度快。

同体系结构无关的特性使得Java应用程序可以在配备了Java解释器和运行环境的任何计算机系统上运行,这成为Java应用软件便于移植的良好基础。但仅仅如此还不够。如果基本数据类型设计依赖于具体实现,也将为程序的移植带来很大不便。例如在Windows3.1中整数(Integer)为16bits,在Windows95中整数为32bits,在DECAlpha中整数为64bits,在Intel486中为32bits。通过定义独立于平台的基本数据类型及其运算,Java数据得以在任何硬件平台上保持一致。Java语言的基本数据类型及其表示方式如下:byte8-bit二进制补码short16-bit二进制补码int32-bit二进制补码long64-bit二进制补码float32-bitIEEE754浮点数double32-bitIEEE754浮点数char16-bitUnicode字符在任何Java解释器中,数据类型都是依据以上标准具体实现的。因为几乎目前使用的所有CPU都能支持以上数据类型、8~64位整数格式的补码运算和单/双精度浮点运算。Java编译器本身就是用Java语言编写的。Java运算系统的编制依据POSIX方便移植的限制,用ANSIC语言写成。Java语言规范中也没有任何"同具体实现相关"的内容。

  1. 解释的

Java解释器(运行系统)能直接运行目标代码指令。链接程序通常比编译程序所需资源少,所以程序员可以在创建源程序上花上更多的时间。

  1. 高性能

如果解释器速度不慢,Java可以在运行时直接将目标代码翻译成机器指令。Sun用直接解释器一秒钟内可调用300,000个过程。翻译目标代码的速度与C/C++的性能没什么区别。

  1. 多线程

多线程功能使得在一个程序里可同时执行多个小任务。线程--有时也称小进程--是一个大进程里分出来的小的独立的进程。因为Java实现的多线程技术,所以比C和C++更键壮。多线程带来的更大的好处是更好的交互性能和实时控制性能。当然实时控制性能还取决于系统本身(UNIX,Windows,Macintosh等),在开发难易程度和性能上都比单线程要好。任何用过当前浏览器的人,都感觉为调一副图片而等待是一件很烦恼的事情。在Java里,你可用一个单线程来调一副图片,而你可以访问HTML里的其它信息而不必等它。

  1. 动态

Java的动态特性是其面向对象设计方法的发展。它允许程序动态地装入运行过程中所需要的类,这是C++语言进行面向对象程序设计所无法实现的。在C++程序设计过程中,每当在类中增加一个实例变量或一种成员函数后,引用该类的所有子类都必须重新编译,否则将导致程序崩溃。Java从如下几方面采取措来解决这个问题。Java编译器不是将对实例变量和成员函数的引用编译为数值引用,而是将符号引用信息在字节码中保存下传递给解释器,再由解释器在完成动态连接类后,将符号引用信息转换为数值偏移量。这样,一个在存储器生成的对象不在编译过程中决定,而是延迟到运行时由解释器确定的。这样,对类中的变量和方法进行更新时就不至于影响现存的代码。解释执行字节码时,这种符号信息的查找和转换过程仅在一个新的名字出现时才进行一次,随后代码便可以全速执行。在运行时确定引用的好处是可以使用已被更新的类,而不必担心会影响原有的代码。如果程序连接了网络中另一系统中的某一类,该类的所有者也可以自由地对该类进行更新,而不会使任何引用该类的程序崩溃。Java还简化了使用一个升级的或全新的协议的方法。如果你的系统运行Java程序时遇到了不知怎样处理的程序,没关系,Java能自动下载你所需要的功能程序。四.与C和C++语言的异同 Java提供了一个功能强大语言的所有功能,但几乎没有一点含混特征。C++安全性不好,但C和C++还是被大家所接受,所以Java设计成C++形式,让大家很容易学习。Java去掉了C++语言的许多功能,让Java的语言功能很精炼,并增加了一个很有用的功能,Java去掉了以下几个C和C++功能和特征:指针运算结构typedefs#define需要释放内存全局变量的定义这个功能都是很容易引起错误的地方。

  1. Unicode

Java使用Unicode作为它的标准字符,这项特性使得Java的程序能在不同语言的平台上都能撰写和执行。简单的说,你可以把程序中的变量、类别名称使用中文来表示<注>,当你的程序移植到其它语言平台时,还是可以正常的执行。Java也是目前所有计算机语言当中,唯一天生使用Unicode的语言。

4. Java程序的工作原理

4.1 Java虚拟机

4.1.1 为什么java能实现目标代码级的平台无关性?

  • 主要是利用java自带的jvm虚拟机,java的源代码编译好之后,形成.class文件,编译好的class文件是 字节码文件,可以在jvm中执行,只要有jvm都可以执行class文件,其实还是存在不同的。

4.2 Java程序工作原理

  • 类装载器 : 其主要功能是为执行程序寻找和装载所需要的类, 就是把字节码文件装到Java虚拟机中
  • 字节码校验器 : 其功能是对字节码文件进行校验, 保证代码的安全性. 字节码校验器负责测试代码段格式并进行规则检查, 检查伪造指针、违反对象访问权限或试图改变对象类型的非法代码
  • 解释器 : 具体的平台并不认识字节码文件, 最终起作用的还是这个最重要的解释器, 它将字节码文件翻译成所在平台能识别的东西

4.3 垃圾回收机制

4.2.1 简要描述Java的垃圾回收机制(Garbage Collection):

  • 对于GC来说,当程序员创建对象时,GC就开始监控这个对象的地址、大小以及使用情况。通常,GC采用有向图的方式记录和管理堆(heap)中的所有对象。通过这种方式确定哪些对象是”可达的”,哪些对象是”不可达的”。当GC确定一些对象为”不可达”时,GC就有责任回收这些内存空间。程序员可以手动执行System.gc(),通知GC运行,但是Java语言规范并不保证GC一定会执行。

4.4 .java转换成.class

在整个 Java 程序的开发流程中,程序员最初是将代码写在后缀为 .java 的文件中,之后再通过编译工具将 .java 文件转换 .class 文件(也称为字节码文件)。这个“转换”过程中,又可以细分为以下四个阶段:

4.4.1 词汇和语法分析:分析源码的执行逻辑,并将其绘制成一个抽象的语法树。

4.4.2 填写符号表:复杂的程序之间会彼此引用,而此阶段就会对这些引用关系做一些预处理工作。可以理解为,在此阶段会用一些符号来表示各个程序之间的关系。

4.4.3 注释处理:几乎所有的编程语言都包含程序和注释两部分,此阶段会对注释进行分析和归类。

4.4.4 生成字节码:根据前三个阶段的结果,最终将 .java 文件转换为 .class 文件。

字节码 .class 文件会被解释为机器码,进而在具体的系统平台上执行。以上过程如下所示。

4.5 JDK, JRE, JVM的关系

JDK(Java Development Kit,Java 开发工具包)是整个 Java 的核心。一个程序从源码到字节码需要编译,在 Java 中,这个编译动作由 JDK 提供的 javac 程序(或命令)来完成。JDK 还提供了执行程序 java、文档工具 javadoc 和反编译工具 javap 等使用工具。JDK 实际就是这些工具和 JRE 的合集。

什么是 JRE 呢?JRE(Java Runtime Environment,Java 运行环境)是 JVM(Java Virtual Machine,Java 虚拟机)和一些常用 API(Application Programming Interface,应用程序接口)的合集。

JVM 负责前文提到的解释并执行字节码。那什么是 API 呢?可以将 API 理解为是一些已经写好的、可以供我们直接使用的代码。举个例子,如果要编写一个排序算法该怎么办?除了自己一行一行的编写代码以外,还可以直接使用 JDK 中已经提供好的排序 API,直接使用 API 里的某一行代码就能帮助我们实现排序功能,是不是很方便呢?并且为了归类,API 通常是以“包”的形式体现的,例如 java.io 就是一个汇集了很多文件操作的包,而 java.lang 是一个汇集了很多程序基础操作的包。

综上,可以发现 JDK 包含了开发工具和 JRE,而 JRE 又包含了 JVM 和常用 API,如下图所示。因此,对于开发者而言,就只需要下载并安装 JDK,然后就可以开发并运行 Java 程序了。

4.6 即时编译

JVM 可判断某段字节码其是否属于使用频率较高的热点代码。如果是,就会将字节码文件转换出的本地机器码保存,以便下次直接执行机器码文件。这使得 Java 程序的执行效率得到很大的提高。

5. JavaSE的结构

Java 从诞生至今,主要衍生出了三个体系,即 Java SE,Java EE,Java ME。
Java SE(Java Standard Edition)

Java SE 是 Java 的基础,也是 Java 的核心。它允许开发和部署在桌面、服务器、嵌入式环境和实时环境中使用的 Java 应用程序。Java SE 为 Java EE 提供了基础。

Java EE(Java Enterprise Edition)

Java EE 是在 Java SE 基础之上发展起来的 Java 企业版,包含了 Web 开发等企业级的开发技术,多用于 Web 系统的服务端开发。使用 Java EE 可以快速开发出安全、稳定、性能较高的大型系统。因此 Java EE 也是很多企业在技术选型阶段的一个重要考虑方向。

Java ME(Java Micro Edition)

在 Java 发展之初,Java 还有另一个分支 — Java ME。Java ME 可以用于一些嵌入式设备的 Java 程序开发。但随着时代的发展,Java ME 逐步走向没落,目前的应用范围也在逐步缩小。

6. Java开发环境搭建

6.1 Java环境配置

  • 这里记录的是window64位系统的Java环境配置

(1)首先下载JDK, 下载地址 :

我这里用的是jdk-8u144-windows-x64(64位操作系统)版本, 我也附上了百度盘链接, 需要可以自取;

链接:https://pan.baidu.com/s/18ccmHAeRo31N6NHuvzYKXw
提取码:7723

下载完成后双击应用程序, 点击下一步

在这个地方更改按装路径

这里我把C盘改成D盘, 点击确定

点击下一步

然后会自动跳出一个窗口, 这是安装公共jre, 点击更改安装路径, 我这里也是把C盘改成D盘, 再点击确定,再下一步即可

这样, jdk就安装好了, 点击关闭

现在, 我们来配置三个JDK路径变量 :

变量名 说明 举例
JAVA_HOME Java的根目录 D:Program FilesJavajdk1.7.0_80
PATH Windows系统执行命令时要搜索的路径 在最前面加上%JAVA_HOME%bin;
CLASSPATH 编译和运行时要找的class路径 .%JAVA_HOME%lib (其中.代表当前路径)

注: %JAVA_HOME%表示的是对JAVA_HOME这个路径的相对引用,

打开文件管理器, 在此电脑上右键点击属性,

然后点击高级系统设置

再点击环境变量

再下面的系统目录下新建一个变量,

变量名设置为JAVA_HOME, 变量值填入之前安装JDK的安装目录, 我这里是 D:Program FilesJavajdk1.7.0_80

确定后再新建一个变量, 变量名为CLASSPATH, 变量值为,

.;%JAVA_HOME%libdt.jar;%JAVA_HOME%libtools.jar;

以.;点和分号开头是为了程序运行时,让它在当前路径去寻找额i外的一些资源,比如说,你自己写的一些类。";"是起着分割的作用,如果在前面的目中没有找到想要,那么会去到分号后面的目录中查找,就这样一级一级的找下去,直到classpath末尾,如果还没有找到,就报异常!

再找到Path路径, 这个路径已经有了, 不需要新建了, 我们只要在变量值最前面加

上%JAVA_HOME%bin;%JAVA_HOME%jrebin;

即可,然后点击确定

我们再打开cmd命令提示符(win+r, 然后输入cmd), 在cmd窗口输入java -version命令测试一些, 若是出现以下内容即说明安装成功

7. 第一个Java程序

  • C语言源码文件是后缀名是.c, 如HelloWorld.c, 它需要变为HelloWorld.exe, 然后才能在操作系统上运行 ;

  • 而Java源码文件, 后缀名是.java,它需要通过javac.exe来被编译成HelloWorld.class文件, 然后再在java虚拟机(JVM)上被java.exe解释运行, 然后这个操作系统通过运行JVM来运行这个Java文件

  • Java文件的基本单位是类, 一个Java文件可以包含无数个类, 但是只能包括一个public的类, 且文件名必须和这个public类的类名保持一致; 如果没有public类, 就不需要保持一致

7.2 Java枚举

class FreshJuice{
    enum FreshJuiceSize{SMALL, MEDIUM, LARGE}
    FreshJuiceSize size;
}

public class FreshJuiceTest {
    public static void main(String[] args) {
        FreshJuice juice = new FreshJuice();
        juice.size = FreshJuice.FreshJuiceSize.MEDIUM;
        System.out.println(juice.size);
    }
}

输出结果

MEDIUM

Java 5.0引入了枚举,枚举限制变量只能是预先设定好的值。使用枚举可以减少代码中的 bug。

例如,我们为果汁店设计一个程序,它将限制果汁为小杯、中杯、大杯。这就意味着它不允许顾客点除了这三种尺寸外的果汁。

注意:枚举可以单独声明或者声明在类里面。方法、变量、构造函数也可以在枚举中定义。

(二)数据类型和运算符

1. 标识符和关键字

Java中所有的关键字

图片.png

2. 变量和常量

3. Java数据类型

3.1 Java数据类型

Java数据类型

1基本数据类型

1.1数值型

1.1.1整数类型 (byte, short, int, long)

1.1.2浮点类型(float, double)

1.2字符型 (char)

1.3布尔型 (boolean)

2引用数据类型

2.1类( class)

2.2接口(interface)

2.3数组

图片.png

以 byte 为例说明取值范围的推理过程:

  • 最大值:高位为 0 表示正数,其余7个位为1,十进制为127
  • 最小值:高位为 1 表示负数,其余7个位为0,十进制为-128

3.2 Java中char类型的变量为什么可以赋值为整型数字?

1、JAVA中,char占2字节,16位。可在存放汉字

2、char赋值

char a=’a’; //任意单个字符,加单引号。

char a=’中’;//任意单个中文字,加单引号。

char a=111;//整数。0~65535。十进制、八进制、十六进制均可。输出字符编码表中对应的字符。

注:只能放单个字符。

3、char运算

char类型是可以运算的因为char在ASCII等字符编码表中有对应的数值。

在JAVA中,对char类型字符运行时,直接当做ASCII表对应的整数来对待。

示例1:

char m=’a’;   –>a

char m=’a’+’b’;   –>? //char类型相加,提升为int类型,输出对应的字符(a和b分别对应

​ 的数值为97和98,相加等于195,其对应的字符为 ?)。

int m=’a’+’b’;   –>195 //195没有超出int范围,直接输出195。

char m=197;   –>? //输出字符编码表中对应的字符。

char m=’197;   –>报错 //因为有单引号,表示是字符,只允许放单个字符。

char m=’a’+1;   –>b //提升为int,计算结果98对应的字符是b。

char m=’中’+’国’;  –>42282

char m=’中’+’国’+’国’+’国’;  –>报错 //int转char有损失。因为结果已经超出char类型的范围。

int m=’中’+’国’+’国’+’国’;  –>86820

char m=’中’+1;   –>丮 //1是int,结果提升为int,输出对应的字符。

char m=’中’+"国";  –>报错 //String无法转换为char。

System.out.println(‘中’+"国");  –>中国 //没有变量附值的过程。String与任何字符用“+”相连,转换为String。

示例2:

char a = 97; –>为char类型变量 a 赋值常量值 97。

char b = ‘a’+3; –>d // 97+3=100,ASCII对应的字符为 d。

char c = a+3; –>报错 //无法从int类型转换为char类型,接下来让我们了解下为什么会不

​ 能这样运算:

​ 首先,我们先知道在jvm内存机制中,char类型数据运算是将字符在ASCII表对应的整数以int类型参与运算(可以认为’ a ‘=97),常量(97)与常量(3)运算得到一个新的常量(100),常量赋值给变量(b),不存在强制转换,只要这个接受变量(b)的类型范围大于这个常量即可。而变量声明时需要定义数据类型(例:char a),内存就为这个变量划分一个char类型大小的空间,其中变量(a)的值是可变的,而常量(3)的值是不变的,两个运算得到的还是一个变量,本例中(a+3)是int类型的变量,而int类型变量(a+3)赋值给char类型变量(c)需要强制转换,因此会报错。

char c=(char)(a+3); –>d

总结:

用单引号’ ‘标识,只能放单个字符。

char+char,char+int——类型均提升为int,附值char变量后,输出字符编码表中对应的字符。

为什么char类型的变量可以赋值为整型数字?

char在java中是unicode编码

Java中对char型数据,在内存中存的就是整数,对应一张ASCII码表 ,比如说字符知 ‘A’ 对应的是65
字符 ‘a’ 对应的是97 ,道所以char c1 = ‘A’ ; 等效于 char c1 = 65 ;
正是因为这样,所以字符型数据既可以作为一个字符使用,也可以作为一个整数使用,所以char型数据可以和int型数据进行运算!
比如 ‘A’ + 1 的结果如果用char型变量接收就是 ‘B’ , 用int型变量接收就是66
char c = ‘A’+1; 最后c为’B’
int i = ‘A’ + 1 ; 最后i为 66
虽然char型是以整数存储,但是和int型还是有一定区别的,表现在取值范围上,
char型 占2个字节 无符号 范围是0~65535

所以char c = 65536 就会报错了,因为越界了

3.3 final, finally, finalize的区别

简单区别:

  • final用于声明属性,方法和类,分别表示属性不可交变,方法不可覆盖,类不可继承。

  • finally是异常处理语句结构的一部分,表示总是执行。

  • finalize是Object类的一个方法,在垃圾收集器执行的时候会调用被回收对象的此方法,供垃圾收集时的其他资源回收,例如关闭文件等。

3.4 Java为什么要保留基本数据类型?

  • 这篇博客内容讲得很有道理.

4. 成员变量和局部变量

5. Java运算符

5.1 短路

  • 短路运算符只能用于逻辑表达式内,非短路运算符可用于位表达式和逻辑表达式内。也可以说:短路运算只能操作布尔型的,而非短路运算不仅可以操作布尔型,而且可以操作数值型。

5.2 使用异或交换两个元素

异或原则,对于任意 x:

  1. x ^ x == 0;
  2. x ^ 0 == x;

思路:

根据原则,可以得到两个公式:

  求a: a^b^a=b

  求b: a^b^b=a

定义两个数:a b

a = a ^ b; // 保存 a ^ b 的结果

b = a ^ b; –> a ^ b ^ b 等于 原a  // 根据公式发现,这一步求的是a,只是用b接收了

a = a ^ b; –> a ^ a ^ b 等于 原b  // 这里的 b 实际上是a ^ b

示例:

public class SwapDemo {
    public static void main(String[] args) {
        int a = 3, b = 4;

        System.out.println("交换前a为:" + a + "交换前b为:" + b);

        a = a^b;
        b = a^b;
        a = a^b;

        System.out.println("交换后a为:" + a + "交换后b为:" + b);
    }
}

运行结果:

交换前a为:3交换前b为:4
交换后a为:4交换后b为:3

6. Java表达式

(三)流程控制

1. if语句

2. switch语句

2.1 switch语句对应的表达式可以是:

  • byte, short, int, char类型的, JDK7.0中又增加支持了String类型.

3. 循环语句

3.1 循环中break, continue, return, exit的区别

  • continue表示跳出本次循环, 进入下一次循环 ;

  • break表示跳出离它最近的循环体, 继续执行程序的下一部分 ;

  • return表示返回主调函数 ,如果在多层循环中, 可以跳出多层循环 ;

  • exit表示退出程序 ;

3.2 在switch语句中如果没有在case语句后面加上break

  • 会不经过表达式判断, 就执行下一行语句

(四)方法和数组

1. 方法

2. 数组

2.1 基本数据类型和引用数据类型在内存使用上的区别

  • 在内存中基本数据类型是把值存储在一块内存中的, 比如int age1 = 20; ,它把值20存在一块名为age1的内存块中;
  • 而引用数据类型则是使用两个内存块, 比如int[] ages = {20, 21}; 这个数组, 它是把值20, 21分别存在两个相邻的内存中(内存块1), 然后再另外在一块名为ages的内存(内存块2)中存放内存块1的首地址, 使得在需要使用这个内存块的时候, 可以通过这个首地址来找到内存块2;

2.2 值传参和引用传参的区别

  • 值传参其实就是当参数是基本类型时,传递参数的值,比如传递i=10,真实传参时,把10赋值给了形参;
  • 引用传参则是当参数是应用数据类型时,传递的是它的首地址。就是把地址值赋值给形参

(五)String字符串

1. String类

1.1 ==和equals()的区别

  • ==是直接比较的两个对象的堆内存地址,如果相等,则说明这两个引用实际是指向同一个对象地址的 ;
  • equals()如果是String类型的比较, 则是比较所指向的内存块的值是否相等, 其他引用数据类型则是比较对象是否为同一个对象 ;

2. StringBuffer类

2.1 String和StringBuffer的区别

  • String:是对象不是原始类型.为不可变对象,一旦被创建,就不能修改它的值;对于已经存在的String对象的修改都是重新创建一个新的对象,然后把新的值保存进去;String 是final类,即不能被继承。
  • StringBuffer:是一个可变对象,当对他进行修改的时候不会像String那样重新建立对象,它只能通过构造函数来建立。

(六)类和对象

1. 类和对象概述

1.1 三种内存空间

  • 用来存放变量, 方法形参
  • 用来存放new出来的对象
  • 常量池
  • 用来存放常量

1.2 面向过程和面向对象的区别, 面向对象的优势和劣势

  • 两者区别
  • 面向过程是朝着前进的目标一步一步往前走, 遇山开山, 涉水架桥;

  • 面向对象则是把这些问题具有的特征, 行为抽象出来, 形成有效的解决方案, 再根据所遇的对应类型的问题来应用这些方案 ;

  • 面向对象的优势

    1. 易维护
      采用面向对象思想设计的结构,可读性高,由于继承的存在,即使改变需求,那么维护也只是在局部模块,所以维护起来是非常方便和较低成本的。
    2. 质量高
      在设计时,可重用现有的,在以前的项目的领域中已被测试过的类使系统满足业务需求并具有较高的质量。
    3. 效率高
      在软件开发时,根据设计的需要对现实世界的事物进行抽象,产生类。使用这样的方法解决问题,接近于日常生活和自然的思考方式,势必提高软件开发的效率和质量。
    4. 易扩展
      由于继承、封装、多态的特性,自然设计出高内聚、低耦合的系统结构,使得系统更灵活、更容易扩展,而且成本较低。
  • 面向对象的劣势

    1. 没有准确的定义:很难提供一个准确的定义来说明面向对象DBMS应建成什么样,这是因为该名称已经应用到很多不同的产品和原型中,而这些产品和原型考虑的方面可能不一样。
    2. 维护困难:随着组织信息需求的改变,对象的定义也要求改变并且需移植现有数据库,以完成新对象的定义。当改变对象的定义和移植数据库时,它可能面临真正的挑战。
    3. 不适合所有的应用:面向对象数据模型用于需要管理数据对象之间存在的复杂关系的应用,它们特别适合于特定的应用,例如工程、电子商务、医疗等,但并不适合所有应用。当用于普通应用时,其性能会降低并要求很高的处理能力。

1.3 面向对象的特性是什么?什么是封装?

  • 面向对象的特性

    • 抽象
    • 封装
    • 继承
    • 多态
  • 封装

    • 封装,即隐藏对象的属性和实现细节,仅对外公开接口,控制在程序中属性的读和修改的访问级别;将抽象得到的数据和行为(或功能)相结合,形成一个有机的整体,也就是将数据与操作数据的源代码进行有机的结合,形成“类”,其中数据和函数都是类的成员。

1.4 构造方法有哪些特点

  • 特点

    (1)构造方法名一定与类同名。

    (2)构造方法无返回值类型(void也不行)

    (3)构造方法可以没有(默认一个无参构造方法),也可以有多个构造方法。他们之间构成重载关系。

    (4)如果定义有参构造函数,则无参构造函数将被自动屏蔽。

    (5)构造方法不能被继承。

    (6)构造方法不能手动调用,在创建类实例的时候自动调用构造方法。

2. Java类

3. 构造方法

4. 对象初始化过程

4.1 new对象初始化过程

  • 系统默认初始化 > 成员变量声明时的初始化 = 初始化块初始化 > 构造器

5. 重载

(七)包和访问控制

1. Java包

1.1 Java包机制的主要作用

  • 把功能相似或相关的类或接口组织在同一个包中,方便类的查找和使用。
  • 如同文件夹一样,包也采用了树形目录的存储方式。同一个包中的类名字是不同的,不同的包中的类的名字是可以相同的,当同时调用两个不同包中相同类名的类时,应该加上包名加以区别。因此,包可以避免名字冲突。
  • 包也限定了访问权限,拥有包访问权限的类才能访问某个包中的类。

2. 引用包

3. 访问权限

3.1 四种访问权限

  • public : 哪都可以访问权限
  • protected : 包内可访问 + 有父子继承关系的也可访问
  • 默认权限 : 包内权限
  • private : 类内权限

4. static关键字

4.1 为什么静态方法不能调用实例变量

  • 最容易理解的一种解释就是静态方法运行的时候, 还没有new出对象, 没有对象就没有办法调用实例变量
  • 用法:

    • 是一个修饰符;用于修饰成员(成员变量和成员函数)
      当成员被静态修饰后,就多了一种调用方式,除了可以被对象调用外,还可以直接被类名调用格式:类名.静态成员
  • 静态的特点:

    1.随着类的加载而加载
    也就是,说静态会随着类的消失而消失,说明静态的生命周期最长

    2.优先于对象的存在
    明确一点:静态是先存在的对象是后存在的

    3.被所有对象共享

    4.可以直接被类名多调用

  • 实例变量和类变量的区别

    1.存放位置
    类变量随着类的加载存在于方法区中,实例变量随着对象的对象的建立存在于堆内存里

    2.生命周期
    类变量生命周期最长,随着“类”的加载而加载,随着类的消失而消失
    实例变量随着“对象”的消失而消失

  • 静态的使用注意事项:

    1.静态方法只能访问静态成员(包括成员变量和成员方法)
    非静态方法可以访问静态也可以访问非静态

    2.静态方法中不可以定义this,super关键字
    因为静态优先于对象存在,所以静态方法中不可以出现this,super关键字

    3.主函数是静态的。

  • 静态的利弊

    • 利:对 对象的共享数据进行单独空间的存储,节省空间,没有必要每一个对象中都存储一份
      可以直接被类名所调用
    • 弊:生命周期过长,访问出现局限性(只能访问静态)
  • 静态块在类加载时被执行,普通块在类被实例化时被执行

4.2 静态方法可以调用静态方法, 不过首先要由静态main方法调用

示例:

public class Test11 {

    static void testStatic1() {
        System.out.println("testStatic1");
    }

    public static void main(String[] args) {
        System.out.println("main");
    }
}

运行结果:

main

从运行结果可以看出, 如果静态方法如果不在main方法中调用, 是不会执行的, 再将以上代码修改后

public class Test11 {

    static void testStatic1() {
        System.out.println("testStatic1");
    }

    public static void main(String[] args) {
        System.out.println("main");
        Test11.testStatic1();
    }
}

运行结果:

main
testStatic1

在main方法中调用后静态方法才执行

(八)继承和多态

1. 抽象和封装

1.1 类抽象的步骤

类抽象, 就是发现类并定义类的属性和方法, 比如要分析以下"租车系统" 的需求

  • (1)发现名词:

    通过阅读需求, 发现需求中有类型, 轿车, 卡车, 品牌, 红旗, 长城, 吨位, 车名, 油量, 车损度等名词

  • (2)确定类和属性

    通过分析,车名, 油量, 车损度, 品牌这些名词依附于轿车这个名词, 车名, 油量, 车损度, 吨位,依附于卡车这个名词, 所以可以根据业务将轿车, 卡车抽象成类, 依附于这些类的名词抽象成属性

  • (3)确定方法

    通过分析需求的动词, 发现显示车辆信息是轿车和卡车的行为, 所以可以根据业务将这个行为抽象成类的方法.

2. 继承

2.1 概念

  • 子承父业,子类持有父类的成员(属性、方法)。子类获取父类(属性&方法)的,新增自己的,覆盖(override)父类的。

2.2 功能

  • 代码的复用,实现多态

2.3 可继承成员

  • 父类中的非私有成员都能被继承,私有的成员只能通过从父类中继承来的公有方法间接的调用
    。成员覆盖:属性覆盖 & 方法覆盖(重写override) (就近原则调用自己的)

2.4 成员覆盖:

  • 属性覆盖 & 方法覆盖(重写override) (就近原则调用自己的)

  • 重写(方法覆盖):

    • 子类拥有与父类完全相同的方法,覆盖了父类中的方法。重写的方法返回值类型/异常类型可以缩小,访问权限可以被放大。

2.5 继承中的初始化:

  • (先人(父)后己(子))

  • 构造器中的第一条可执行语句是对其它构造器(父类构造器|当前类构造器)的调用,当没有显示调用其它构造器时,系统默认调用的是父类无参构造器(父类中必须有无参构造器)

2.6 最终类不能被继承

  • 最终量(常量)不能被二次赋值
  • 最终方法不能被覆盖(重写)
  • 最终类不能被继承

2.7 重载和重写的区别

主要是规则上的不同

  • 重载

    ①必须具有不同的参数列表。

    ②可以有不同的访问修饰符。

    ③可以抛出不同的异常。

  • 重写

    ①参数列表必须完全与被重写的方法相同,否则不能称其为重写而是重载。

    ②返回的类型必须一直与被重写的方法的返回类型相同,否则不能称其为重写而是重载。

    ③访问修饰符的限制一定要大于被重写方法的访问修饰符。

    ③访问修饰符的限制一定要大于被重写方法的访问修饰符。

2.8 深入解析Java重写 – 返回值、修饰符必须一致?

重写是子类对父类的允许访问的方法的实现过程进行重新编写, 返回值和形参都不能改变。即外壳不变,核心重写!

重写的好处在于子类可以根据需要,定义特定于自己的行为。 也就是说子类能够根据需要实现父类的方法。

重写方法不能抛出新的检查异常或者比被重写方法申明更加宽泛的异常。例如: 父类的一个方法申明了一个检查异常 IOException,但是在重写这个方法的时候不能抛出 Exception 异常,因为 Exception 是 IOException 的父类,只能抛出 IOException 的子类异常。

在面向对象原则里,重写意味着可以重写任何现有方法。

方法的重写规则

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

返回类型与被重写方法的返回类型可以不相同,但是必须是父类返回值的派生类(java5 及更早版本返回类型要一样,java7 及更高版本可以不同)。

访问权限不能比父类中被重写的方法的访问权限更低。例如:如果父类的一个方法被声明为 public,那么在子类中重写该方法就不能声明为 protected。

父类的成员方法只能被它的子类重写。

声明为 final 的方法不能被重写。

声明为 static 的方法不能被重写,但是能够被再次声明。

子类和父类在同一个包中,那么子类可以重写父类所有方法,除了声明为 private 和 final 的方法。

子类和父类不在同一个包中,那么子类只能够重写父类的声明为 public 和 protected 的非 final 方法。

重写的方法能够抛出任何非强制异常,无论被重写的方法是否抛出异常。但是,重写的方法不能抛出新的强制性异常,或者比被重写方法声明的更广泛的强制性异常,反之则可以。

构造方法不能被重写。

如果不能继承一个方法,则不能重写这个方法。

Super 关键字

当需要在子类中调用父类的被重写方法时,要使用 super 关键字。

  • 问:java疯狂讲义中说重写返回值类型要比父类小,在eclipse中验证,重写返回值类型必须一致,那么Java重写返回值类型必须一样吗?

答:java 5或者以前,必须一样,java 7 java 8可以不同,但是必须是父类返回值的派生类。

  • 问:Java重写要求子类跟父类的修饰符一样吗?

答:子类重写父类的方法的访问修饰符,不能低于父类的方法访问权限;
————————————————
版权声明:本文为CSDN博主「公众号-JavaEdge」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/qq_33589510/article/details/107022096

3. 多态

3.1 什么是多态, 用一个例子进行说明

  • 多态(Polymorphism)按字面的意思就是“多种状态”。在面向对象语言中,接口的多种不同的实现方式即为多态。引用Charlie Calverts对多态的描述——多态性是允许你将父对象设置成为一个或更多的他的子对象相等的技术,赋值之后,父对象就可以根据当前赋值给它的子对象的特性以不同的方式运作(摘自“Delphi4 编程技术内幕”)。

  • 多态分为 :

    • (1)向上转型 : 父类引用指向子类对象(或子类实例赋给父类引用), 然后这个父类引用就可以调用父类的属性( 属性在编译期静态地被绑定了 )和子类的方法( 方法在运行时才被动态地绑定 ), 且这个子类的方法必须是子类方法对父类方法的覆盖才能调用 ;

    • (2)向下转型 : 子类引用指向父类对象, 就是强制类型转换, 然后这个子类引用就可以调用子类的属性和方法, 但前提是这个父类对象一开始就指向这个子类对象

现在我们用一个例子来理解多态这个概念

首先, 我们来创建一个继承关系

父类 :

/**
 *@ 父类: 交通工具
 */
public class Vehicle {
    /** 父类属性 */
    public String brand = "品牌";

    /** 父类方法 */
    public void start() {
        System.out.println("启动车子");
    }

    public void stop() {
        System.out.println("停车");
    }
}

子类1(将父类具体化) :

/**
 *@ 派生类:自行车
 */
public class Bike extends Vehicle {
    /** 子类属性覆盖父类属性 */
    public String brand = "凤凰";

    /** 子类方法重写父类方法 */
    @Override
    public void start() {
        System.out.println("骑自行车");
    }

    /** 子类方法重写父类方法 */
    @Override
    public void stop() {
        System.out.println("停下");
    }

    /** 子类新增的方法 */
    public void showBikeMsg() {
        System.out.println("MsgBike");
    }
}

子类2(将父类具体化) :

/**
 * 派生类:小汽车
 */
public class Car extends Vehicle {
    /** 子类属性覆盖父类属性 */
    public String brand = "奥迪";

    /** 子类方法重写父类方法 */
    @Override
    public void start() {
        System.out.println("开车");
    }

    /** 子类方法重写父类方法 */
    @Override
    public void stop() {
        System.out.println("停车");
    }

    /** 子类新增的方法 */
    public void showCarMsg() {
        System.out.println("MsgCar");
    }
}

测试类

public class Test {
    public static void main(String[] args) {
        //子类创建对象
        Bike b = new Bike();
        System.out.println(b.brand);
        b.start();
        b.stop();

        System.out.println("-------------------");

        //向上转型: 子类实例赋给父类引用
        Vehicle v = new Bike();
        System.out.println(v.brand);
        v.start();
        v.stop();

        System.out.println("-------------------");

        //向下转型: 强制类型转换
        Bike bike = (Bike)v;
        System.out.println(bike.brand);
        bike.start();
        bike.stop();
        bike.showBikeMsg();
    }
}

让我们先来看一下运行结果

  • (1)在测试类中我们先创建了一个子类对象, 然后用它去调用属性和方法, 运行结果显示它调用的是自己重写覆盖的方法属性;
  • (2)然后我们将子类实例new Bike()赋给父类引用Vehicle v ,使得这个父类引用可以调用父类属性和子类已重写的方法, 这就是向上转型 ;
  • (3)最后, 我们再将v这个父类对象强制( 通过使用(Bike)v来完成 )赋给子类引用Bike bike ,使得这个子类引用可以调用子类自己的属性和方法, 这就是向下转型 , 但前提是这个父类对象v一开始就指向这个子类Bike, 如果对象v一开始指向的是子类Car, 那便不能将对象v强制类型转换为Bike类型 ;
  • 另外, 向上转型的v之所以只能调用父类属性和子类和子类方法, 原因是由Java程序编译运行机制决定的, 程序在运行之前, 需要先经过编译, 在这行语句中
        Vehicle v = new Bike();
  • 编译到Vehicle v 时, 它一看这个变量类型是Vehicle, 这时它就会去检索Vehicle有哪些属性, 而不会去检索有哪些方法, 因为方法的运行需要对象来调用, 在编译的时候是不会去检索方法的, 方法在运行的时候才会去检索, 这样属性在编译期就被静态地绑定了;

  • 然后再到new Bike这里, new代表开辟空间, 只有在程序运行的时候才会开辟空间, 所以new Bike这部分所有的行为是在程序运行时才会探测得出来, 才会给v赋值过来, 才会确定v有哪些方法, 这时候Bike的行为就会绑定给v(当然, 所绑定的方法, 必须是子类重写了父类的方法), 这样方法就在运行时被动态地绑定了;

(九)抽象类和接口

1. 抽象类

1.1 抽象类的特征

  • 特征

    (1)不能被直接实例化

    (2)抽象类的子类必须实现抽象方法, 除非子类也是抽象类

    (3)抽象类里可以有普通方法, 也可以有抽象方法, 但是有抽象方法的类必须是抽象类

1.2 没有抽象方法的抽象类

这种类存在的原因是让这个类不可以被继承

例如图书管理系统中的AdminPerson类和User类, 它们都是Person类的子类, 但是我们只是希望只存在AdminPerson类对象和User类对象, 而不需要有其他人类的对象, 比如说Teacher类, 那么我们就可以把Person类变成抽象类, 这样既满足要求, 又能使Person类的很多代码得到复用

2. 接口

2.1 接口的特征

  • 特征

    (1)接口中不允许有实体方法

    (2)接口中可以有成员变量, 默认修饰符是public static final, 接口中的抽象方法必须用public修饰

    (3)一个类可以实现多个接口

    (4)接口可以继承其他接口, 实现接口合并的功能

2.1 抽象类和接口的区别( 含使用范围 )

  • 区别

    • (1)抽象类用abstract class表示 ; 接口使用abstract interface表示, abstract一般省略

    • (2)抽象类本质上还是一个类, 可以定义常量、静态变量、成员变量,构造方法、静态方法、抽象方法以及普通方法 ; 接口可以定义静态常量(public static final double PI = 3.14f;其中public static final一般省略), 和抽象方法, JDK8及以后,允许在接口中定义static方法(静态方法,只能通过接口名调用,不可以通过实现类的类名或者实现类的对象调用。)和default方法(default方法,只能通过接口实现类的对象来调用。如果默认方法不能满足需要,实现类可以覆盖默认方法。)。

    • (3)接口内的所有东西默认是public的,且不能改变, public一般省略;抽象类可以设置权限。

    • (4)子类继承抽象类使用extend,且只能继承一个抽象类;可以实现多个接口,使用implement。接口只能继承或继承自接口;抽象类可以继承自普通类,也可继承自抽象类,同时可以实现多个接口。

2.2 使用一个类实现多个接口和实现一个扩展接口的差别

  • 使用一个类直接实现多个接口, 或通过接口间继承形成一个扩展接口再让类继承, 这两种方式都可以让类实现多个接口, 它们在使用上的差别是什么?
  • 差别

    • 如果多个不同的接口都写了默认方法, 那么一个类在实现多个接口时需要覆盖默认方法, 不然会冲突 ; 使用一个扩展接口去继承这些接口时, 也会覆盖这些默认类, 这时就不用实现类去覆盖了

2.3 接口会不会太多余了?

接口的作用就是把使用接口的人和实现接口的人分开,实现接口的人不必要关心谁去使用,而使用接口的人也不用关心谁实现的接口,由接口将他们联系在一起。

很多JAVA初级程序员对于接口存在的意义很疑惑。不知道接口到底是有什么作用,为什么要定义接口。

好像定义接口是提前做了个多余的工作。下面我给大家总结了4点关于JAVA中接口存在的意义:

  1、重要性:在Java语言中, abstract class 和interface 是支持抽象类定义的两种机制。正是由于这两种机制的存在,才赋予了Java强大的 面向对象能力。

  2、简单、规范性:如果一个项目比较庞大,那么就需要一个能理清所有业务的架构师来定义一些主要的接口,这些接口不仅告诉开发人员你需要实现那些业务,而且也将命名规范限制住了(防止一些开发人员随便命名导致别的程序员无法看明白)。

  3、维护、拓展性:比如你要做一个画板程序,其中里面有一个面板类,主要负责绘画功能,然后你就这样定义了这个类。

​ 可是在不久将来,你突然发现这个类满足不了你了,然后你又要重新设计这个类,更糟糕是你可能要放弃这个类,那么其他地方可能有引用他,这样修改起来很麻烦。

​ 如果你一开始定义一个接口,把绘制功能放在接口里,然后定义类时实现这个接口,然后你只要用这个接口去引用实现它的类就行了,以后要换的话只不过是引用另一个类而已,这样就达到维护、拓展的方便性。

  4、安全、严密性:接口是实现软件松耦合的重要手段,它描叙了系统对外的所有服务,而不涉及任何具体的实现细节。这样就比较安全、严密一些(一般软件服务商考虑的比较多)。

作者:Dion
链接:https://www.zhihu.com/question/20111251/answer/14012223
来源:知乎

能问这个问题,说明(1)你很会思考(2)编程水平还是处于起步阶段。

接口是个规范”,这句没错。
不如直接就在这个类中写实现方法岂不是更便捷”,你怎么保证这个接口就一个类去实现呢?如果多个类去实现同一个接口,程序怎么知道他们是有关联的呢?

既然不是一个类去实现,那就是有很多地方有用到,大家需要统一标准。甚至有的编程语言(Object-C)已经不把接口叫 interface,直接叫 protocol。

统一标准的目的,是大家都知道这个是做什么的,但是具体不用知道具体怎么做
比如说:
我知道 Comparable 这个接口是用来比较两个对象的,那么如何去比较呢?
数字有数字的比较方法,字符串有字符串的比较方法,学生(自己定义的类)也有自己的比较方法。

然后,在另外一个负责对象排序(不一定是数字喔)的代码里面,肯定需要将两个对象比较。
这两个对象是什么类型呢?
Object a,b?肯定不行,a > b 这样的语法无法通过编译。
int a,b?也不行?一开始就说了,不一定是数字。

….

所以,Comparable 就来了。他告诉编译器,a b 两个对象都满足 Comparable 接口,也就是他们是可以进行比较的。具体怎么比较,这段程序不需要知道。
所以,他需要一些具体的实现,Comparable 接口有一个方法,叫 compareTo。那么这个方法就是用来取代 <、> 这样的运算符。
因为运算符是编译器保留给内置类型(整数、浮点数)进行比较用的,而不是一个广义的比较运算。

如果你可以明白 JDK 自身库里面诸如 Comparable 这样已经有的接口,那么就很容易理解自己在开发程序的时候为什么需要用到接口了。

本文转载自:https://www.cnblogs.com/yibinmanong/p/6774647.html

作者:不违本心

原文出处及转载信息见文内详细说明,如有侵权,请私信删除。

2.4 抽象类和接口中有构造方法吗?

本文转载自: https://blog.csdn.net/YuanMxy/article/details/74389953
作者:YuanMxy
原文出处及转载信息见文内详细说明,如有侵权,请私信删除

(1)Java中抽象类和接口中有构造方法吗?
#####①在接口中 不可以有构造方法
在接口里写入构造方法时,编译器提示:Interfaces cannot have constructors。
A. 构造方法用于初始化成员变量,但是接口成员变量是常量,无需修改。接口是一种规范,被调用时,主要关注的是里边的方法,而方法是不需要初始化的,
B. 类可以实现多个接口,若多个接口都有自己的构造器,则不好决定构造器链的调用次序
C. 构造器是属于类自己的,不能继承。因为是纯虚的,接口不需要构造器。
#####②在抽象类中 可以有构造方法。
在抽象类中可以有构造方法,只是不能直接创建抽象类的实例对象,但实例化子类的时候,就会初始化父类,不管父类是不是抽象类都会调用父类的构造方法,初始化一个类,先初始化父类。
(2)补充:构造方法、抽象类、接口的定义:
#####①构造函数(构造器、构造函数):构造函数是一种特殊的函数。其主要功能是用来在创建对象时初始化对象, 即为对象成员变量赋初始值,总与new运算符一起使用在创建对象的语句中。
A.方法名与类名相同;
B.没有返回类型(例如return、void等);
C.不能被static、final、native、abstract和synchronized修饰,不能被子类继承。
D.父类的构造方法不能被子类调用,可以通过super语句调用父类的构造方法。
E.构造方法可以重载,以参数的个数,类型,顺序,分为空参构造方法和有参构造方法。
#####②抽象类:使用了关键词abstract声明的类叫作“抽象类”。如果一个类里包含了一个或多个抽象方法,类就必须指定成abstract(抽象)。“抽象方法”,属于一种不完整的方法,只含有一个声明,没有方法主体。
注:
抽象类中不一定有抽象方法,抽象方法一定存在于抽象类中。
继承抽象类的可以是普通类,但必须重写抽象类中的所有抽象方法,也可以是抽象类,无需重写抽象类中的所有抽象方法。
#####③接口:接口是一种规范,是一系列方法的声明,是一些方法特征的集合,一个接口只有方法的特征没有方法的实现,因此这些方法可以在不同的地方被不同的类实现,而这些实现可以具有不同的行为(功能)。
注:
可以说是一种特殊的抽象类,里面的方法全是抽象方法。
子类实现接口必须对接口中的方法全部重写。

#####接口和抽象类的语法区别:
1)接口不能有构造方法,抽象类可以有。
2)接口不能有方法体,抽象类可以有。
3)接口不能有静态方法,抽象类可以有。
4)在接口中凡是变量必须是public static final,而在抽象类中没有要求。

发表评论

电子邮件地址不会被公开。 必填项已用*标注