java基础学习笔记记录
文章目录
本内容建立在学习过C语言的基础上。
常用DOS命令
- dir ,查看当前目录下的所有文件及文件夹
- md ,创建文件夹
- rd ,删除文件夹
- cd 地址,进入指定目录(进入C、D盘直接输入C:、D:即可跳转)
- cd… ,返回到上一级目录
- cd\ ,返回到根目录
- del ,删除文件
- exit ,退出dos命令行
面向过程和面向对象
过程:记录一个进程
对象:将每一个不同的操作或实体包装成不同的模块,以便于搭积木式组合
两大核心机制JVM和GC
将Java文件在不同版本的JVM上执行,实现Java的跨平台性
自动回收不使用的内存,相比自行回收,回收不及时,但不会出错。
下载、安装及环境变量配置
为了防止需要用到多个版本或着需要替换Java版本时重新安装下载的麻烦
不推荐直接下载安装官网,推荐使用压缩版JDK,方便随取随用
这样更改Java版本时只需更改环境变量即可。
配置环境变量
- 设置JAVA_HOME
为需要的版本的jdk所在文件夹的地址(不用加“”或‘’) - 设置CLASSPATH
.;JAVA_HOME%\lib\dt.jar;%JAVA_HOME%\lib\tools.jar
- 在path中加入两个新的配置
%JAVA_HOME%\bin %JAVA_HOME%\jre\bin
除了首次,以后更改版本时只需更改第一步即可。
eclipse快捷输入
输入:ma+" Alt+/ "
Eclipse会自动筛选库钟带有ma的内容,选择相应的项,将输出:
public static void main(String[] args) {
}
syso+" Alt+/ "
为:
System.out.println();
" Ctrl+/ "
,//注释及取消
"Ctrl+Shift+F"
自动格式
文件Hello world格式
package com.test;
public class Text{
public static void main(String[] args){
System.out.print("Hello world");
}
}
编译后文件格式为.class
三种注释
单行注释//
多行注释/**/
文档注释,用于解释该文件的思路
/**
*这是一个打印hello world的文件
*@author sidany
*@version 1.1.0
*/
关键字与保留字
关键字:在编程语言中事先定义好的,用于关键地方表达特使含义的单词,关键字主要特点之一是都是小写。
保留字:Java中提前预定好的,现版本尚未使用,可能会在未来版本中作为关键字来使用的单词。
标识符与命名规范
Java对各种变量、方法和类等要素命名时使用的字符序列称为标识符。相当于C语言中的变量、函数。
命名规范:
- 不能用数字开头
- 不能使用关键字和保留字,但可包括。
- 包括26字母,0-9数字、_和$。不包括空格。
- 严格区分大小写
各类名称命名规范:
- 包名:全小写,xxxyyy
- 类名、接口名:各单词首字母大写,XxxYyy
- 变量名、方法名:第一个单词首字母小写,其他单词首字母大写,xxxYyy
- 常量名:全大写,以下划线隔开,XXX_YYY
Scanner 输入
java.util.Scanner 是 Java5 的新特征,我们可以通过 Scanner 类来获取用户的输入。
下面是创建 Scanner 对象的基本语法:
Scanner s = new Scanner(System.in);
接下来我们演示一个最简单的数据输入,并通过 Scanner 类的 next() 与 nextLine() 方法获取输入的字符串,在读取前我们一般需要 使用 hasNext 与 hasNextLine 判断是否还有输入的数据:
使用 next 方法:
import java.util.Scanner;
public class ScannerDemo {
public static void main(String[] args) {
Scanner scan = new Scanner(System.in);
// 从键盘接收数据
// next方式接收字符串
System.out.println("next方式接收:");
// 判断是否还有输入
if (scan.hasNext()) {
String str1 = scan.next();
System.out.println("输入的数据为:" + str1);
}
scan.close();
}
}
执行以上程序输出结果为:
$ javac ScannerDemo.java
$ java ScannerDemo
next方式接收:
runoob com
输入的数据为:runoob
可以看到 com 字符串并未输出,接下来我们看 nextLine。
使用 nextLine 方法:
import java.util.Scanner;
public class ScannerDemo {
public static void main(String[] args) {
Scanner scan = new Scanner(System.in);
// 从键盘接收数据
// nextLine方式接收字符串
System.out.println("nextLine方式接收:");
// 判断是否还有输入
if (scan.hasNextLine()) {
String str2 = scan.nextLine();
System.out.println("输入的数据为:" + str2);
}
scan.close();
}
}
执行以上程序输出结果为:
$ javac ScannerDemo.java
$ java ScannerDemo
nextLine方式接收:
runoob com
输入的数据为:runoob com
可以看到 com 字符串输出。
next() 与 nextLine() 区别
next():
- 1、一定要读取到有效字符后才可以结束输入。
- 2、对输入有效字符之前遇到的空白,next() 方法会自动将其去掉。
- 3、只有输入有效字符后才将其后面输入的空白作为分隔符或者结束符。
- next() 不能得到带有空格的字符串。
nextLine():
- 1、以Enter为结束符,也就是说 nextLine()方法返回的是输入回车之前的所有字符。
- 2、可以获得空白。
如果要输入 int 或 float 类型的数据,在 Scanner 类中也有支持,但是在输入之前最好先使用 hasNextXxx() 方法进行验证,再使用 nextXxx() 来读取:
import java.util.Scanner;
public class ScannerDemo {
public static void main(String[] args) {
Scanner scan = new Scanner(System.in);
// 从键盘接收数据
int i = 0;
float f = 0.0f;
System.out.print("输入整数:");
if (scan.hasNextInt()) {
// 判断输入的是否是整数
i = scan.nextInt();
// 接收整数
System.out.println("整数数据:" + i);
} else {
// 输入错误的信息
System.out.println("输入的不是整数!");
}
System.out.print("输入小数:");
if (scan.hasNextFloat()) {
// 判断输入的是否是小数
f = scan.nextFloat();
// 接收小数
System.out.println("小数数据:" + f);
} else {
// 输入错误的信息
System.out.println("输入的不是小数!");
}
scan.close();
}
}
执行以上程序输出结果为:
$ javac ScannerDemo.java
$ java ScannerDemo
输入整数:12
整数数据:12
输入小数:1.2
小数数据:1.2
hasNext、hasNextLine、next、nextLine等此类
hasNext和hasNextLine的区别
二者都是用于判断“有无键盘输入”的,有则返回true,没有则阻塞!一定记住是阻塞而不是返回false,很多人都说是返回false,但你查源码会发现是不会返回false的,他会让你一直阻塞在判断阶段,二者只是在细节上有不同
hasNext()
方法会判断接下来是否有非空字符.如果有,则返回true,没有则阻塞。例如一直敲回车相当于一直判断为空字符,但是不会返回false,而是一直阻塞在判断阶段,直到你输入了非空字符hasNextLine()
方法会根据行匹配模式去判断接下来是否有一行(包括空行),如果有,则返回true。这个没什么特别的,只要是你敲了回车那都是true并且不会阻塞
首先,在看用法和解释之前,有以下几个点必须时刻牢记
- next方法不能录入空格,在特定情况下会把空格当作回车,
nextLine
方法可以识录入空格hasNext
和hasNextLine
的返回值都是boolean
类型,但只有可能返回true,不可能返回false,并且都默认以回车键为结束(hasNext
可以设置为任意符号为结束键,不在本文研究范围之内)hasNext、next
不能直接识别裸回车,而hasNextLine
和nextLine
都可以直接识别裸回车。换句话讲:对于不输入符号而直接裸敲一个回车的操作,只有后两个能识别
hasNext
、hasNextLine
在返回一个boolean
类型结果true的同时,会在堆空间中开辟一块专门用于存放刚刚输入的字符串,用于下次next
或者nextLine
:即下次next
或者nextLine
不需要再从键盘输入,相当于系统自动把刚刚输入的字符串再原封不动的输入了一遍。同时这个存储寿命=调用对象的寿命- 对于
hasNext
来说,每次敲击回车都相当于在堆空间中开辟一行,敲几次回车就会直接给后续next
、nextLine
方法赋值几次hasNext
是线程阻塞的,对于hasNext
来说,如果一直不输入字符,反而一直敲回车的话,整个线程会卡在这个输入的地方,直到有字符输入
总结
hasNext、hasNextLine
不可能返回false,只有true和阻塞两种结果
hasNext、hasNextLine
会判断有无输入,并且hasNext
一直敲回车而不输入字符会导致线程阻塞。如果直接连续敲回车,那么hasNextLine
会判断为true。
hasNext、hasNextLine
也有存储功能,从“开始输入”到“判断结束”的过程中的所有输入都将储存,直到之后遇到需要键盘输入的next、nextLine
,这些存储的字符串和空格会自动填写给后面的next、nextLine
。而空格再next
和nextLine
上有不同的表现
查看API还有很多同类型的不同方法,按照这个思路可以一通百通
具体可参考原文链接:https://blog.csdn.net/m0_56079407/article/details/120576881
数据
基本数据类型
数值型
整数**(byte(
-2^7,2^7-1
)(1字节=8bit
)、short(2字节
)、int(4字节
)、long(8字节
))**声明long类型,后需加字母 ‘l’ 或 ‘L’ 。浮点**(float(
精度7位有效数字
)、double(16位有效数字
))**声明float常量,后需加 ‘f’ 或 ‘F’字符型(char)包括’中’、‘a’、‘9’、‘\n’、‘\’ ’ …
布尔型(boolean)和C语言不同,Java的0不能等同于false,1也不等同于ture。故不能使用0或1参与判断
boolean b1 = true;
boolean b2 = false;
引用数据类型(引用类型都可以用NULL作为值)
类(class)
字符串(String)
String s0 = “hello”;
String s1 = “hello”;
在内存中只会存在一个"hello",二者指向的是"hello"的内存地址。
字符串还可以用’+'拼接
String str = “he”+“ll”+“o”;
接口(interface)
数组( [ ] )
基本数据类型转换
隐式类型转换
小的类型在计算中会自动转换成大的类型进行转换。
char、byte、short
之间不会相互转换,三者计算式首先转化成int类型。
且byte、short
只要参与计算则自动转换成int类型
byte
char > int > long > float > double
short
char类型的数据在与数字或字符进行数学运算时,它是先转换成ASCII码的值然后再参与运算。也就是会转换成int类型。
而与String字符串进行运算,其他类型数据会被先转换成字符串类型。
System.out.println("5+5="+5+5);//等于:5+5=55,类似于"5+5="+"5"+"5"
System.out.println('*');//等于:*
System.out.println('*'+'\t'+'*');//等于:93
System.out.println("*"+'\t'+'*');//等于:* *
强制类型转换
自动类型转换的逆过程,将大的强制转换成小的数据类型,使用时加强制转换符( )
,可能会造成精度降低或溢出,使用时请额外注意。
这里强调,在Java中,字符串不属于基本数据类型而是被看作为对象。
因此,字符串不能直接转换为其他数据类型,但借用基本类型对应的包装类可以实现将字符串转换成别的基本类型。
String a = "43";
int i = Integer.parseInt(a);
boolean
类型不可以转化成其他数据类型
浮点数
浮点数运算和整数运算相比,只能进行加减乘除这些数值计算,不能做位运算和移位运算。
浮点数常量有两种表现形式:
十进制
如:5.12、23.0f、.457(必须要有小数点)
科学计数法
如:5.12e2、346E2、100E-2
精确度
由于浮点数存在运算误差,所以比较两个浮点数是否相等常常会出现错误的结果。正确的比较方法是判断两个浮点数之差的绝对值是否小于一个很小的数:
// 比较x和y是否相等,先计算其差的绝对值:
double r = Math.abs(x - y);
// 再判断绝对值是否足够小:
if (r < 0.00001) {
// 可以认为相等
} else {
// 不相等
}
浮点数的类型转换
整数于浮点数进行运算自动转化为浮点数。
但需要特别注意,在一个复杂的四则运算中,两个整数的运算不会出现自动提升的情况。例如:
double d = 1.2 + 24 / 5; // 5.2
计算结果为5.2
,原因是编译器计算24 / 5
这个子表达式时,按两个整数进行运算,结果仍为整数4
。
溢出
整数运算在除数为0
时会报错,而浮点数运算在除数为0
时,不会报错,但会返回几个特殊值:
NaN
表示Not a NumberInfinity
表示无穷大-Infinity
表示负无穷大
例如:
double d1 = 0.0 / 0; // NaNdouble
d2 = 1.0 / 0; // Infinity
double d3 = -1.0 / 0; // -Infinity
字符与字符串
字符
字符类型char
是基本数据类型,它是character
的缩写。一个char
保存一个Unicode字符:
char c1 = 'A';
char c2 = '中';
因为Java在内存中使用Unicode
字符集表示字符,由于Java使用的 UTF-16
编码方案采用不同长度的编码表示所有的Unicode
代码点。16
位的编码单元,即两个字节,所以一个char
占用2
个字节。
Unicode
代码点的合法范围是U+0000到U+10FFFF
。要得到一个字符的Unicode
编码,只需将char
类型直接赋值给int
类型:
int n1 = 'A'; // 字母“A”的Unicodde编码是65
int n2 = '中'; // 20013
也可以直接用转义字符\u
+Unicode编码来表示一个字符:
// 注意是十六进制:
char c3 = '\u0041'; // 'A',因为十六进制0041 = 十进制65
char c4 = '\u4e2d'; // '中',因为十六进制4e2d = 十进制20013
Java使用 UTF-16
编码方案来表示char
类型的字符,请注意,UTF-16
编码对大部分常见字符来说是足够的,但对于某些特殊字符(如 Emoji
表情符号)可能需要多个char来表示。
字符串
和char
类型不同,字符串类型String
是引用类型(也就是说String本身也是一个class
),Java编译器对String
有特殊处理,因此我们可以用双引号" "
表示字符串。一个字符串可以存储0个到任意个字符:
String s = ""; // 空字符串,包含0个字符
String s3 = "中文 ABC"; // 包含6个字符,其中有一个空格
实际上字符串在String
内部是通过一个char[]
数组表示的,因此,按下面的写法也是可以的:
String s2 = new String(new char[] {
'H', 'e', 'l', 'l', 'o', '!'});
Java字符串的一个重要特点就是字符串不可变。这种不可变性也是通过内部的private final char[]
字段,以及没有任何修改char[]
的方法实现的。
字符串使用双引号" "
表示开始和结束,如果字符串本身恰好包含一个"
字符时,我们需要借助转义字符\
:
String s = "abc\"xyz"; // abc"xyz
常见的转义字符包括:
\"
表示字符"
\'
表示字符'
\\
表示字符\
\n
表示换行符
\r
表示回车符
\t
表示Tab
\u####
表示一个Unicode编码的字符
字符串连接
Java可以使用+
连接任意字符串和其他数据类型,这样极大地方便了字符串的处理。
任何基本数据类型与String
类型进行连接运算时(+)
,该类型将自动转化成字符串类型
String str = ""+1+2;
System.out.println(str);//输出:12
一些字符串类型运算的情况
String str1 = 4;//这个是错的,要加""
String str2 = 3.5f + "";//是对的,f表float类型
System.out.println(str2);//输出:3.5
System.out.println(3+4+"Hello");//输出:7Hello
System.out.println("Hello"+3+4);//输出:Hello34
System.out.println('a'+1+"Hello");//输出:98Hello
System.out.println("Hello"+'a'+1);//输出:Helloa1
String str3 = 1+3+5+"a"+2+6+9;
System.out.println(str3);//为:9a269
多行字符串
如果我们要表示多行字符串,使用+号连接会非常不方便:
String s = "first line \n"
+ "second line \n"
+ "end";
从Java 13开始,字符串可以用""" """
表示多行字符串(Text Blocks)了。举个例子:
String s = """
SELECT * FROM
users
WHERE id > 100
ORDER BY name DESC
""";
上述多行字符串实际上是5行,在最后一个DESC
后面还有一个\n
。如果我们不想在字符串末尾加一个\n
,就需要这么写:
String s = """
SELECT * FROM
users
WHERE id > 100
ORDER BY name DESC""";
还需要注意到,多行字符串前面共同的空格会被去掉,即:
String s = """
...........SELECT * FROM
........... users
...........WHERE id > 100
...........ORDER BY name DESC
...........""";
用.
标注的空格都会被去掉。
如果多行字符串的排版不规则,那么,去掉的空格就会变成这样:
String s = """
......... SELECT * FROM
......... users
.........WHERE id > 100
......... ORDER BY name DESC
......... """;
总是以最短的行首空格为基准。
字符串索引charAt()
java中,charAt()方法用于返回指定索引处的字符。
索引范围从index = 0 到 length-1
。
public char charAt(int index);
例:
public class Demo{
public static void main(String[] args){
String s = "jixiao";
char what =s.charAt(5);//o
System.out.println(what);
}
}
null
引用类型的变量可以指向一个空值null
,它表示不存在,即该变量不指向任何对象。例如:
String s1 = null; // s1是nullString
s2 = s1; // s2也是nullString
s3 = ""; // s3指向空字符串,不是null
注意要区分空值null
和空字符串""
,空字符串是一个有效的字符串对象,它不等于null
。
运算符
算数运算符
运算符 | 运算 | |
---|---|---|
+ | 正号/加 | a=-3;b=+a;//b=-3 |
- | 负号或减 | |
* | 乘 | |
/ | 除 | 7/2=3 |
% | 取模 | 7%5=2 |
++ | 自增(前),先运算后取值; 自增(后),相反 |
a=2; b=++a;//b=3 c=a++;//=2 |
– | 自减,同上 | |
+ | 字符串连接 | “He”+“llo”=“Hello” |
算数运算符的特别注意项
负数与%相关
-
取余采用向0取整,即向 0 方向取最接近精确值的整数
-
取模采用向负无穷方向取整
在C/C++, C#, JAVA, PHP这几门主流语言中,'%'运算符都是做取余运算,而在python中的'%'是做取模运算。
简单理解,在Java中:
模数为负时,负号可忽略不计,如:5%(-3) = 2
但被模数为负数则不可忽略。如:-5%3 = -2
异号情况下:使用公式:被除数 -(除数*商)**=** 余 或 模
取余:5/-3
商约等于-1.66
取余,商往0
靠,就应该是 -1
。
5-(-3)\*(-1) = 2
取模:商往负无穷,就应该是-2
。
5-(-3)\*(-2) = -1
同号情况下:
都为正,则为正;都为负,则为负。
此外,取模运算的额结果不一定总是整数,可能受到浮点数精度、负数处理以及数据类型范围的限制。在进行取模运算时,需要考虑这些因素,以避免错误的结果。
参考:
赋值运算符
= 赋值
== 比较
扩展运算符
-=、+=、*=、/=、%=
字符串同样可以做+=
的操作,就是字符串的拼接。
String str = "he";
str += "llo";
System.out.println(str);//等于hello
关于涉及类型转换的注意事项
当short、char及byte
类型用于计算时一般会先转换成默认的int
类型。无法用原来的定义的变量接收,需要使用强制类型转换。
但使用扩展赋值运算符时,变量在参与运算时自动把结果强制类型转换为当前变量类型。(不只局限于short、char
和byte
)
所以,
short s = 2;
s = (short)(s + 3);//s=s+3会报错
s += 3;//等于short类型的5
int i = 1;
i *= 0.1;//i等于0,等同于i=(int)(i*0.1)
逻辑运算符(注意双与及双或)
运算符 | 用法 |
---|---|
& | 与 (两者都对则为true) |
| | 或(两者都不对则为false) |
! | 非(取反,只针对一个对象) |
^ | 异或(二者不同则为true) |
&& | 短路与(先考虑第一个,第一个就能确定了就不用看第二个了) |
|| | 短路或 |
int a=0;
int b=1;
System.out.println(a!=0&&++b==2);//输出false
System.out.println(b);//b=1
位运算符
运算符 | 运算 | 范例 |
---|---|---|
<< | 左移 | 3 << 2 = 12 相当于 3*2*2=12 , m << n --> m * 2^n |
>> | 右移 | 3 >> 1 = 1 --> 3/2=1 , m >> n --> m / 2^n |
>>> | 无符号右移 | 3 >>> 1 = 1 --> 3/2=1 , 正数的 >>> 与 >> 一致 |
& | 与 | 6 & 3 = 2 |
| | 或 | 6 | 3 = 7 |
^ | 异或运算 | 6 ^ 3 = 5 |
~ | 按位取反 | ~6 = -7;0=1;1=0 |
运算符 | 总结 |
---|---|
<< | 空位补 0 ,被移除的高位丢弃,空缺位补 0 。 |
>> | 被移位的二进制最高位是 0 ,右移后,空缺位补 0 ; 最高位是 1 ,空缺位补 1 。 |
>>> | 被移位二进制最高位无论是 0 或者是 1 ,空缺位都用 0 补 |
& | 二进制位进行 & 运算,只有 1&1 时结果是 1 ,否则是 0; |
| | 二进制位进行 | 运算,只有 0 | 0时结果是 0 ,否则是 1; |
^ | 相同二进制位进行 ^ 运算,结果是 0 ; 1^1=0 , 0^0=0 不相同二进制位 ^ 运算结果是 1 。 1^0=1 , 0^1=1 |
~ | 正数取反,各二进制码按补码各位取反 负数取反,各二进制码按补码各位取反 |
三元(三目)运算符
( 条件表达式 )? 表达式 1 :表达式 2 ;
优先级
程序流程控制
顺序结构
按照代码的顺序流程执行
分支结构
if(){
}
else if(){
}
else{
}
switch(){
case 常量:break;
case 常量:
default:
}
switch
( 表达式 ) 中表达式的返回值必须是下述几种类型之一:
byte , short , char , int ,枚举, String ;
case
子句中的值必须是常量(相对于变量的概念),且所有case
子句中的值应是不同的;
default
子句是可写可不写的,当没有匹配的case
时,执行 default
switch和if语句的对比
if
和switch
语句很像,具体什么场景下,应用哪个语句呢?
如果判断的具体数值不多,而且符合
byte 、 short 、 int 、 char
这四种类型。虽然两个语句都可以使用,建议使用swtich
语句。因为效率稍高。
其他情况:对区间判断,对结果为
boolean
类型判断,使用if
,if
的使用范围更广。
循环结构
for循环及for each
同C语言类似
此外,Java SE5引入了一种更加简洁的 for 语法用于数组和容器,即 for each
。
使用 for each
循环遍历数组和集合元素时,无须获得数组和集合长度,无须根据索引来访问数组元素和集合元素,for each
循环自动遍历数组和集合的每个元素。
foreach 循环和普通循环不同的是:,它无需循环条件,无需循环迭代语句,这些都由系统来完成,for each 循环自动迭代数组的每个元素,当每个元素都被迭代一次后,for each
循环自动结束。
for each 循环的语法格式如下:
for (type var : array / collection)//array 数组 或者 collection 容器/集合
{
// var 自动迭代访问每个元素
}
如:
public static void main(String[] args){
String[] books = {
"Hello","World","!"};
for(String b : books){
//相当于for(int i=0;i<books.lenght;i++){b=books[i];}
System.out.println(b);
//先输出Hello,然后输出World,然后输出!
}
}//b相当于一个临时变量,系统会把数组元素依次赋给b
使用for each
循环迭代数组元素时,改变这个循环变量并不能改变数组的值,但改变循环变量的值将会影响循环内的操作,因此不要对for each
的循环变量进行赋值。
while循环
同c语言
do/while循环
同c语言
特殊流程控制语句
break:结束本层循环
continue:结束当次循环,进入下一次循环
return:结束整个方法
数组
定义方式
type var[];
type[] var;
初始化
// 1. 定义一个整数数组,给它分配可以放下5个元素的空间
int[] numbers = new int[5];//可以是变量
// 2. 定义一个字符串数组,并初始化元素
String[] fruits = {
"Apple", "Banana", "Orange"};
//or
String[