Post

Java 语言基础

Java 的发展历程

Java 来自 sun,aka 斯坦福大学网络。

时间描述
1991 ~ 1995Sun 为了占领智能费电子产品市场, 由 james gosling 负责该项目,来开发 Oak 语言
1995将 Oak 改名为 Java
1996JDK1.0
1997JDK1.1
1998JDK1.2,将该版本命名为 J2SDK,将 Java 更名为 Java 2
1999将 java 分为三大块:J2SE(Java 标准版)、J2EE (Java 企业版)、J2ME(Java 微型版本)
2000J2SE1.3
2002J2SE1.4
2004此时不再叫 J2SE1.5,叫 5.0
20052005 Java 10 周年,将 J2SE 改为 JAVASE、 将 J2EE 改为 JAVAEE、将 J2ME 改为 JAVA
2006JDK6
2009Oracle 收购 SUN 公司,BEA 公司(JavaEE 服务器 Weblogic)。
2011JDK7 发布,提供新的 G1 收集器、加强对非 Java 语言的调用支持、可并行的类加载架构等。
2014JDK8
2017JDK9
2018JDK10,主要对内部进行重构,统一源仓库,统一垃圾收集器接口,统一即时编译器接口
2018JDK11,这也是一个 LTS(long-term support)版本,包含 17 个 JEP,同时被引入的还有 ZGC 这样革命性的垃圾收集器。
2019JDK12,RedHat 接手了 OpenJDK 8 和 OpenJDk 11 的管理和维护权。
2019JDK13
2020JDK14
2020JDK15
2021JDK16
2021JDK17,JDK 11 之后的下一个 LTS 版本。

Identifier - 标识符

标识符可以标识类名,接口名,变量名,方法名

  • 由数字,字母,下划线和美元符号组成,其他不行
  • 不能以数字开头
  • 关键字不能作为标识符
  • 标识符区分大小写
  • 标识符理论上没有长度限制
合法标识符不合法标识符
_123Test123Test
HelloWorldHello-World
HelloWorldHelloWorld#
public1public
HelloWordHello World

Camel Case - 驼峰命名法

  • 类名称的第一个字符大写,接下来遇到新词首字母大写
  • 方法名称首字母小写,接下来遇到新词首字母大写
  • 变量也是首字母小写,接下来遇到新词首字母大写

Keywords - 关键字

Keywords   
abstractassertbooleanbreak
bytecasecatchchar
classconstcontinuedefault
dodoubleelseenum
extendsfinalfinallyfloat
forgotoifimplements
importinstanceofintinterface
longnativenewpackage
privateprotectedpublicreturn
shortstaticstrictfpsuper
switchsynchronizedthisthrow
throwstransienttryvoid
volatilewhile  

Variables - 变量

变量是 java 中的一个最基本的单元,也就是内存中的一块区域。

四个基本属性:

  • 变量名: 合法的标识符
  • 变量的数据类型: 可以是基本类型和引用类型(必须包含类型)
  • 存储单元: 存储单元大小是由数据类型决定的,如:int 为 4 个字节 32 位
  • 变量值: 在存储单元中放的就是变量值(如果是基本类型放的就是具体值,如果是引用类型放的是内存地址,如果 null,表示不指向任何对象)

Type - Java 数据类型

在计算机内部,所有信息都采用二进制表示,每个二进制由 0 和 1 两种状态,一个字节有 8 位,也就是由 8 个 0 或 1 构成。

short 类型的 6 在计算机中是如何存储的?short 是两个字节,那么 short 6 的二进制为: 00000000 00000110

int 类型的 6 在计算机中存储为 32 位: 00000000 00000000 00000000 00000110

char 类型可以存放一个汉字,java 中的 char 使用 utf-16 编码。

1
2
        char c = '中';
        System.out.println(c); // 中

基本类型

数据类型关键字内存占用取值范围 
字节型byte1 个字节-128127
短整型short2 个字节-3276832767
整型int (default)4 个字节-2 的 31 次方2 的 31 次方-1
长整型long8 个字节-2 的 63 次方2 的 63 次方-1
单精度浮点数float4 个字节1.4013E-453.4028E+38
双精度浮点数double8 个字节4.9E-3241.7977E+308
字符型char2 个字节065535
布尔类型boolean1 个字节TRUEFALSE

引用数据类型

  • 数组
  • 接口

Literals - 字面值

  1. 什么是字面值?

    一眼看上去就知道是多少的数据,就是字面值。

  2. 字面值本质:

    • 字面值是有数据类型的:
      • 整型 100
      • 浮点型 3.14
      • 布尔型 true/false
      • 字符型 ‘中’
      • 字符串型 “ABC”
      • 在内存中占用空间
      • 字面值就是内存中的一块空间,这块空间有类型,有值
      • 只有字面值内存无法得到重复利用
    • java 语言中所有的字符都采用单引号括起来
    • java 语言中所有的字符串都采用双引号括起来

基本类型的转换

  • 在 java 中基本类型可以相互转换,boolean 类型比较特殊不可以转换成其他类型
  • 转换分为默认转换和强制转换:
    • 默认转换:容量小的类型会默认转换为容量大的类型
      • byte–>short/char–>int–>long–>float–>double
      • byte、short、char 之间计算不会互相转换,首先先转换成 int
    • 强制转换:
      • 将容量大的类型转换成容量小的类型,需要进行强制转换
      • 只要不超出范围可以将整型值直接赋值给 byte,short,char
      • 在多种类型混合运算过程中,首先先将所有数据转换成容量最大的那种,再运算
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
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
  //出现错误,1000超出了byte的范围
  byte a = 1000;

  //正确,因为20没有超出byte范围
  byte a = 20;

  //正确,因为数值1000没有超出short类型的范围
  short b = 1000;

  //正确,因为默认就是int,并且没有超出int范围
  int c = 1000;

  //正确,可以自动转换
  long d = c;

  //错误,出现精度丢失问题,大类型-->>小类型会出现问题
  int e = d;

  //将long强制转换成int类型
  //因为值1000,没有超出int范围,所以转换是正确的
  int e = (int)d;

  //因为java中的运算会会转成最大类型
  //而10和3默认为int,所以运算后的最大类型也是int
  int f = 10/3;

  //声明10为long类型
  long g = 10;

  //出现错误,多个数值在运算过程中,会转换成容量最大的类型
  //以下示例最大的类型为double,而h为int,所以就会出现大类型(long)到小类型(int)的转换,将会出现精度丢失问题
  int h = g/3;

  //可以强制转换,因为运算结果没有超出int范围
  int h = (int)g/3;

  //可以采用long类型来接收运算结果
  long h = g/3;

  //出现精度损失问题,以下问题主要是优先级的问题
  //将g转换成int,然后又将int类型的g转换成byte,最后byte类型的g和3运算,那么它的运算结果类型就是int,所以int赋值给byte就出现了精度损失问题
  byte h = (byte)(int)g/3;
  //正确
  byte h = (byte)(int)(g/3);
  //不能转换,还有因为优先级的问题
  byte h = (byte)g/3;
  //可以转换,因为运算结果没有超出byte范围
  byte h = (byte)(g/3);
  //可以转换,因为运算结果没有超出short范围
  short h = (short)(g/3);

  short i = 10; byte j = 5;
  //错误,short和byte运算,首先会转换成int再运算
  //所以运算结果为int,int赋值给short就会出现精度丢失问题
  short k = i + j;

  //可以将运算结果强制转换成short
  short k = (short)(i + j);

  //因为运算结果为int,所以可以采用int类型接收
  int k =i + j;

  char l = 'a';
  System. out.println(l);

  //输出结果为 97,也就是a的 ASCII 值
  System.out.println((byte)l);

  int m = l + 100;
  //输出结构为197,取得a的ASCII码值,让后与100进行相加运算
  System.out.println(m);

Operator - 运算符

算术运算符

运算符运算
+加法运算
-减法运算
*乘法运算
/除法运算
%取模运算,两数字相除取余数
++,- -自增自减运算

i++ : 先赋值再运算

1
2
3
4
5
6
  int a = 1;
  int b = a++;

  // ++在变量的后面,先把值赋值给b,然后a再加(也就是先赋值再自加),所以就输出了a=2 b=1
  System.out.println("a=" + a); // 2
  System.out.println("b=" + b); // 1

++i : 先运算再赋值

1
2
3
4
5
6
  int a = 1;
  int b = ++a;

  // 输出结果为a=2 b=2,如果++在变量的前面,是先自加在赋值
  System.out.println("a=" + a); // 2
  System.out.println("b=" + b); // 2

比较运算符

运算符运算
>大于
<小于
>=大于等于
<=小于等于
==等于
!=不等于

逻辑运算符

运算符运算
!取反
&非简洁与,A,B 都为真,结果为真,有一个为假,结果为假
|非简洁或,A,B 有一个为真,结果为真,都为假,结果为假
^异或,A,B 不同真假时结果为真,同真同假,结果为假
&&简洁与,A,B 都为真,结果为真,A 为假,则不再判断直接为假
||简洁或,A,B 都为假,结果为假,A 为真,则不再判断直接为真

赋值运算符

运算符运算
=赋值
+=加等于
-=减等于
*=乘等于
/=除等于
%=取模等

三元运算符

运算符运算
x?a:b判断 x,x 为真,表达式值为 a,x 为假,表达式值为 b
1
2
3
4
5
  int a = 11;
  int b = a > 0 ? 1 : -1;
  System.out.println(b); // 1
  boolean c = a % 2 == 0 ? true : false;
  System.out.println(c); // false

Java 的加载与运行

编译时

.java源代码 -> Java 编译器 -> .class字节码

运行时

类加载器 -> 字节码校验器 -> 解释器 / JIT 代码生成器 -> 硬件

public class 和 class 的区别

  • 一个.java 源文件中可以定义多个 class
  • 并且一个 class 会生成一个.class 文件
  • 采用 public class 来声明 class,那么文件名必须和类名完全一致(包括大小写)
  • 如果要定义 public 的 class,那么这个 public 的 class 也只能有一个

Conditional Statements - 控制语句

Java 控制语句可以分为 7 种:

控制条件结构语句

  • if、if else
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
public class test {
    public static void main(String[] args) {

        int age = 3;

        if (age > 0 && age <= 5) {
            System.out.println("幼儿");
        } else if (age > 5 && age <= 10) {
            System.out.println("儿童");
        } else if (age > 10 && age <= 18) {
            System.out.println("少年");
        } else {
            System.out.println("青年");
        }
    }
}
  • switch

表达式的值只能为:char、byte、short、int 类型,boolean、long、float、double 都是非法的。 break 语句可以省略,但会出现 switch 穿透。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
public class test {
    public static void main(String[] args) {

        char c = 'd';
        switch (c) {
            case 'a':
                System.out.println("优秀");
                break;//注意 break case 'b':
            System.out.println("良好");
            break;
            case 'c':
                System.out.println("一般");
                break;
            default:
                System.out.println("很差");
        }
        System.out.println("switch 执行结束!");
    }
}

控制循环结构语句

  • for
1
2
3
        for (int i = 1; i <= 10; i++) {
            System.out.println(i);
        }
  • while
1
2
3
4
5
6
        int i = 1;
        //注意死循环问题
        while (i <= 10) {
            System.out.println(i);
            i++;
        }
  • do while

do while 与 while 非常相似,不同点在于 do while 先执行循环体,也就是说不管条件符不符合,循环体至少执行一次

1
2
3
4
5
        int i = 1;
        do {
            System.out.println(i);
            i++;
        } while (i <= 10); //注意分号

改变控制语句顺序

  • break
1
2
3
4
5
6
7
8
9
10
11
    public static void main(String[] args) {
        for (int i = 1; i <= 5; i++) {
            System.out.println("i===================" + i);
            for (int j = 1; j <= 10; j++) {
                System.out.println(j);
                if (j == 5) {
                    break;
                }
            } //以上 break 会到此为止
        } //以上 break 不会跳到这里
    }
  • continue

continue 只能用在循环语句中,表示在循环中执行到 continue 时,自动结束本次循环,然后判断条件,决定是否进行下一次循环。

1
2
3
4
5
6
7
8
9
10
        for (int i = 1; i <= 100; i++) {

            if (i % 2 != 0) {
                System.out.println(i);
            }
            if (i % 2 == 0) {
                continue; //继续下一次循环 }
                System.out.println(i);
            }
        }

Method - 方法

什么是方法?

  • 方法是可以重复调用的代码块。
  • 方法在调用的时候,才会在内存分配空间。
  • 分配空间指在栈中分配空间(JVM 在内存中有一块内存是栈(stack)内存)。
  • 方法调用叫压栈。
  • 方法结束叫弹栈。

语法:

[方法修饰列表] 返回值类型 方法名(方法参数列表){ 方法体 }

  • 方法修饰列表 - Modifier

    可选,方法的修饰符可以包括:

    public protected private abstract static final synchronized

    其中 public protected private 不能同时存在。

  • 返回值类型 - Return Type

    如果没有返回值使用 void 关键字。

    如果存在返回值可以是基本类型和引用类型, 如果存在返回值,使用 return 语句。

    Return 语句后面不能再执行语句。

  • 方法名 - Method Name 任意合法的标识符

  • 方法参数列表 - Parameters/Arguments

    参数列表可以多个,如 method(int a, int b)

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
    public static void main(String[] args) {
        String s = method1(1);
        System.out.println(s);
    }

    public static String method1(int c) {
        return switch (c) {
            case 1 -> {
                System.out.println("优秀");
                yield "优";
            }
            case 2 -> {
                System.out.println("良好");
                yield "良好";
            }
            case 3 -> {
                System.out.println("一般");
                yield "一般";
            }
            default -> {
                System.out.println("很差");
                yield "很差";
            }
        };
    }

Overload - 方法重载

重载的条件

  • 方法名相同。
  • 方法的参数类型,个数,顺序至少有一个不同。
  • 方法的返回类型可以不同(不依靠返回类型来区分重载)。
  • 方法的修饰符可以不同,因为方法重载和修饰符没有任何关系。
  • 方法重载只出现在同一个类中。
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
    public static void main(String[] args) {

        int retInt = sum(10, 20);
        System.out.println(retInt);
        float retFloat = sum(1.5f, 2.5f);
        System.out.println(retFloat);
        double retDouble = sum(2.2, 3.2);
        System.out.println(retDouble);

    }

    //对int求和
    public static int sum(int v1, int v2) {
        return v1 + v2;
    }

    //对float求和
    public static float sum(float v1, float v2) {
        return v1 + v2;
    }

    //对double求和
    public static double sum(double v1, double v2) {
        return v1 + v2;
    }

方法递归

递归:指方法调用自身。

1
2
3
4
5
6
7
8
9
10
11
12
13
    public static void main(String[] args) {
        int retValue = method1(5);
        System.out.println(retValue);
    }

    //采用递归求和
    public static int method1(int n) {
        if (n == 1) {
            return 1;
        } else { //递归调用,调用自身
            return n + method1(n - 1);
        }
    }
This post is licensed under CC BY 4.0 by the author.

Trending Tags