知识屋:更实用的电脑技术知识网站
所在位置:首页 > 科技

Java基础知识(上)

发表时间:2022-03-24来源:网络

第一章 初识Java

一、Java诞生的原因

1.平台与机器指令

无论哪种编程语言编写的应用程序都需要经过操作系统处理器来完成程序的运行,因此这里所指的平台是由操作系统(OS)和处理器(CPU)所构成。与平台无关是指软件的运行不因操作系统、处理器的变化导致发生无法运行或出现运行错误。

所谓平台的机器指令就是可以被该平台直接识别、执行的一种由0,1组成的序列代码。需要注意的是,相同的CPU和不同的操作系统所形成的平台的机器指令可能是不同的,因此,每种平台都会形成自己独特的机器指令,例如,某个平台可能用8位序列代码10001111表示一次加法操作,以10100000表示一次减法操作,而另一种平台可能用8位序列代码10101010表示一次加法操作,以10010011表示一次减法操作。

2.C/C++程序依赖平台

现在,让我们分析一下为何C/C++语言编写的程序可能因为操作系统的变化、处理器升级导致程序出现错误或无法运行。

C/C++语言提供的编译器对C/C++源程序进行编译时,将针对当前C/C++源程序所在的特定平台进行编译、链接,然后生成机器指令,即根据当前平台的机器指令生成对应的机器码文件(可执行文件)。这样一来,就无法保证C/C++编译器所产生的可执行文件在所有的平台上都能被正确地运行,这是因为不同平台可能具有不同的机器指令。因此,如果更换了平台,可能需要修改源程序,并针对新的平台重新编译源程序。

3.Java程序不依赖平台

Java语言和其他语言相比,最大的优势就是它的平台无关性,这是因为Java可以在平台之上再提供一个Java运行环境(Java Runtime Environment ,JRE),该Java运行环境由Java虚拟机(Java Virtual Machine,JVM)、类库以及一些核心文件组成。Java虚拟机的核心是所谓的字节码指令,即可以被Java虚拟机直接识别、执行的一种由0,1组成的序列代码。字节码并不是机器指令,因为它不和特定的平台相关,不能被任何平台直接识别,执行。Java针对不同平台提供的Java虚拟机的字节码指令都是相同的,如所有的虚拟机都将1111 0000识别、执行为加法操作。

和C/C++不同的是,Java语言提供的编译器不针对特定的操作系统和CPU芯片进行编译,而是针对Java虚拟机把Java源程序编译为称作字节码的一种“中间代码”,例如,Java源文件中的“+”被编译成字节码指令:1111 0000。字节码是可以被Java虚拟机识别、执行的代码,即Java虚拟机负责解释运行字节码,其运行原理是:Java虚拟机负责将字节码翻译成虚拟机所在平台的机器码,并让当前平台运行该机器码。


小故事:印度尼西亚有一个重要的盛产咖啡的岛屿叫Java,中文译名叫爪哇,开发人员为这种新的语言起名为Java,其寓意是为世人端上一杯热咖啡。


二、Java程序的开发步骤

1.编写源文件

文件扩展名是.java

2.编译Java源程序

使用Java编译器(javac.exe)编译源文件,得到字节码文件。

3.运行Java程序

使用JavaSE平台中的java解释器(java.exe)来解释执行字节码文件。

使用Linux环境编译执行Java程序

第二章 初识对象和简单数据类型

一、简单的矩形类

面向对象的一个重要思想就是通过抽象得到类,即将某些数据以及针对这些数据上的操作封装在一个类中,也就是说,抽象的关键有两点:一是数据,二是数据上的操作。

我们对观察的矩形做如下抽象:

矩形具有宽和高之属性可以使用矩形的宽和高之属性

现在根据如上的抽象,编写出如下的React类、

React.java

public class React { double weight; double height; double getArea(){ double area = width*height; return area; } }

(1)类声明

(2)类体

二、使用矩形类创建对象

类是Java语言中最重要的一种数据类型。用类创建对象需经过两个步骤:

声明对象为对象分配成员变量

2.1 用类声明对象

由于类也是一种数据类型,因此可以使用类来声明一个变量,如下:

React rectangle1;

这时rectangle1是一个空对象,它在内存中还没有任何数据。如图声明对象时的内存模型:

2.3 使用对象

对象.变量

对象.方法

三、标识符与关键字

1.标识符

标识符就是一个名字。有以下限制:

由字母、下划线、美元符号和数字组成,长度不受限制。第一个字符不能是数字不能是关键字不能是true、false、null区分大小写

Java语言使用Unicode标准字符集。

2.关键字

被赋予特定意义的一些单词。

四、基本数据类型

4.1 8种基本数据类型

逻辑类型:boolean整数类型:byte、short、int、long字符类型:char浮点类型:float、double

对于int类型,内存分配4个字节。

byte类型,内存分配1个字节

short,内存分配2个字节

long,分配8个字节

char,分配2个字节

\n \b \t \' \" \\

三、简单数据类型的级别与数据转换

当把级别低的变量的值赋给级别高的变量时,系统会自动完成数据类型的转换。当把级别高的变量的值赋给级别低的变量时,必须使用显示类型转换运算。格式为:

(类型名)要转换的值。

四、从命令行窗口输入、输出数据

4.1 输入

Scanner reader = new Scanner(http://System.in);

然后reader对象调入下列方法,读取用户在命令行输入的各种基本类型数据:

nextBoolean()、nextByte()、Short Int Long Float Double。

上述方法执行时会堵塞,程序等待用户在命令行输入数据并确认。

4.2 输出

System.out.println()或System.out.print(),前者换行。

需要特别注意的是,在使用System.out.println()或System.out.print()输出字符串常量时,不可以出现回车换行,例如,下面的写法无法通过编译:

System.out.println(“您好,很高

兴认识你!”);

如果需要输出的字符串的长度较长,可以将字符串分解成几部分,然后使用并置符号:“+”将它们首尾相接,例如,以下是正确写法:

System.out.println(“您好,很高“ +

“兴认识你!”);

还有和C语言中printf函数类似的数据输出方法,该方法使用格式如下:

System.out.println(“格式控制部分”,表达式1,表达式2,表达式3,...,表达式n);

%d:输出int类型数据值。

%c:输出char型数据。

%f:输出浮点型数据,小数部分最多保留6位

%s:输出字符串数据

%md:输出的int型数据占m列

%m.nf:输出的浮点型数据占m列,小数保留n位

第三章 运算符、表达式和语句

一、算术运算与算术表达式

1.算术运算符

加、减、乘、除、求余运算符是二目运算符,即连接两个操作元的运算符。*,/, %运算符的优先级(3级)高于加、减运算符(4级)。

2. 算术表达式

用算术符号和括号连接起来的符合Java语法规则的式子。

二、自增,自减运算符

是单目运算符,可以放在操作元之前,也可以放在操作元之后。操作元必须是一个整型或浮点型变量。作用是使变量的值增1或减1。

++x表示在使用x之前,先使x的值增1。x++表示在使用x之后,使x的值增1

三、算术混合运算的精度

如果表达式中有双精度浮点数,则按双精度进行运算。如果最高是单精度,则按单精度。如果Long,则按Long。如果最高低于Int,则按Int。

四、关系运算符和关系表达式

关系运算符用来比较两个值的关系。

和C语言不同的是,Java中关系运算符的运算结果是boolean型,当运算符对应的关系成立时,运算结果是true,否则是false。

!=和==的优先级是7

,=的优先级是6

五、逻辑运算符和逻辑表达式

逻辑运算符包括&&,||,!。

其中&&,||是二目,!为单目。

逻辑运算符的操作元必须是boolean型数据,逻辑运算符可以用来连接关系表达式。

结果为boolean型的变量或表达式可以通过逻辑运算符形成逻辑表达式。

逻辑运算符“&&”和“||”也称做短路逻辑运算符,这是因为当op1的值是false时,“&&”运算符在进行运算时不再去计算op2的值,直接得出op1&&op2的结果是false;当op1的值是true时,“||”运算符在进行运算时不再去计算op2的值,直接就得出op1||op2的结果是true。

六、赋值运算符与赋值表达式

“=”是二目运算符,左面的操作元必须是变量,不能是常量或表达式。

注意,不要将“=”赋值运算符与“==”等号逻辑运算符混淆

七、位运算符

整型数据在内存中以二进制的形式表示,如一个int型变量在内存中占4个字节共32位,int型数据7的二进制表示是:

00000000 00000000 00000000 00000111

左面最高位是符号位,最高位是0表示正数,是1表示负数。负数采用补码表示,如-8的补码表示是:

11111111 11111111 11111111 11110000

这样就可以对两个整型数据实施位运算,即对两个整型数据对应的位进行运算得到一个新的整型数据。

7.1 “按位与”运算

“&”是双目运算符,运算法则是:如果a,b两个数据对应位都是1,则c的该位是1,否则是0。如果b的精度高于a,那么结果c的精度和b相同。

7.2 “按位或”运算

“|”是双目运算符,运算法则是:如果a,b两个数据对应位都是0,则c的该位是0,否则是1。如果b的精度高于a,那么结果c的精度和b相同。

7.3 “按位非”运算

“~”是单目运算符,运算法则是:如果a对应位是0,则c的该位是1,否则是0。

7.4 “按位异或”运算

“^”是二目运算符,运算法则是:如果a,b两个数据对应位相同,则c的该位是0,否则是1。如果b的精度高于a,那么结果c的精度和b相同。

八、instanceof运算符

二目运算符,左面的操作元是一个对象;右面是一个类。当左面的对象是右面的类的或子类创建的对象时,该运算符运算的结果是true,否则是false。

九、if条件分支语句

9.1 if语句

if语句是单条件分支语句,即根据一个条件来控制程序执行的流程。

关键字if后面的一对小括号()内的表达式的值必须是boolean类型,当值为true时,则执行紧跟着的符合语句,然后结束当前if语句的执行;如果表达式的值为false,结束当前if语句的执行。

9.2 if-else语句

单条件分支语句。

关键字if后面的一对小括号()内的表达式的值必须是boolean类型,当值为true时,则执行紧跟着的符合语句,然后结束当前if-else语句的执行;如果表达式的值为false,则执行关键字else后面的复合语句,结束当前if-else语句的执行。

9.3 if-else if-else语句

多条件分支语句,即根据多个条件来控制程序执行的流程。

语法格式:

if(){

}

else if(){

}

...

else{

}

关键字if以及多个else if后面的一对小括号()内的表达式的值必须是boolean类型。程序执行if else if else时,按该语句中表达式的顺序,首先计算第1个表达式的值,如果计算结果为true,则执行紧跟着复合语句,结束当前if-else if-else语句的执行,如果计算结果为false,则继续计算第2个表达式的值,依次类推。

十、switch开关语句

单条件多分支的开关语句

十一、循环语句

根据条件,要求程序反复执行某些操作,直到程序“满意”为止。

11.1 for循环语句

11.2 while循环

执行规则是:

(1)计算表达式的值,如果该值是true时,就进行(2),否则执行(3)。

(2)执行循环体,再进行(1)。

(3)结束while语句的执行。

11.3 do-while循环

和while循环的区别是:do-while额循环体至少被执行一次。

十二、break和continue语句

break和continue语句是用关键break或continue加上分号构成的语句,例如:

break;

在循环体中可以使用break语句和continue语句。在一个循环中,如循环50次的循环语句中,如果在某次循环中执行了break语句,那么整个循环语句就结束。如果在某次循环中执行了continue语句,那么本次循环就结束,即不再执行本次循环体中continue语句后面的语句,而转入进行下一次循环。

第四章 类与对象

抽象关键两个方面:属性和功能

一、类

类封装了一类对象的属性和方法。

1.1 类声明

1.2 类体

1.3 成员变量

1.4 方法

当一个方法不需要返回数据时,返回类型必须是void。

方法中的局部变量的名字如果与成员变量的名字相同,那么方法就隐藏了成员变量,如果想在该方法中使用被隐藏的成员变量,必须使用关键字this。

对成员变量的操作只能放在方法中,方法可以对成员变量和该方法体中声明的局部变量进行操作。

不能这样做:

class A { int a; a=12; //非法,这是赋值语句(语句不是变量的声明,只能出现在方法体中) }


1.5 类的UML图

属于结构图

描述一个系统的静态结构。

类的图

接口的图

泛化关系的图

关联关系的图

依赖关系的图

实现关系的图

图的结构:

顶部第1层是名字层。如果是常规字体,是具体类。如果是斜体,是抽象类。

第2层是变量层,也称属性层,列出类的成员变量及类型,格式是“变量名字”:“类型”。

第3层是方法层,也称操作层。格式是:“方法名字(参数列表)”:“类型”。

例如:

这时在文件夹test中将生成若干个html文档,查看这些文档可以知道源文件中类的组成结构,如类中的方法和成员变量。

使用javadoc时,也可以使用参数-d指定生成文档所在的目录。例如:

javadoc -d C:\document Hello.java

第五章 子类与继承

一、子类与父类

class 子类名 extends 父类名 {

}

子类继承父类的成员变量作为自己的一个成员变量,可以被子类中自己定义的任何实例方法操作。方法也一样。

5.1 子类和父类在同一包中的继承性

当子类和父类在同一个包中时,父类中的private访问权限的成员变量和方法不会被子类继承。其余的都继承。

5.2 子类和父类不在同一包中的继承性

当子类和父类不在同一个包中时,父类中的private和友好访问权限的成员变量和方法不会被子类继承。其余的都继承。

5.3 protected的进一步说明

如果用D类在D中创建了一个对象,那么该对象总是可以通过“.”运算符访问继承的或自己定义的protected变量和protected方法的,但是,如果在另外一个类中,如在Other类中用D类创建了一个对象object,该对象通过“.”运算符访问protected变量和protected方法的权限如下列(1)(2)所述。

(1)对于子类D中声明的protected成员变量和方法,如果object要访问这些protected成员变量和方法,只要Other类和D类在同一个包中就可以了。

(2)如果子类D的对象的protected成员变量或方法是从父类继承的,那么就要一直追溯到该protected成员变量或方法的“祖先”类,即A类,只要Other类和A类在同一个包中就可以了。

5.4 继承关系的UML图

三、子类对象的特点

当用子类的构造方法创建一个子类对象时,不仅子类中声明的成员变量被分配了内存,而且父类的成员变量也都分配了内存空间,但只将其中一部分(子类继承的那部分)作为分配给子类对象的变量。也就是说,父类中的private成员变量尽管分配了内存空间,也不作为子类对象的变量,即子类不继承父类的私有的成员变量

同样,如果子类和父类不在同一包中,尽管父类的友好变量分配了内存空间,但也不作为子类的成员变量,即如果子类和父类不在同一包中,子类不继承父类的友好变量

通过上面的讨论,我们有这样的感觉:子类创建对象时似乎浪费了一些内存,因为当用子类创建对象时,父类的成员变量也都分配了内存空间,但只将其中一部分作为分配给子类对象的变量,如父类的private成员变量尽管分配了内存空间,也不作为子类对象的变量,当然,它们也不是父类某个对象的变量,因为我们根本就没有使用父类创建任何对象。这部分内存似乎成了垃圾一样,但实际情况并非如此,我们需注意到,子类中还有一部分方法是从父类继承的,这部分方法却可以操作这部分未继承的变量

四、成员变量的隐藏和方法重写

4.1 成员变量的隐藏

在编写子类时,我们仍然可以声明成员变量,一种特殊的情况是,如果所声明的成员变量的名字和从父类继承来的成员变量的名字相同(声明类型可以不同),在这样情况下,子类就会隐藏掉所继承的成员变量,即子类对象以及子类自己声明定义的方法操作与父类同名的成员变量是指子类重新声明定义的这个成员变量

4.2 方法重写

子类通过重写可以隐藏已继承的实例方法。

(1)重写的语法规则

如果子类可继承父类的某个实例方法,那么子类就有权重写这个方法。

子类定义一个方法的类型和父类的类型一致,并且名字、参数个数、参数的类型和父类完全相同。

(2)重写的目的

子类通过方法的重写可以隐藏继承的方法,子类通过方法重写可以把父类的状态和行为改变为自身的状态和行为。一旦方法被重写,子类对象调用的方法一定是重写方法。重写方法既可以操作继承得多成员变量、方法,也可以操作子类新声明的成员变量、方法但无法操作被子类隐藏的成员变量和方法

(3)允许重写方法的类型可以是父类方法的类型的子类型。

(4)重写父类方法时,不可以降低方法的访问权限。

五、super关键字

5.1 用super操作被隐藏的成员变量和方法

子类一旦隐藏了继承的成员变量,那么子类创建的对象就不再拥有该变量该变量将归关键字super所有,同样子类一旦隐藏了继承的方法,那么子类创建的对象就不能调用被隐藏的方法,该方法的调用由关键字super负责。因此,如果在子类中想使用被子类隐藏的成员变量或方法就需要使用关键字super。如super.x、super.play()就是访问和调用被子类隐藏的成员变量x和方法play()。

例:

假设银行已经有了按整年year计算利息的一般方法,其中year只能取正整数。

建设银行准备隐藏继承的成员变量year和重写计算利息的方法,即自己声明一个double型的year变量,如当year取值是5.216时,表示要计算5年零216天的利息,但希望首先按银行的方法计算出整5年的利息,然后再自己计算216天的利息。那么,建设银行就必须把5.216的整数部分赋给隐藏的n,并让super调用隐藏的,按整年计算利息的方法。

5.2 使用super调用父类的构造方法

当用子类的构造方法创建一个子类的对象时,子类的构造方法总是先调用父类的某个构造方法,也就是说,如果子类的构造方法没有明显地指明使用父类的哪个构造方法,子类就调用父类的不带参数的构造方法,即如果在子类的构造方法中,没有明显地写出super关键字来调用父类的某个构造方法,那么默认的有:

super();

子类不继承父类的构造方法,因此,子类在其构造方法中需使用super来调用父类的构造方法,而且super必须是子类构造方法中的头一句。

我们已经知道,如果类里定义了一个或多个构造方法,那么Java不提供默认的构造方法(不带参数的构造方法),因此,当我们在父类中定义多个构造方法时,应当包括一个不带参数的构造方法,以防止子类省略super时出现错误。

六、final关键字

可以修饰类、成员变量和成员方法,方法中的局部变量。

6.1 final类

可以使用final将类声明为final类。final类不能被继承,即不能有子类。

6.2 final方法

final方法不允许子类重写。

6.3 常量

如果成员变量或局部变量被修饰为final,那么它就是常量。常量在声明时没有默认值,所在在声明常量时必须指定该常量的值,而且不能再发生变化。

七、对象的上转型对象。

假设,A类是B类的父类,当用子类创建一个对象,并把这个对象的引用放在父类的对象时,如:

A a; a=new B();

A a; B b = new B(); a=b;

这时,称对象a是对象b的上转型对象。

上转型对象的特点。

八、继承与多态

父类的某个实例方法被其子类重写时,可以各自产生自己的功能行为。

九、abstract类和abstract方法

abstract方法只允许声明,不允许实现,而且不允许使用final和abstract同时修饰一个方法。

(1)abstract类可以有abstract方法,也可以有非抽象方法。

(2)abstract类不能用new运算创建对象。

注意:

(1)abstarct类也可以没有abstract方法。

(2)如果一个abstract类是abstract类的子类,它可以重写父类的abstract方法,也可以继承这个abstrac方法。

如果一个非抽象类是某个抽象类的子类,那么它必须重写父类的抽象方法,给出方法体。

十、面向抽象编程

abstract类只关心操作,但不关心这些操作具体实现的细节。

十一、开、闭原则

让设计的系统应当对扩展开放,对修改关闭。本质是指当系统中增加新的模块时,不需要修改现有的模块。在设计系统时,应当首先考虑到用户的需求的变化,将应对用户变化的部分设计为对扩展开放,而设计的核心部分是经过精心考虑之后确定下来的基本结构,这部分应当是对修改关闭的,即不能因为用户的需求变化而再发生变化,因为这部分不是用来应对需求变化的。

如果系统的设计遵守了“开-闭原则”,那么这个系统一定是易维护的,因为在系统中增加新的模块时,不必去修改系统中的核心模块。

收藏
  • 人气文章
  • 最新文章
  • 下载排行榜
  • 热门排行榜