文章目录
优点
-
面向对象编程的思想,更简单有效,Java 省略了 C++ 语言中所有难以理解的部分,例如头文件、指针、结构、单元等等。
-
可移植性,跨平台,“一次编写,到处运行”。
Java 程序实际上没有直接和操作系统打交道,而是在 JVM 虚拟机(用 C++ 语言实现的位于操作系统之下的虚拟的计算机)上运行的,JVM 屏蔽了不同操作系统之间的差异。
-
高性能,Java 是一种解释型语言,所以其执行效率相对 C/C++ 语言来说会慢一些,但它并不是完全的解释型,而是一种解释型和编译型的折中。
使用 Java 语言编写程序,首先使用编译软件或集成开发环境编写源程序,再使用 Java 编译器进行一次伪编译,将源程序编译成为中间码(字节码文件 .class),最后再使用 Java 解释器进行解释。
这一手段使得其性能得到提高。
-
分布式计算,Java 语言拥有强大的、易于使用的连网能力,Java 应用程序可以像访问本地文件系统那样通过 URL 访问远程对象。
-
动态性,反射机制,在 Java 语言中可以简单直观的查询运行时的信息,也可以将新代码加入到正在运行的程序中去。
-
多线程,Java 语言的多线程处理能力使得程序能够具有更好的交互性、实时性。
-
安全性,Java 语言在设计之初就在安全性方面考虑很仔细,通过 Java 可以构建出防病毒、防篡改的系统。
-
健壮性,Java 拥有异常机制,垃圾清理机制。
Java 语言在伪编译阶段做了许多潜在问题的检查,由于省略了指针与内存管理,避免了很多在程序运行时才能被发现的问题。
此外,Java 提供了对内存的自动管理,程序员无需在程序中进行分配、释放内存。
面向过程 VS 面向对象
C 语言是面向过程的语言,C++ 是一半面向过程、一半面向对象,Java 是完全面向对象编程(Object-Oriented Programming)的语言。
区别:
- 面向过程侧重功能的实现步骤和因果关系,面向对象侧重对象之间的组合关系;
- 面向过程代码耦合度高、扩展维护能力较低,面向对象相反;
- 面向过程的优点是快速开发,面向对象需要提取和模型建立(框架)。
JDK 、JRE 、JVM
JDK:Java Development Kit,Java 开发套件
JRE:Java Runtime Environment,Java 运行环境
JVM:Java Virtual Machine,Java 虚拟机
由下图可知,JDK 包含 JRE ,JRE 包含 JVM。
有关 JVM 的内容,读者可以戳这里:
语法
01-注释
书写注释是一个很好的习惯,注释不会被执行,目的是让人看懂。
Java 中的三种注释:
- 单行注释:// 注释
- 多行注释:/* 注释 */
- 文档注释: /** 注释 */
02-标识符(自定义名)
程序员自主命名的符号,类名、变量名、常量名、接口名、方法名等等
命名规则与规范:
- 只能由数字、字母(包括中文)、下划线、美元符号组成
- 不以数字开头
- 关键字不做标识符
- 严格区分大小写
- 见明知意
- 接口与类名:每个单词首字母大写
- 变量名与方法名:第一个单词首字母小写,第二个单词开始首字母大写
- 常量名:所有字母大写,单词与单词间采用下划线衔接
03-运算符
算术运算符 | + , - , * , / (取商) , % (取余,模运算) , ++ , - - |
赋值运算符 | = , += , -= , *= , /= , %= , ^= , &= , |= , <<= , >>= |
关系运算符 | > , < , >= , <= , == , != , instanceof |
逻辑运算符 | & , | , ! , &&(短路与) , ||(短路或) |
位运算符 | & , | , ^ (异或) , ~ (取反) , >> (右移1位相当于除以2), << (左移1位相当于×2) |
条件运算符 | 布尔表达式 ? 表达式1 : 表达式2(布尔表达式为true时执行表达式1,否则执行表达式2) |
其他 | new |
注意:
- 变量名 ++,变量名 - -,表示变量先赋值后自增
- ++ 变量名,- - 变量名,表示变量先自增后赋值
04-数据类型
数据类型用来声明变量,程序在运行过程中根据不同的数据类型分配不同大小的空间。
数据类型分为两大类:基本类型 ( primitive type ) 和引用类型 ( reference type )
- 基本数据类型
数值类型 | 占字节 | 取值范围 | 默认 | |
---|---|---|---|---|
整数型 | byte(字节型) | 1 | [-27~27-1] | 0 |
short(短整型) | 2 | [-215~215-1] | 0 | |
int(整型) | 4 | [-231~231-1] | 0 | |
long(长整型) | 8 | [-263~263-1] | 0L | |
浮点型 | float(单精度) | 4 | [-231~231-1] | 0.0f |
double(双精度) | 8 | [-263~263-1] | 0.0 | |
字符型 | char(字符型) | 2 | [0~216-1] | ‘\u0000’ |
布尔类型 | boolean(布尔型) | 1 | true、false | false |
-
引用数据类型:类(如字符串类 String)、接口、数组;其实 Java 中除了8种基本数据类型之外,其余的都属于引用数据类型
-
补充
bit:位,一个二进制码0/1,是计算机内部数据存储的最小单位
byte:字节,B,1B = 8bit,是计算机内部数据处理的基本单位
1024B = 1KB
1024KB = 1M
1024MB = 1G (210 = 1024)
- 扩展
整数扩展:Java 中不同进制的表示
//二进制
int i1=0b10;
//八进制
int i2=010;
//十进制
int i3=10;
//十六进制
int i4=0x10;
输出结果:
浮点数扩展:大小有限,结果会舍入误差,有时接近但不相等,因此最好完全避免使用浮点数进行比较。使用 BigDecimal,Java 语言的一种数学工具类。
字符扩展:ASCII 码,采用1B进行存储,所有的字符本质还是数字
字符 | 十进制 | 二进制 |
---|---|---|
0 | 48 | 0011 0001 |
A | 65 | 0100 0001 |
a | 97 | 0110 0001 |
转义字符:
\t | 制表符 |
\n | 换行符 |
05-类型转换
8种基本数据类型中,除了 boolean 类型不能转换,其余七种都可以转换。多种不同类型的数据在做运算时,要先转换为同一种数据类型(容量最大的那一种)。
byte、short、char 类型在做混合运算时要先各自转换成 int 类型。
如果 int 类型没有超出 byte、short、char 的取值范围,可以直接赋值给这三种类型的变量。
-
自动类型转换:小容量向大容量转换
-
强制类型转换:大容量向小容量转换,编写时必须添加“强制类型转换符”
语法:(转换后的数据类型)转换前的数据类型变量名;
强制类型转换在运行时可能出现精度损失、内存溢出等问题。
int a=10_0000_0000;//数字间可以用下划线隔开
int b=20;
long ab1=a*b;//内存溢出,运算过程是int型,运算后已经溢出了
long ab2=(long)a*b;//在运算前转换,运算过程一直是long型
long ab3=a*(long)b;
输出结果:
06-关键字
1. this
this 保存当前对象的内存地址,指向自身。
使用:
- this 出现在实例方法中,代表当前对象,存储在堆内存中对象的内部
- this 出现在构造方法中
注意:静态方法中不能使用 this ,因为静态方法中不存在对象,而 this 代表当前对象。
this 用于区分局部变量和实例变量时不能省略(增强代码可读性),如 setter() 方法。
2.super
super 不保存内存地址,也不指向任何对象,只代表当前对象的父类特征。当父类和子类存在同名属性或者方法重写时,通过 super 可以访问父类属性或调用父类方法。
使用:
- super() :调用父类的无参构造器
- super(实参):调用父类的带参构造器,初始化 当前对象的父类特征,而不是创建新对象
- super.方法名/属性名:调用父类方法、访问父类属性
注意:
- super() 和 this() 只能出现在构造方法首行,且两者不能同时出现
- 若构造方法首行没有 super() 和 this() ,则默认有一个 super() ,父类构造方法一定执行。
3.static
修饰静态变量、静态方法,使用时不需要 new 对象,而是使用 类名. 的方式访问。
静态变量 VS 实例变量
- 静态变量属于类级别的属性,在类加载时初始化,无需 new 对象,存储在方法区
- 实例变量属于对象级别的属性,使用时需要 new 对象
- 当一个变量不因对象的变化而变化时,把它声明为静态变量,可以避免堆空间的内存浪费(使用该变量时不用 new )
注意:
- 局部变量:在方法体内声明
- 实例变量:对象级别,存储在堆内存
- 静态变量:类级别,存储在方法区,方法区存储的都是只加载一次的
静态方法 VS 实例方法
- 静态方法:行为发生时不会因对象的变化而变化,无需 new 对象,通过 类名. 调用
- 实例方法:行为发生时会因为对象变化而不同,需要 new 对象,通过引用. 调用
- 大部分情况下,工具类中的方法都是静态方法,便于使用
注意:调用静态方法不会发生空指针异常,空指针异常只发生在空引用访问实例相关的数据情况下。
静态代码块 VS 实例代码块
- 静态代码块在类加载时被执行,且只执行一次,利用静态代码块可以记录类加载的日志信息
- 实例代码块在对象创建时被执行,执行多次。
4.final
final 表示最终的、不可变的。
注意:
- final 修饰的局部变量只能赋值一次
- final 修饰的实例变量只能赋值一次,系统不自动赋值,手动赋值可以在声明变量时,也可以在调用构造方法时,一般会添加 static 联合修饰
- final 修饰的静态变量只能赋值一次,这两个关键字联合修饰的变量称为常量(常量全部大写,单词之间_分隔)
- final 修饰的引用只能永远指向一个对象,但可以修改对象的属性值,不会改变内存地址(引用)
- final 修饰的方法无法覆盖(重写)
- final 修饰的类无法继承
常量 VS 静态变量:
- 不同点在于常量的值不能变
- 相同点在于都存储在方法区,都在类加载时初始化
07-包机制 Package
为了更好的组织类,Java 提供包机制,用于区别类名的命名空间,相当于文件夹。一般利用企业域名倒置作为包名,要使用其他包下的类时,需要使用 import 语句导入相应的包。
JavaDoc:JavaDoc 命令是用来生成自己 API 文档的,写在类的前面就是该类的注释,写在方法的前面就是该方法的注释。
参数信息:
- @author 作者
- @version 版本号
- @since 指明需要使用的最早的jdk版本
- @param 参数名
- @return 返回情况
- @throws 异常抛出情况
08-流程控制
用户交互 Scanner 工具类:java.util.Scanner 是 Java5 的新特性,用于获取用户的输入,实现程序与人的交互。它也是一种属于 IO 流的类,如果不关闭会一直占用资源,用完后要调用 close() 方法关闭资源。
基本语法:Scanner s = new Scanner(System.in);
通过 Scanner 类的 next() 与 nextLine() 方法获取键盘输入的字符串,在读取前通过 hasNext() 与 hasNextLine() 方法判断是否有字符串输入。
next() 以空格结束,nextLine() 以回车结束。
顺序结构
Java 的基本结构就是顺序结构(从上到下执行),顺序结构是最简单的算法结构,它是任何一个算法都离不开的一种基本算法结构。除非特别指明,否则就按照顺序一句一句执行。
选择结构
-
if 单选择结构:先判断再执行
基本语法:
if(布尔表达式){
布尔表达式为 true 时,将要执行的语句;
}
-
if 双选择结构
基本语法:
if(布尔表达式){
布尔表达式为 true 时,将要执行的语句1;
}else{
布尔表达式为 false 时,将要执行的语句2;
}
-
if 多选择结构
基本语法:
if(布尔表达式1){
布尔表达式1为true时,将要执行的语句1;
}else if(布尔表达式2){
布尔表达式2为true时,将要执行的语句2;
}else if(布尔表达式3){
布尔表达式2为true时,将要执行的语句3;
}……
else{
以上布尔表达式都为false时,将要执行的语句;
}
-
if 嵌套结构:在 if 结构里嵌套 if 结构,以提高效率(二分法)。
基本语法:
if(布尔表式式1){
布尔表达式1为true时,将要执行的语句1;
if(布尔表达式2){
布尔表达式2为true时,将要执行的语句2;
}
}
-
switch 多选择结构:switch case 语句判断一个变量与一系列常量值的相等关系,每个常量值为一个分支。
基本语法:
switch(表达式){
case value1:
表达式等于value1时,将要执行的语句1;
break; //break可选,表示跳出该选择结构,不再执行下面case分支里的语句
case value2:
表达式等于value2时,将要执行的语句2;
//不写break,则下面分支里的代码将会被执行,直到遇到break或是switch选择结构结束
……
default: //可选
以上分支都不满足的情况下,将要执行的语句;
}
switch语句中的变量类型(表达式类型)可以是byte、short、int、char、String(JDK7开始支持String类的比较),同时case后面的常量必须是相同类型。
循环结构
-
while 循环:最基本的循环,先判断后执行。
基本语法:
while(布尔表达式){
布尔表达式为true时,将要执行的循环体;
}
如果循环条件一直为true,就会造成无限循环(死循环),会影响程序性能或造成程序崩溃,应该避免这种情况。
少部分情况下需要循环一直进行,比如服务器的请求响应监听等。
-
do while 循环:先执行后判断,至少会执行一次。
对于上面的while 循环而言,如果不满足循环条件,则不能进入循环。但有时我们需要即使不满足条件,也至少要执行一次。
基本语法:
do{
代码块;
}while(布尔表达式);
-
for 循环:最有效、最灵活,循环次数在执行前就已经确定。
基本语法:
for(初始化表达式;布尔表达式;表达式){
布尔表达式为true时,将要执行的循环体;
}
-
增强for 循环:主要用于数组或集合对象。(可遍历数组)
基本语法:
for(声明语句:表达式){
循环体;
}
声明语句:声明新的局部变量(作用域限定在该循环内),该变量的数据类型必须和数组元素的类型相匹配,其值与此时数组元素的值相等。
表达式:要访问的数组名,或者是返回值为数组的方法。
转向语句
- break:控制循环的流程,用于强行跳出该循环,即不再执行循环体中剩余的语句(也可在switch选择语句中使用),并且不再执行该循环。
- continue:用在循环体中,用于终止某次循环过程,即不再执行循环体中剩余的语句,而是接着进行下一次是否执行该循环的判定。
- return:方法体中的返回。