Java基础知识点
Java有三个版本:
- SE Standard(标准) 初级版本
- ME Micro移动版本
- EE Enterprise企业
JVM:
- java虚拟环境
即java virtual machine
JRE 和 JDK:
- JRE: runtime environment. 运行环境
- JDK: Development kit. 开发工具包.
工具:
- javac: 编译工具
- jar: 打包工具.
- 源文件(.java) 符合java语法的源代码
- 字节码文件(.class) 通过源文件编译出来的16进制文件.
java函数结构:
- 一. 外部结构. 类方法
- 二. 程序入口. main方法
- 编写在类中
- 类中的main方法可有可无.
- 有的话, 只能有一个
- 可以在入口中, 编写n多语句.(语句是以;结尾的句子.)
- 三. 编写代码.
- 一行编写一条语句.
基本语法:
- System.out.print("输出内容")
- System.out.println("输出内容且换行")
环境变量:
- 配置java路径:
cmd中能够在任何目录下运行java安装目录下的bin内的命令文件.
将java安装路径/bin, 添加到系统环境变量中 - 配置classpath:
使cmd能够在任何目录下运行目录下的class文件.
设置class所在的路径:
- set 临时设置. set classpath=...
// 设置了路径之后, 会先在设置的目录里找.
// 如果路径后面没有;则只寻找设置目录. 如果路径后面有;则先找设置路径,找不到找cmd当前目录. - 永久设置, 依旧在电脑环境变量中配置.
public class 和 class:
- 类的public是可有可无的
- 类一旦使用public来修饰, 则文件名和类名必须一致.
- 类如果没有使用public修饰, 则文件名和类名可以不一样.
- 一个类中的main方法是可有可无的, 但如果没有main方法的话, 无法运行.
- 一个源文件可以编写多个类, 当编译成功后会自动生成对应类的个数的字节码文件.
- 在一个源文件中, 最多只有一个类前面使用public修饰.因为, public修饰的类名,必须与源文件的文件名相同.
关键字:
java中预留的具有特殊意义的单词. 一般以蓝色显示, 都小写.
标示符:
对名字, 类名, 变量, 方法名称的修饰.
标示符的命名规则: 字母,下划线,$美元符号开头. 之后为字母,,$还有数字.不能使用关键字.
java中类名命名风格和Python中一致. 大驼峰命名法.
变量, 方法,参数的命名采用小驼峰命名法.
标示符的长度不应该超过15的字符.
java中区分大小写.
字面值:
java中常见字符类型:
整数类型字面值
浮点数类型字面值
字符串类型字面值: 双引号引起来的叫字符串.
字符类型字面值: 单引号引起来的叫字符. 这点和Python很大区别,Python不区分单双引号.
布尔类型字面值
java中常用的进制有:
2进制(01): 0b表示. 0b1101010110
8进制(0-7): 0表示. 0324357
10进制(0-9): 无表示. 315
16进制(0-9,A-F): 0x表示. 0x.
十进制转二进制: 除2取余法
二进制转十进制: 乘2叠加法
字符编码:
- 按照某种格式某种规定讲数据存储在计算机中.
ASCII:
'a' => 91 'b'=> 92
'A' => 65 'B'=>66
'0' ===> 48
'' ===> 32
iso8859-1: 西欧语言编码,兼容ASCII
GBK/GB2312: 中文编码
Unicode:统一全球所有国家文字
常用有 utf-8,utf-16,utf-32
java源代码使用unicode编码
乱码是因为编码和解码的时候没有采用一套统一的格式.
所以编码和解码的时候需要统一.
变量:
变量是存放数据的, 并且该变量中的数据是可以改变的.
- 常用数据类型:
整数类型 int
浮点类型 double (浮点类型区分: 单精准度浮点数; 双精准度浮点数;)
字符串 string
字符 char (字符类型取值范围,0---65535)
布尔类型 boolean
- java中对于变量的操作步骤:
- 声明(java中使用变量必须先声明, 且声明变量类型.)
- 赋值
- 使用
- 变量分为:
局部变量: 在方法中定义的变量
成员变量: 在类中定义的变量
变量在内存中的存储方式:
- 当程序在运行的时候, JVM会在内存中自动分配空间
- 内存中包括:
- 栈: 存放方法以及方法中的局部变量.
- 堆: 存放方法对象
- 方法区: 代码片段/常量池/静态属性
基本数据类型变量: 在内存中存放真正的值. 例如:int,double,char......
引用数据类型变量: 在内存中存放数据的地址(引用).例如:String
基本数据类型:
- 基本数据类型有八种:
- 4种整数类型: byte, short, int, long
- 2种浮点类型: float, double
- 1种布尔类型: boolean
- 1种字符类型: char
需要注意: java中String类型不属于基本的数据类型. 而属于一个对象.
- int的数据类型中分4种:
byte, short , int , long.
byte, 1字节.-128--127
short, 2字节 -32768--32767
int 4字节, 11位数字以下
- !! 取值范围小的数字类型可以赋值给 取值范围大的数字类型, 构成自动类型转换.
当数值超出 数字类型的取值范围, 则编译出错.
数据类型的相互转换:
- float与double:
- 注意:
java中, 一旦出现小数, 默认的数据类型就是double.
而double的数据类型取值范围大于, float类型.
所以, float a = 0.1; 报错
float a = 0.1; // 报错:
// 取值范围大的数据类型不能直接给取值范围小的数据类型赋值.否则报错.
float a = 0.1f; // 隐式转换(自动类型转换)
float a = (float)0.1; //显式转换(强制类型转换)
- char与int:
整数型可以给字符型直接赋值, 字符存放的就是ASCII对应的字符.
字符型也可以直接给整数型赋值, 整数型存放的是字符对应ASCII序列.
char a = 'a';
a = 99; // c
System.out.println(a);
a = 65; // A
System.out.print(a);
int b = 12;
b = 'B';
System.out.println(b); // 66
b = 'b';
System.out.print(b); //98
-
类型转化方式:
自动类型转换=> 隐式转换. 取值范围小 >> 取值范围大.
强制类型转换=> 显式转换. 取值范围大 >> 取值范围小. 大转小过程, 可能造成精度丢失. -
总结: 类型转换6条规则
- 基本8种数据类型, 除了boolean. 其他7种都可以相互转换.
- 当取值范围小的, 赋值给取值范围大的. 隐式类型转换
- 取值范围大的,赋值给取值范围小的. 显示类型转换, 可能存在精度丢失.
- 当对byte,short,char赋值的时候, 如果没有超出该类型范围则可以直接赋值.
- 当对byte,short,char类型进行运算的时候, 会先转化成int类型然后再进行运算.
- 当多种数据类型进行混合运算的时候, 则先转化为取值范围大的类型, 再进行运算.
运算符
-
四种运算符 + - * / .
使用方法没有什么大的区别.
当字符串与数字做加法的时候. 默认为连接运算.
但是字符串无法与数值做减法运算, 如出现则报错. -
++ 和 --
++ 和 -- 代表当前数值 +1 或者-1.
不过有前置后置的区别.
int a = 2;
int b = 3;
int c = a++; // 指的, 先获取a的值, 然后将a的值++操作之后, 赋值给c. 3 = a +1, c = 3. (当赋值过程结束之后, a才进行++)
int c = ++a; // 指的, 先对a值进行++操作, 然后再将a赋值给c. ++a = 3, c = 3. (当a进行++操作之后, 才对c进行赋值.)
== 与equals区别
- == 对比两个字符串的位置(类似Python’s is)
- 内存地址相同True
- 不同False
- equals对比字符串内容是否相同
- 内容相同True
- 不同False
equals的使用语法
// 使用equal的时候,以固定字符串为基,.equals()对比变量。
String name;
String name = input.next();
if("张三".equals(name)){
system.out.println("名字相同");
}
switch case
-
做
等值操作
的时候,使用switch case -
default 可有可无。顺序可以任意。 但是一般建议放在最后。
-
case后面要加break。 如果不加break,则从当前第一个匹配的case,之后的所有语句都会执行。(向下穿透)
-
switch case 中可以使用break , 但不能使用continue。
switch case 和 多重if 使用区别
进行等值操作的时候使用switch case。
区间操作的时候使用多重if。
for 循环
for 循环格式
for (循环条件){
循环体
}
例如:
for(int i =0;i<5;i++){ System.out.println("This is " + i + "line") }
语法中需要注意的点:
- 条件语句表达式有三:
- 表达式1 : 完成变量初始化
- 表达式2 : 变量判断。 True则运行循环体;False则跳过。
- 表达式3: 变量的更改。 对变量进行增减。 避免形成死循环。 (
表达式3
在循环体
之后执行)
- 条件语句三个表达式,以
;
隔开。 条件语句可以省略,但是该分号不能省略。
do while
do while 是java下比较独特的循环方式。 先进行循环, 再进行判断。
do为循环体, while为判断内容
语法:
do{
循环体
}while(循环条件)
例如:
int i = 0;
do{
System.out.println("OK")
i++;
}while(i<5)
方法
方法调用
方法调用的时候。
调用的方法会进入方法区
。
执行的时候会压入栈,(先进后出)
执行完之后, 从栈中释放之后, 才从方法区中释放.
调用自定义方法
在调用方法的时候, 需要先引入该方法所在的类,到同文件.
之后先调用类-方法名称;
如果在同类下调用方法的话, 类名可以省略.
方法中变量
- java中方法声明的变量是局部变量.形参也属于局部变量
- 方法执行完毕之后, 弹栈. 其中局部变量也随之释放空间.
- 各自方法中的局部变量可以重名.各自独立.
方法名
java中,同一个类的方法名可以相同. 但是参数列表必须不同(值的类型不同)
类
类对象的属性没有赋值的时候有默认值:
- int: 0
- float: 0.0
- Char: u0000
- Boole: false
- 所有引用类型(String): null
成员变量局部变量
- 在类中声明的是成员变量. 成员变量有默认值. (类型不一样默认值不一样)
- 在方法中生命的是局部变量, 形参也属于局部变量, 局部变量没有默认值, 必须先声明再使用.
- 成员变量和局部变量可以重名, 调用的时候就近原则, 谁近谁优先. 不过当在同名两个变量的时候, 想要调用较远的成员变量. 则可以通过: this.变量名 来调用对象的这个成员变量(this,调用这个方法的对象).
空指针异常
java.lang.NullPointeException
(java当中没有指针, 此处空指针异常, 指的是引用异常.)
当引用名称的值为null的时候,则不能访问某个对象中的属性或者方法. 如果访问, 则空指针异常.
解决办法:
在访问某个属性或者方法之前, 必须保证,该引用名称中存放的是对象的地址(引用).
封装
封装的意义不仅是为了减轻开发者的负担,也是为了提升代码鲁棒性.
当不希望外部调用, 或者为了避免逻辑错误, 需要用到封装.
构造一些内部才能使用的方法或者属性且避免外部修改, 这样在进行调用的时候, 能够传入合理的属性,产生正确的逻辑.
在Python中, 方法或者属性前面添加__两个下划线, 表示私有属性或方法
Java中. 则使用private私有的, 来表示该方法的私有属性.
this关键字
this不仅能访问本类的属性和方法, 还可以调用本类的构造方法.
this在调用本类的构造方法的时候, 需要写在方法的第一句.
可以直接调用类的成员变量.
this在使用的时候, 应该避免递归调用. 调用自身.
参数的传递
基本数据类型:
基本数据类型在传递的过程当中传递的是具体的值.
传递后, 当一个方法的值发生变化. 另一个方法内的值不变.
两者是相互独立的
java中使用其他包的类
首先确保是该类是公共类, 以便能够从外部调用.
其次, 在需要使用的包中. 导入该类, 即可使用
Eclipse快捷键
-
Alt+/ 智能提示
-
Ctrl+1 快速修复
-
Ctrl+W关闭当前窗口
-
Ctrl+Shift+w 关闭所有窗口
-
Ctrl+s 保存
-
Ctrl+Shift+s 保存所有
-
Ctrl+单行/ 取消注释
-
Ctrl+Shift+/ 块注释
-
Ctrl+Shift+ 取消块注释
-
Ctrl+Shift+f 代码格式化(自动对齐)
-
Ctrl+Shift+0 自动导入所有需要的类
-
Shift+Enter 在当前行的下面产生空行
-
Ctrl+At+向下箭头 复制一行
-
A1t+向下/向上箭头 移动一行
-
Ctrl+D 删除一行
-
Alt+Shift+R 重命名
-
Alt+Shift+m 把一段代码抽象为一个方法
-
Alt+Shift+l 把一个表达式赋值给一个局部变量
-
Ctrl+Shift+T 打开类型
-
Ctrl+0 显示类成员
-
Ctrl+F11 运行程序
-
F11 调试程序
-
Ctrl+Shift+b 添加/取消断点
-
Alt+Shift+A 块选择
- Alt+Shift+S 自动生成列表
- Alt+Shift+S+O 自动生成带参构造方法
- Alt+Shift+S+S 自动重写toString方法.
java中接口概念
相比较于Python, java是不支持多继承的概念的. 子类只能继承一个父类.
则子类不能拥有两个父类的功能.
这样的话, 能够让开发过程更加清晰, 维护起来更加方便.
但是开发过程中有些时候却会比较繁琐.
所以在java中的接口的概念, 比python中有更明确的定义.
java中接口使用interface
关键字声明.
接口是功能的封装
接口可多继承.
可以理解的是.java中的对象, 和python中的对象, 如果详细划分的话, 具有不同的意义.
Python中对象, 具有对象的属性和方法(功能),当继承对象类的时候, 同时继承属性 以及 方法.
Java中对象, 具有对象和属性, 继承单个类的属性和方法. 某些时候, 可以把类和接口分隔开来理解. 一个类有许多接口, 继承一个接口集, 如当前类没有所需要的功能的时候, 就不能再继承接口集, 只能一个一个去添加功能所在的接口.
这样能够让代码更清晰. 不至于出现多继承之后, 出现了许多方法, 难以维护的情况.
Rational Rose
Rational Rose
是一款面向对象的同意建模语言的可视化建模工具. 用于可视化建模.
一般用在公司级水平软件应用的组件构造
能够用图像化 来描述程序中类
之间的关系
try
try语法, 搭配catch 用来捕获某种异常. finally, 无论如何都会执行的语句.
try至少要搭配任意一个,否则语法错误. 且在finally中会释放系统资源.[GC]
在使用过程当中. 两个点需要注意:
- catch捕捉异常的时候, 顺序应该从小到大. 先捕捉可能出现的针对性问题, 然后最后一个catch再去打印异常栈.
- 在catch中return的变量, 会先暂时性保存变量的值, 待执行finall结束之后, 再将变量返回. 所以如果在finally中进行变量的改动, 不会体现在返回值上.
- 在try中有多个return的时候, 只以finally中return为准. finally中没有return才考虑其他.
自定义throw抛出异常
在使用异常的时候, 很常见遇到一些异常情况. 所以时常需要自定义异常用以抛出.
自定义异常的步骤如下:
- 定义一个类, 继承自
Exception
- 在定义的异常类中, 提供两个构造方法.(一般无参和字符串)
- 在需要的位置上, 通过
throw
抛出异常. throw
所在的位置通过throws
声明该异常.- 在调用方法时, 需要对受检异常进行预处理
try
catch
数组
java中数组定义的时候也同样需要对数组类型进行定义,而且需要定义数组的长度
// 整数类型数组, 数组名为data, 长度为10
int[] data = int[10];
数组和String一样, 属于引用类型数据.
在栈中以数组名(变量名)存储了数组在堆中的内存地址.
需要注意的是, 在定义数组的时候,会直接根据数组的长度, 在内存中开辟一块儿连续的存储长度. 用来存储该数组.
在使用数组的时候, 根据下标查询数组的时候, 其实是根据 数组类型内的 数据宽度, 来计算,然后偏移, 之后获取下标对应的数据所在字节.
比如说
data[2]
假设data在堆中的地址为0x2555
则对应, int类型两个字节, 下标为2的元素位置在0x2555之后向后偏移2* 2= 4的字节位置. 则是该元素所处的位置. 便可以进行取值.
数组静态初始化定义
// 数组的静态定义不需要指定个数, 以静态指定的数量为标准
int[] data = int[]{1123,123,4,5,123,5};
数组循环
在java中, for循环数组的时候.有两种方式.
通过一般的for循环, 根据数组的.lenght
属性判断长度, 设置变量进行循环.
还可以采用foreach
的写法
for(int xx : data ){
System.out.println(xx)
}
可变长参数
当定义一个方法可接收任意长度的数据, 可使用可变长参数.
注意:
- 一个方法只能拥有一个可变长参数.
- 可变长参数 只能 放在参数列表的最后.
因为在`堆`中定义数组的时候, 没有设置开辟的具体的空间, 则该 可变长参数应该放在最后, 表明之后的所有空间都可以用来存放可变长参数.
- 在方法体中, 使用可变长参数的时候, 直接当做数组使用即可.
定义方法:
方法名参数类型
参数名
,...
参数
public class Test{
public static void main(String[] args){
sum();
sum(1,2,3,4,5);
}
// 在定义的时候直接时候 ... `变量名` 的方式代表可变长参数
public static void sum(int ... data){
int sum = 0;
for (int i : data){
sum += i;
}
System.out.println("Sum == " + sum);
}
}
二维数组
java中的数组和Python列表中不一样的地方, 一方面在于强类型, 一方面在于静态化的数据大小.
二位数组上的结构类似于Python中的列表套列表.
java中二维数组, 就是数组中, 嵌套数组.
其中, 二维数组中 每一个元素都保存的是, 一个一维数组的引用. 存储了该一维数组在堆
中的内存地址.
public static void main(String[] args){
int [] data1 = new int []{1,23,4,5,5};
int [] data2 = {6,8,4,2,3};
int x = 10;
int y = 20;
int [] data3 = {x,y};
// 声明二维数组, 两个[] [] 来表示嵌套.
int [][] myData = { data1, data2, data3};
}
二维数组的静态初始化
元组有静态初始化.
二维数组也有静态初始化.
方式有:
public static void main(String[] args){
// 二维数组的定义.
int [] [] myData = new int[5] [];
// 需要注意的是在这里.
// myData是一个数组.数组的元素是int[], int[]却是一种引用类型, 所以默认初始化为null
// 每个元素都是int[]类型的一维数组.
// 所以在静态初始化的时候, 需要对元素中的每一个一维元素甚至包含其内的元素也要赋值.
// 赋值过程:
myData[0] = new int[1,2,3];
myData[1] = new int[]{1,2,3};
// mydata[2] = {1,2,3}; //该简化方式, 仅适用于数组的静态初始化. 不适合用来赋值.
int [] data1 = {1,2,3};
myData[2] = data1;
// 二维数组的静态初始化
int [][] myData2 = new int [][]{data1,myData2[1],new int []{1,2,3}};
// 静态初始化简写:
int [][] myData3 = {data1,myData2[1],new int []{1,2,3}};
int [][] myData4 = {{1,2,3},{1,2,3},{1,2,3,4}};
}