Java 基础知识点整理
Java 语言是一种优秀的编程语言,由 C 语言、C++ 语言发展而来。Java 语言提供了一些有效的新特性,使得使用 Java 比 C++ 更容易写出“无错代码”。
Java特性和优点
-
面向对象编程的思想,更简单有效,Java 省略了 C++ 语言中所有难以理解的部分,例如头文件、指针、结构、单元等等。
-
可移植性,跨平台,“一次编写,到处运行”。
Java 程序实际上没有直接和操作系统打交道,而是在 JVM 虚拟机(用 C++ 语言实现的位于操作系统之下的虚拟的计算机)上运行的,JVM 屏蔽了不同操作系统之间的差异。
-
高性能,Java 是一种解释型语言,所以其执行效率相对 C/C++ 语言来说会慢一些,但它并不是完全的解释型,而是一种解释型和编译型的折中。
使用 Java 语言编写程序,首先使用编译软件或集成开发环境编写源程序,再使用 Java 编译器进行一次伪编译,将源程序编译成为中间码(字节码文件.class),最后再使用 Java 解释器进行解释。
这一手段使得其性能得到提高。
-
分布式计算,Java 语言拥有强大的、易于使用的连网能力,Java 应用程序可以像访问本地文件系统那样通过 URL 访问远程对象。
-
动态性,反射机制,在 Java 语言中可以简单直观的查询运行时的信息,也可以将新代码加入到正在运行的程序中去。
-
多线程,Java 语言的多线程处理能力使得程序能够具有更好的交互性、实时性。
-
安全性,Java 语言在设计之初就在安全性方面考虑很仔细,通过 Java 可以构建出防病毒、防篡改的系统。
-
健壮性,Java 拥有异常机制,垃圾清理机制。
Java 语言在伪编译阶段做了许多潜在问题的检查,由于省略了指针与内存管理,避免了很多在程序运行时才能被发现的问题。
此外,Java 提供了对内存的自动管理,程序员无需在程序中进行分配、释放内存。
Java三大版本
JavaSE:标准版(桌面程序、控制台开发……)
JavaME:嵌入式开发(手机、家电……)
JavaEE:E企业级开发(web端、服务器开发……)
了解JDK、JRE、JVM
JDK:Java Development Kit,Java 开发套件
JRE:Java Runtime Environment,Java 运行环境
JVM:Java Virtual Machine,Java 虚拟机
由下图可知,JDK 包含 JRE ,JRE 包含 JVM。
理解 Java 内存:
- 栈:存放基本类型变量(包括基本类型的具体数据元素),存放引用对象的变量,即存放该引用在堆中的地址,可以把它看成是线程区,main 线程就在其中。
- 堆:存放 new 出来的对象、数组,可以被所有线程共享,不会存放别的对象引用,堆中进行默认初始化(0 或 null)。
- 方法区:存放 static 变量和 class 变量,可以被所有线程共享。
Java语法规则
01-注释、标识符、关键字
-
注释:书写注释是一个很好的习惯,注释不会被执行,目的是让人看懂
Java中的三种注释:
- 单行注释://注释
- 多行注释:/* 注释 */
- 文档注释: /** 注释 */
-
标识符:程序员自主命名的符号,类名、变量名、常量名、接口名、方法名等等
命名规则与规范:
- 只能由数字、字母(包括中文)、下划线、美元符号组成
- 不以数字开头
- 关键字不做标识符
- 严格区分大小写
- 见明知意
- 接口与类名:每个单词首字母大写
- 变量名与方法名:第一个单词首字母小写,第二个单词开始首字母大写
- 常量名:所有字母大写,单词与单词间采用下划线衔接
-
关键字:SUN 公司提前定义好的具有特殊含义的单词
02-数据类型
数据类型用来声明变量,程序在运行过程中根据不同的数据类型分配不同大小的空间。
数据类型分为两大类:基本类型 ( 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 换行符
03-类型转换
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;
输出结果:
04-变量、常量
-
变量:内存中存储数据的最基本单元
-
变量三要素:变量名、变量类型、作用域(值,内容空间复用)
-
变量声明:
语法:数据类型 变量名
注意:变量必须先声明,再赋值,最后才能访问;
变量可以重复赋值,但不可重复声明。
-
变量的作用:
-
未声明变量的情况:
System.out.println(100); System.out.println(100);
输出结果都为100,但分别占用不同的内存空间。
-
已声明变量的情况:
int i=100; System.out.println(i); System.out.println(i);
输出结果都为100,但两者占用相同的内存空间,实现了内存空间复用,节省开销。
-
-
理解作用域:根据声明变量的位置进行划分
- 类变量(静态变量):在方法体之外声明的变量,类加载时初始化并分配空间;
- 实例变量:在方法体之外声明的变量,构造方法执行时、创建对象时分配空间。从属于对象
- 局部变量:在方法体之内声明的变量,方法执行过程中分配空间。局部变量只在当前方法体中有效,在使用局部变量前必须初始化(赋初始值),在方法体执行结束后局部变量会释放空间。
由上图可知,局部变量开辟的是栈空间,而栈空间不会对变量进行初始化,所以我们要给局部变量赋初始值。
堆空间会对变量进行初始化,自动给变量赋数据类型默认值,方法区相当于是堆空间,也会进行初始化。
-
-
常量:初始化后不能再被改变值,使用修饰符 final 。
语法:final 数据类型 常量名 = 初始值;
05-运算符 Operator
算术运算符 | + , - , * , / (取商) , % (取余,模运算) , ++ , - - |
赋值运算符 | = , += , -= , *= , /= , %= , ^= , &= , |= , <<= , >>= |
关系运算符 | > , < , >= , <= , == , != , instanceof |
逻辑运算符 | & , | , ! , &&(短路与) , ||(短路或) |
位运算符 | & , | , ^ (异或) , ~ (取反) , >> (右移1位相当于除以2), << (左移1位相当于×2) |
条件运算符 | 布尔表达式 ? 表达式1 : 表达式2(布尔表达式为true时执行表达式1,否则执行表达式2) |
其他 | new |
注意:
- 变量名 ++,变量名 - -,表示变量先赋值后自增
- ++ 变量名,- - 变量名,表示变量先自增后赋值
06-包机制 Package、JavaDoc
-
包机制:为了更好的组织类,Java 提供包机制,用于区别类名的命名空间,相当于文件夹。一般利用企业域名倒置作为包名,要使用其他包下的类时,需要使用 import 语句导入相应的包。
-
JavaDoc:JavaDoc 命令是用来生成自己 API 文档的,写在类的前面就是该类的注释,写在方法的前面就是该方法的注释。
参数信息:
- @author 作者
- @version 版本号
- @since 指明需要使用的最早的jdk版本
- @param 参数名
- @return 返回情况
- @throws 异常抛出情况
07-Java流程控制
-
用户交互 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:方法体中的返回。
08-Java方法 Method
-
定义:方法的本意是功能块,是可以完成某个特定功能,并且可以被重复利用的代码段。类似于其它语言中的函数。
方法包含于类或由类创建的对象中,方法在程序中被创建,在其他地方被引用。
我们在设计方法时,最好保持方法的原子性,即一个方法实现一个功能,有利于后期的扩展。
-
基本语法:[]表示可选
[修饰符] 返回值类型 方法名 ([形参类型 形参名]){
方法体;
[return 返回值;] //若方法返回值类型为void,则不写
}
-
方法的调用
静态方法:类名.方法名()
实例方法:引用.方法名() ——引用即创建的实例对象
-
方法的重载:在一个类中,方法名必须相同,形参列表必须不同(形参个数不同、或类型不同等)。
方法的返回值类型可以相同也可以不同,若仅仅是方法的返回值类型不同则不是方法的重载。
-
可变(长度)参数方法:JDK1.5 开始,Java 支持传递同类型的可变参数给一个方法。如果形参列表存在可变长度参数,那么编译器会将其转化为一个数组形参,本质上相当于定义了一个数组。
public class Test {public static void main(String[] args){Test test=new Test();test.print(1,2,3,4);}public void print(int... a){System.out.println(a);System.out.println(a[0]);System.out.println(a[1]);System.out.println(a[2]);System.out.println(a[3]);} }
运行结果:
可以看到第一行结果,a输出的是对象 test 的内存空间地址值。
声明:在指定的可变参数类型后加…。如int… a,表示在调用该方法时,传递的int型实参可以是输入不定数量(0~n)的整型数。
注意:一个方法中只能指定一个可变参数,并且必须是方法的最后一个形式参数。
-
方法的递归:方法自己调用自己,或者几个方法互相调用,了解递归的思想。(程序从前往后运行,数值从后往前传递)
递归通常可以把一个大型的复杂问题层层转化为一个与原问题相似的规模较小的问题来求解,其能力在于用有限的语句来定义对象的无限集合。
递归可能引起的问题:栈内存溢出错误,由两种情况引起:递归方法没有结束条件,递归太深导致弹栈之前就栈内存溢出。
所以在写代码的时候,建议使用循环,循环的效率高、内存小,尽量避免使用递归。
09-数组
-
概述
数组是一种数据结构,是相同类型数据的有序集合,描述的是相同类型的若干个数(元素)按照一定先后次序(下标)排列而成,数据元素通过索引(下标)获得。
数组属于引用类型数据,指向本数组第一个元素的内存地址。其父类是 Object 类,存储于堆内存中。
-
如果数组中存储的元素是基本数据类型,则本数组元素存储的是数据元素本身;
-
如果数组中存储的元素是引用数据类型,则本数组元素存储的是对象的内存地址。
-
-
声明:先在栈中声明,再在堆中开辟空间
-
动态初始化:包含了默认初始化 0 或 null (堆中操作初始化),不确定具体元素,需要预先分配空间。
语法:元素数据类型[] 数组变量名 = new 元素数据类型[数组长度];
-
静态初始化:创建 + 赋值,花括号里是元素内容。
语法:元素数据类型[] 数据变量名 = {……};
-
-
注意
- 数组一旦创建长度不可变,要扩容必须新建一个数组并拷贝。
- 数组拷贝属于浅拷贝。
- 数组元素必须同一类型且内存地址连续,首元素的内存地址(堆中)作为数组对象(栈中)的内存地址。
- 数组变量属于引用类型,所以数组本身可以看成一个对象,Java 里对象在堆中。
- 遍历数组:for 循环、for-each循环
-
二维数组(矩阵)
-
语法:动态和静态初始化
数据类型[][] 变量名 = new 数据类型[数据长度(行数)][元素数组长度(列数)];
数据类型[][] 变量名 = {{……},{……},……};
-
遍历:两层循环。
for(int i=0;i<array.length;i++) {for(int j=0;j<array[i].length;j++){System.out.print(array[i][j]+" ");} }
-