Java基础语法

1.浮点型拓展

1.1浮点类型的舍入误差

浮点类型float, double的数据不适合在不容许舍入误差的领域

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
public class Main {
public static void main(String[] args) {
// 定义一个float类型变量f并赋值为0.1
float f = 0.1f;

// 定义一个double类型变量d并赋值为1.0除以10,即0.1
double d = 1.0 / 10;
System.out.println(f == d); // 输出:false,由于精度差异,比较结果为false
float d1 = 2131231231f;

// 定义一个float类型变量d2,将d1加1后的结果赋值给d2
float d2 = d1 + 1;
System.out.println("d1="+d1);
System.out.println("d2="+d2);
// 检查d1是否等于d2
if (d1 == d2) {
// 如果d1等于d2,输出"d1==d2"
System.out.println("d1==d2");
} else {
// 如果d1不等于d2,输出"d1!=d2"
System.out.println("d1!=d2");
}
}
}

out:
false
d1=2.13123123E9
d2=2.13123123E9
d1==d2

注:

1.浮点数一般都存在舍入误差,很多数字无法精确表示,其结果只能是接近,但不等于。

2.避免比较中使用浮点数

3.需要进行不产生舍入误差的精确数字计算,需要使用BigDecimal

1.2 BigDecimal类

BigDecimal类:用于高精度数值运算的类,它允许你精确地表示和执行各种数学运算,包括加法、减法、乘法、除法等,而不会丢失精度。

常用方法:

1.BigDecimal(String val):构造方法,将String类型转换成BigDecimal类型数据。

2.BigDecimal(double val):构造方法,将double类型转换成BigDecimal类型数据。

3.BigDecimal(int val):构造方法,将int类型转换成BigDecimal类型数据。

4.BigDecimal add(BigDecimal value):加法,求两个BigDecimal类型数据的和。

5.BigDecimal subtract(BigDecimal value):减法,求两个BigDecimal类型数据的差。

6.BigDecimal multiply(BigDecimal value):乘法,求两个BigDecimal类型数据的积。

7.BigDecimal divide(BigDecimal divisor):除法,求两个BigDecimal类型数据的商。

8.BigDecimal remainder(BigDecimal divisor):求余数,求BigDecimal类型数据除以divisor的余数。

9.BigDecimal max(BigDecimal value):最大数,求两个BigDecimal类型数据的最大值。

10.BigDecimal min(BigDecimal value):最小数,求两个BigDecimal类型数据的最小值。

11.BigDecimal abs():绝对值,求BigDecimal类型数据的绝对值。

12.BigDecimal negate():相反数,求BigDecimal类型数据的相反数。

13.BigDecimal compareTo():比较两个BigDecimal 对象的大小

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
import java.math.BigDecimal;
public class Main{
public static void main(String[] args)
{
BigDecimal num1 = new BigDecimal("0.1");//字符串带双引号被解释为确切的数值,若不加会存在一个微小的舍入误差
BigDecimal num2 = new BigDecimal("0.2");
BigDecimal num3=num1.multiply(new BigDecimal("2"));
BigDecimal sum = num1.add(num2);
System.out.println(num3.compareTo(num2));
System.out.println("sum="+sum);
}
}

out:
0
sum=0.3

2.Scanner对象

2.1 创建 Scanner 对象的基本语法:

Scanner s = new Scanner(System.in)

通过 Scanner 类的 next()nextLine() 方法获取输入的字符串

读取前一般需要使用 hasNext()hasNextLine() 判断是否还有输入的数据

2.2 next & nextLine

使用next方式接收一下输入的数据

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
import java.util.Scanner;
public class Main {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
while (scanner.hasNext()) {
String token = scanner.next();
System.out.println("Next Token: " + token);
}
scanner.close();
}
}

in:
hello world
out:
Next Token: hello
Next Token: world

使用nextLine方式接收一下输入的数据

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
import java.util.Scanner;
public class Main {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
while (scanner.hasNextLine()) {
String token = scanner.nextLine();
System.out.println("Next Token: " + token);
}
scanner.close();
}
}

in:
hello world
out:
Next Token: hello world

两者区别:

1.next() 不能得到带有空格的字符串,nextLine()可以获得空白。

2.nextLine():以Enter为结束符,也就是说 nextLine()方法返回的是输入回车之前的所有字符。

2.3 其他数据类型

如果要输入int、float等类型的数据,在 Scanner 类中也有支持,使用hasNextXxx() 方法、 nextXxx() 方法来读取

3.可变参数

可变参数的声明:

typeName... parameterName

注:一个方法中只能指定一个可变参数,它必须是方法的最后一个参数。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
public class Main{
public static void printMax(double... num){
if(num.length==0)
{
System.out.println("wrong!");
}
double result=0;
for (int i = 1; i < num.length; i++)
{
if (num[i] > result)
{ result = num[i]; }
}
System.out.println(num[num.length-1]);
};
public static void main(String args[])
{
printMax(1,2.3,5.0);
}
}

out:
5.0

4.Arrays 类

数组的工具类java.util.Arrays

常用功能:

4.1 打印数组

1
2
3
4
5
6
7
8
9
10
11
12
13
14
import java.util.Arrays;
public class Main{
public static void main(String args[])
{
int []num=new int[10];
for(int i=0;i<10;i++){
num[i]=i;
}
System.out.println(Arrays.toString(num));
}
}

out:
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]

4.2 数组排序

1
2
3
4
5
6
7
8
9
10
11
12
import java.util.Arrays;
public class Main{
public static void main(String args[])
{
int []num= {5,8,9,4,2};
Arrays.sort(num);
System.out.println(Arrays.toString(num));
}
}

out:
[2, 4, 5, 8, 9]

4.3 二分法查找

在进行此调用之前对数组进行排序(通 过sort方法等)

1
2
3
4
5
6
7
8
9
10
11
12
import java.util.Arrays;
public class Main{
public static void main(String args[])
{
int []num= {5,8,9,4,2};
Arrays.sort(num);
System.out.println("索引为:"+Arrays.binarySearch(num,4));
}
}

out:
索引为:1

4.4 将数组转换成List集合

1
2
int []num= {5,2,9,4,2,3,10};
List<int[]> list= Arrays.asList(num);

5.内部类

5.1 成员内部类

实例化内部类,首先需要实例化外部类,通过外部类去调用内部类

注:成员内部类中不能写静态属性和方法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
ppublic class Test {
public static void main(String[] args) {
//1.实例化外部类
Outer out=new Outer();
//2.通过外部类调用内部类
Outer.Inner inObject = out.new Inner();
inObject.In();
}
}
class Outer{
private int id;
public void out(){
System.out.println("外部类");
}
Outer()
{
id=10;
}
class Inner{
private int id;
public void In(){
System.out.println("内部类");
}
Inner(){
id=1;
System.out.println("外部:"+Outer.this.id);//Outer.this.显式调用外部类的变量
System.out.println("内部:"+id);//内部类中的变量会暂时将外部类的成员变量给隐藏
}
}
}

out:
外部:10
内部:1
内部类

5.2 静态内部类

静态内部类能够直接被外部类给实例化,不需要使用外部类对象

静态内部类只能访问自己属性和方法及外部类的静态属性和方法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
public class OuterClass {
private static int outerStaticField = 42;

// 静态内部类
public static class StaticInnerClass {
private int innerField;

public StaticInnerClass(int innerField) {
this.innerField = innerField;
}

public void printValues() {
System.out.println("Outer static field: " + outerStaticField);
System.out.println("Inner field: " + innerField);
}
}

public static void main(String[] args) {
// 创建静态内部类的实例
StaticInnerClass innerObj = new StaticInnerClass(10);
// 调用静态内部类的方法
innerObj.printValues();
}
}

5.3 局部内部类

局部内部类是在一个方法内部声明的一个类

在局部内部类中,如果要访问局部变量,那么该局部变量要用final修饰

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
public class LocalInnerClassTest {
// 外部类的成员变量
private String name;
private static int age;
LocalInnerClassTest(String name,int age)
{
this.name=name;
this.age=age;
}
// 外部类的实例方法
public void run() {}
// 外部类的静态方法
public static void go() {}
// 外部类的实例方法,包含局部内部类的定义
public void test() {
// 定义一个 final 局部变量
final String myname = "xxx";
// 定义局部内部类 LocalInnerClass
class LocalInnerClass {
// 局部内部类的成员变量
private String name;
// 局部内部类的方法,接受一个参数 name
public void test(String name) {
// 在方法中访问参数 name
System.out.println(name);
// 在局部内部类的成员方法中,可以使用 this 关键字访问局部内部类的成员变量
System.out.println(this.name);
// 在局部内部类中访问外部方法中的 final 变量 myname
System.out.println(myname);
// 在局部内部类中访问外部类的成员变量 name
System.out.println(LocalInnerClassTest.this.name);
// 在局部内部类中调用外部类的实例方法 run()
LocalInnerClassTest.this.run();
// 在局部内部类中调用外部类的静态方法 go()
LocalInnerClassTest.go();
}
}
// 创建局部内部类的实例
LocalInnerClass lic = new LocalInnerClass();
// 修改局部内部类的成员变量 name
lic.name = "tom";
// 调用局部内部类的方法 test(),传入参数 "test"
lic.test("test");
}
public static void main(String[] args) {
LocalInnerClassTest inner=new LocalInnerClassTest("wang",22);
inner.test();
}
}

out:
test
tom
xxx
wang

注:局部内部类不能通过外部类对象直接实例化,而是在方法中实例化出自己来,然后通过内部类对象调用自己类中的方法。

5.4 匿名内部类

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
// 定义一个接口
interface Greeting {
void greet();
}
public class AnonymousInnerClassExample {
public static void main(String[] args) {
// 使用匿名内部类创建实现 Greeting 接口并调用greet方法
new Greeting() {
@Override
public void greet() {
System.out.println("Hello, world!");
}
}.greet();
}
}