Java基础语法

之前学习java记得笔记,但是一直没怎么遇到java类的题,平时也不用java,所以经常忘记,今天想起来了再看一遍,再把之前写的笔记整理整理发到博客上。

Java预学习

Jave的优势

从互联网到企业平台,Java是应用最广泛的编程语言,原因在于:

  • Java是基于JVM虚拟机的跨平台语言,一次编写,到处运行;
  • Java程序易于编写,而且有内置垃圾收集,不必考虑内存管理;
  • Java虚拟机拥有工业级的稳定性和高度优化的性能,且经过了长时期的考验;
  • Java拥有最广泛的开源社区支持,各种高质量组件随时可用。

PS:JVM则是执行Java字节码的虚拟机。

Java语言常年霸占着三大市场:

  • 互联网和企业应用,这是Java EE的长期优势和市场地位;
  • 大数据平台,主要有Hadoop、Spark、Flink等,他们都是Java或Scala(一种运行于JVM的编程语言)开发的;
  • Android移动平台。

这意味着Java拥有最广泛的就业市场。

Java简介

  • Java最早是由SUN公司(已被Oracle收购)的詹姆斯·高斯林(高司令,人称Java之父)在上个世纪90年代初开发的一种编程语言,最初被命名为Oak,目标是针对小型家电设备的嵌入式应用,结果市场没啥反响。谁料到互联网的崛起,让Oak重新焕发了生机,于是SUN公司改造了Oak,在1995年以Java的名称正式发布,原因是Oak已经被人注册了,因此SUN注册了Java这个商标。随着互联网的高速发展,Java逐渐成为最重要的网络编程语言。

  • Java介于编译型语言和解释型语言之间编译型语言如C、C++,代码是直接编译成机器码执行,但是由于不同平台(x86、ARM等)CPU的指令集不同,编译的机器码也都不一样。解释型语言如Python、Ruby没有这个问题,可以由解释器直接加载源码然后运行,代价就是运行效率太低。而Java是将代码编译成一种“字节码”,它类似于抽象的CPU指令,然后,针对不同平台编写虚拟机,不同平台的虚拟机负责加载字节码并执行,这样就实现了“一次编写,到处运行”的效果。为了保证不同平台、不同公司开发的虚拟机能够正确执行Java字节码,SUN公司制定了一系列的Java虚拟机规范。

  • 随着Java的发展,SUN给Java又分出了三个不同版本:

    • Java SE: Standard Edition(标准版)
    • Java EE:Enterprise Edition (企业版)
    • Java ME:Micro Edition (微型版)

    三者区别:

    SE: 包含标准的JVM和标准库

    EE: 在SE的 基础上加上了大量的API和库

    ME:针对嵌入式设备的“瘦身版”,SE的标准库无法再ME上使用,ME的虚拟机也是“瘦身版”

    EE>SE>ME

Jdk

jdk(Java development kit):java开发工具包,支持Java程序开发的最小环境,即如果你要进行Java开发,你至少要在你的开发机器上安装JDK。

JDK = Java程序设计语言+Java虚拟机+Java API类库

JDK的一些可执行文件:

  • java:这个可执行程序其实就是JVM,运行Java程序,就是启动JVM,然后让JVM执行指定的编译后的代码;
  • javac:这是Java的编译器,它用于把Java源码文件(以.java后缀结尾)编译为Java字节码文件(以.class后缀结尾);
  • jar:用于把一组.class文件打包成一个.jar文件,便于发布;
  • javadoc:用于从Java源码中自动提取注释并生成文档;
  • jdb:Java调试器,用于开发阶段的运行调试。

Jre

jre(Java Runtime Environment):java运行环境,支持Java程序运行的标准环境,如果你不需要进行Java程序开发,只是要运行Java程序,例如运行Jar文件,那么你可以在你的运行机器上只安装JRE。

**JRE = Java虚拟机 +Java API类库中的Java SE API子集 **

jvm

jvm(Java Virtual Machine):java虚拟机 ,其主要任务为将字节码装载到内部,解释/编译为对应平台上的机器指令执行。

下载IDEA

IDEA 全称 IntelliJ IDEA,是java语言开发的集成环境(IDE),IntelliJ在业界被公认为最好的java开发工具之一。

Intellij IDEA 最突出的功能自然是调试(Debug),可以对Java代码,JavaScript,JQuery,Ajax等技术进行调试。

官方下载地址

根据官方提示即可正确安装。

第一个Java程序

  1. 打开刚刚下载好的IDEA
  2. 选择一个目录并打开文件夹
  3. 打开左上角File->Settings->Plugins,搜索Chinses选择并下载汉化插件,如下图:

image-20210803130548237

  1. 在左侧项目栏中右键点击项目文件夹->新建->新模块,如下图

image-20210803130757343

  1. 选择Java模块和模块SDK,如果电脑上有JDK则会自动写入,如果没有点击下载JDK

image-20210803130944509

  1. 点击下一步->输入项目名->点击完成
  2. 右键src文件夹->新建->Java类

image-20210803131146753

  1. 这里起名为"Hello",然后写入以下代码:
public class Hello {
    public static void main(String[] args){
        System.out.println("Hello World!");
    }
}
  1. 点击上方运行->运行,即可执行代码

代码解释

在一个Java程序中,你总能找到一个类似:

public class Hello {
    ...
}

的定义,这个定义被称为class(类),这里的类名是Hello,大小写敏感,class用来定义一个类,public表示这个类是公开的,publicclass都是Java的关键字,必须小写,Hello是类的名字,按照习惯,首字母H要大写。而花括号{}中间则是类的定义。

注意到类的定义中,我们定义了一个名为main的方法:

    public static void main(String[] args) {
        ...
    }

方法是可执行的代码块,一个方法除了方法名main,还有用()括起来的方法参数,这里的main方法有一个参数,参数类型是String[],参数名是argspublicstatic用来修饰方法,这里表示它是一个公开的静态方法,void是方法的返回类型,而花括号{}中间的就是方法的代码。

方法的代码每一行用;结束,这里只有一行代码,就是:

        System.out.println("Hello, world!");

它用来打印一个字符串到屏幕上。

Java规定,某个类定义的public static void main(String[] args)是Java程序的固定入口方法,因此,Java程序总是从main方法开始执行。注意到Java源码的缩进不是必须的,但是用缩进后,格式好看。

以上这些C语言是一样的!!!

Java代码的运行过程

Java源码本质上是一个文本文件,我们需要先用javacHello.java编译成字节码文件Hello.class,然后,用java命令执行这个字节码文件:

┌──────────────────┐
│    Hello.java    │<─── source code
└──────────────────┘
          │ compile
          ▼
┌──────────────────┐
│   Hello.class    │<─── byte code
└──────────────────┘
          │ execute
          ▼
┌──────────────────┐
│    Run on JVM    │
└──────────────────┘

因此,可执行文件javac是编译器,而可执行文件java就是虚拟机。

我们使用命令行的方式来感受一下它的执行过程吧

  1. 第一步,在保存Hello.java的目录下执行命令javac Hello.java
$ javac Hello.java

image-20210803132344946

如果源代码无误,上述命令不会有任何输出,而当前目录下会产生一个Hello.class文件:

  1. 执行Hello.class,使用命令java Hello
$ java Hello

image-20210803132553101

PS:给虚拟机传递的参数Hello是我们定义的类名,虚拟机自动查找对应的class文件并执行。

如果执行

$ java Hello.class

image-20210803132803575

或者还可以直接运行java Hello.java也是可以的:

$ java Hello.java Hello, world!

这是Java 11新增的一个功能,它可以直接运行一个单文件源码!

需要注意的是,在实际项目中,单个不依赖第三方库的Java源码是非常罕见的,所以,绝大多数情况下,我们无法直接运行一个Java源码文件,原因是它需要依赖其他的库。

Java程序基础

基本结构

我们先剖析一个完整的Java程序:

public class Hello {
    public static void main(String[] args){
        System.out.println("Hello World!");
        // 输出文本
    }
}

因为Java是面向对象的语言,一个程序的基本单位就是classclass是关键字,这里定义的class名字就是Hello

类名要求:

  • 类名必须以英文字母开头,后接字母,数字和下划线的组合
  • 习惯以大写字母开头

注意到public是访问修饰符,表示该class是公开的。

class内部,可以定义若干方法(method):

这里的方法名是main,返回值是void,表示没有任何返回值。

我们注意到public除了可以修饰class外,也可以修饰方法。而关键字static是另一个修饰符,它表示静态方法,,目前,我们只需要知道,Java入口程序规定的方法必须是静态方法,方法名必须为main,括号内的参数必须是String数组。

方法名也有命名规则,命名和class一样,但是首字母小写

在方法内部,语句才是真正的执行代码。Java的每一行语句必须以分号结束:

注释

Java有3种注释,第一种是单行注释,以双斜线开头,直到这一行的结尾结束:

// 这是注释...

而多行注释以/*星号开头,以*/结束,可以有多行:

/*
这是注释
blablabla...
这也是注释
*/

还有一种特殊的多行注释,以/**开头,以*/结束,如果有多行,每行通常以星号开头:

/**
 * 可以用来自动创建文档的注释
 * 
 */
public class Hello {
    public static void main(String[] args) {
        System.out.println("Hello, world!");
    }
}

这种特殊的多行注释需要写在类和方法的定义处,可以用于自动创建文档。

变量和数据类型

变量

在Java中,变量分为两种:基本类型的变量引用类型的变量

基本数据类型

基本数据类型是CPU可以直接进行运算的类型。Java定义了以下几种基本数据类型:

  • 整数类型:byte,short,int,long
  • 浮点数类型:float,double
  • 字符类型:char
  • 布尔类型:boolean

整型

public class Main {
    public static void main(String[] args) {
        int i = 2147483647;
        int i2 = -2147483648;
        int i3 = 2_000_000_000; // 加下划线更容易识别
        int i4 = 0xff0000; // 十六进制表示的16711680
        int i5 = 0b1000000000; // 二进制表示的512
        long l = 9000000000000000000L; // long型的结尾需要加L
    }
}

浮点型

float f1 = 3.14f;
float f2 = 3.14e38f; // 科学计数法表示的3.14x10^38
double d = 1.79e308;
double d2 = -1.79e308;
double d3 = 4.9e-324; // 科学计数法表示的4.9x10^-324

对于float类型,需要加上f后缀。

浮点数可表示的范围非常大,float类型可最大表示3.4x1038,而double类型可最大表示1.79x10308。

字符型

字符类型char表示一个字符。Java的char类型除了可表示标准的ASCII外,还可以表示一个Unicode字符:

char a = 'A';
char zh = '中';

注意char类型使用单引号',且仅有一个字符,要和双引号"的字符串类型区分开。

引用类型

除了上述基本类型的变量,剩下的都是引用类型。例如,引用类型最常用的就是String字符串:

String s = "hello";

引用类型的变量类似于C语言的指针,它内部存储一个“地址”,指向某个对象在内存的位置。

常量

定义变量的时候,如果加上final修饰符,这个变量就变成了常量:

final double PI = 3.14; // PI是一个常量

根据习惯,常量名通常全部大写。

var关键字

有些时候,类型的名字太长,写起来比较麻烦。例如:

StringBuilder sb = new StringBuilder();

这个时候,如果想省略变量类型,可以使用var关键字:

var sb = new StringBuilder();

编译器会根据赋值语句自动推断出变量sb的类型是StringBuilder。对编译器来说,语句:

var sb = new StringBuilder();

实际上会自动变成:

StringBuilder sb = new StringBuilder();

因此,使用var定义变量,仅仅是少写了变量类型而已。

数组类型

Java的数组有几个特点:

  • 数组所有元素初始化为默认值,整型都是0,浮点型是0.0,布尔型是false
  • 数组一旦创建后,大小就不可改变。
public class Main {
    public static void main(String[] args) {
        // 5位同学的成绩:
        int[] ns = new int[5];
        ns[0] = 68;
        ns[1] = 79;
        ns[2] = 91;
        ns[3] = 85;
        ns[4] = 62;
    }
}

数组是引用类型,在使用索引访问数组元素时,如果索引超出范围,运行时将报错

可以用数组变量.length获取数组大小。

也可以在定义数组时直接指定初始化的元素,这样就不必写出数组大小,而是由编译器自动推算数组大小。例如:

public class Main {
    public static void main(String[] args) {
        // 5位同学的成绩:
        int[] ns = new int[] { 68, 79, 91, 85, 62 };
        System.out.println(ns.length); // 编译器自动推算数组大小为5
    }
}

还可以进一步简写为:

int[] ns = { 68, 79, 91, 85, 62 };

运算

运算符

  • 算术运算符
  • 关系运算符
  • 位运算符
  • 逻辑运算符
  • 赋值运算符
  • 三元运算符
  • instanceof 运算符

运算规则

浮点数运算和整数运算相比,只能进行加减乘除这些数值计算,不能做位运算移位运算

如果参与运算的两个数其中一个是整型,那么整型可以自动提升到浮点型

溢出

整数运算在除数为0时会报错,而浮点数运算在除数为0时,不会报错,但会返回几个特殊值:

  • NaN表示Not a Number
  • Infinity表示无穷大
  • -Infinity表示负无穷大

短路运算

布尔运算的一个重要特点是短路运算。如果一个布尔运算的表达式能提前确定结果,则后续的计算不再执行,直接返回结果。

因为false && x的结果总是false,无论xtrue还是false,因此,与运算在确定第一个值为false后,不再继续计算,而是直接返回false

字符串连接

Java的编译器对字符串做了特殊照顾,可以使用+连接任意字符串和其他数据类型,这样极大地方便了字符串的处理。如果用+连接字符串和其他数据类型,会将其他数据类型先自动转型为字符串。

多行字符串

字符串可以用"""..."""表示多行字符串。

Java流程控制

输出

在前面的代码中,我们总是使用System.out.println()来向屏幕输出一些内容。

println是print line的缩写,表示输出并换行。因此,如果输出后不想换行,可以用print()

public class Hello {
    public static void main(String[] args){
        System.out.print("Hello,");
        System.out.print("World!\n");
        System.out.println("Hello,World!");
    }
}
>>>
Hello,World!
Hello,World!

格式化输出

果要把数据显示成我们期望的格式,就需要使用格式化输出的功能。格式化输出使用System.out.printf(),通过使用占位符%?printf()可以把后面的参数格式化成指定格式:

public class Hello {
    public static void main(String[] args){
        double a = 3.1415926;
        System.out.printf("%.2f", a);
    }
}
>>>
3.14

Java的格式化功能提供了多种占位符,可以把各种数据类型“格式化”成指定的字符串:

占位符 说明
%d 格式化输出整数
%x 格式化输出十六进制整数
%f 格式化输出浮点数
%e 格式化输出科学计数法表示的浮点数
%s 格式化字符串

注意,由于%表示占位符,因此,连续两个%%表示一个%字符本身。

输入

和输出相比,Java的输入就要复杂得多。

我们先看一个从控制台读取一个字符串和一个整数的例子:

import java.util.Scanner;

public class Main {
    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in); // 创建Scanner对象
        System.out.print("Input your name: "); // 打印提示
        String name = scanner.nextLine(); // 读取一行输入并获取字符串
        System.out.print("Input your age: "); // 打印提示
        int age = scanner.nextInt(); // 读取一行输入并获取整数
        System.out.printf("Hi, %s, you are %d\n", name, age); // 格式化输出
    }
}

首先,我们通过import语句导入java.util.Scannerimport是导入某个类的语句,必须放到Java源代码的开头,后面我们在Java的package中会详细讲解如何使用import

然后,创建Scanner对象并传入System.inSystem.out代表标准输出流,而System.in代表标准输入流。直接使用System.in读取用户输入虽然是可以的,但需要更复杂的代码,而通过Scanner就可以简化后续的代码。

有了Scanner对象后,要读取用户输入的字符串,使用scanner.nextLine(),要读取用户输入的整数,使用scanner.nextInt()Scanner会自动转换数据类型,因此不必手动转换。

要测试输入,我们不能在线运行它,因为输入必须从命令行读取,因此,需要走编译、执行的流程:

$ javac Main.java

这个程序编译时如果有警告,可以暂时忽略它,在后面学习IO的时候再详细解释。编译成功后,执行:

$ java Main
Input your name: Bob
Input your age: 12
Hi, Bob, you are 12

根据提示分别输入一个字符串和整数后,我们得到了格式化的输出。

if语句

if语句的基本语法是:

if (条件1) {
    // 条件1满足时执行
}else if(条件2){
    // 条件2满足时执行
}else{
    // 条件1,2不满足时执行
}

判断引用类型相等

在Java中,判断值类型的变量是否相等,可以使用==运算符。但是,判断引用类型的变量是否相等,==表示“引用是否相等”,或者说,是否指向同一个对象。例如,下面的两个String类型,它们的内容是相同的,但是,分别指向不同的对象,用==判断,结果为false

public class Main {
    public static void main(String[] args) {
        String s1 = "hello";
        String s2 = "HELLO".toLowerCase();
        System.out.println(s1);
        System.out.println(s2);
        if (s1 == s2) {
            System.out.println("s1 == s2");
        } else {
            System.out.println("s1 != s2");
        }
    }
}
>>>
hello
hello
s1 != s2

要判断引用类型的变量内容是否相等,必须使用equals()方法:

注意:执行语句s1.equals(s2)时,如果变量s1null,会报NullPointerException

switch语句

switch语句的基本语法是:

switch(option){
    case 1:
        // 执行语句
        break;
    case 2:
        // 执行语句
        break;
    case 3:
        // 执行语句
        break;
    default:
        // 执行语句
        break
};

从Java 12开始,switch语句升级为更简洁的表达式语法,使用类似模式匹配(Pattern Matching)的方法,保证只有一种路径会被执行,并且不需要break语句:

switch(option){
        case 1 -> {
            // 执行语句
        }
        case 2 -> // 单个语句;
        default -> {
            // 执行语句
        }
};

使用新的switch语法,不但不需要break,还可以直接返回值。

int opt = switch(option){
    case 1 -> 1;
    case 2 -> 2;
    default -> {
        int code = 1+1;
        yield code;	// switch语句返回值
    }
};

大多数时候,在switch表达式内部,我们会返回简单的值。

但是,如果需要复杂的语句,我们也可以写很多语句,放到{...}里,然后,用yield返回一个值作为switch语句的返回值:

while和do while语句

while语句的基本语法是:

while (条件表达式) {
    循环语句
}
// 继续执行后续代码

do while语句的基本语法是:

do {
    执行循环语句
} while (条件表达式);

for循环

for语句的基本语法是:

for (初始条件; 循环检测条件; 循环后更新计数器) {    // 执行语句}

for each 循环

Java还提供了另一种for each循环,它可以更简单地遍历数组:

public class Main {    public static void main(String[] args) {        int[] ns = { 1, 4, 9, 16, 25 };        for (int n : ns) {            System.out.println(n);        }    }}

除了数组外,for each循环能够遍历所有“可迭代”的数据类型,包括后面会介绍的ListMap等。

break和continue

在循环过程中,可以使用break语句跳出当前循环。

break语句通常都是配合if语句使用。要特别注意,break语句总是跳出自己所在的那一层循环。

break会跳出当前循环,也就是整个循环都不会执行了。而continue则是提前结束本次循环,直接继续执行下次循环。

Java数组操作

遍历数组

for方法:

public class Hello {
    public static void main(String[] args) {
        int[] ns = {1, 3, 5, 7, 9};
        for(int i = 0;i < ns.length;i++){
            System.out.println(ns[i]);
        }
    }
}

for each方法:

public class Hello {
    public static void main(String[] args) {
        int[] ns = {1, 3, 5, 7, 9};
        for(int n : ns){
            System.out.println(n);
        }
    }
}

数组排序

最简单的冒泡排序 :

import java.util.Scanner;

public class Sort {
    public static void main(String[] args){
        int[] num = new int[100];
        var input = new Scanner(System.in);
        System.out.print("请输入需要排序数字的数量:");
        int sum = input.nextInt();
        System.out.print("请输入需要排序的数字:");
        for(int i = 0;i < sum;i++){
            num[i] = input.nextInt();
        }
        for(int i = sum - 1;i > 0; i--){
            for(int j = 0;j < i;j++){
                int temp;
                if(num[j] > num[j+1]){
                    temp = num[j];
                    num[j] = num[j+1];
                    num[j+1] = temp;
                }
            }
        }
        for(int i = 0;i < sum; i++){
            System.out.printf("%d ", num[i]);
        }
    }
}

多维数组

public class Hello {
    public static void main(String[] args) {
        int[][] ns = {
                { 1, 2, 3, 4 },
                { 5, 6, 7, 8 },
                { 9, 10, 11, 12 }
        };
        System.out.println(ns.length); 
        for(int[] i : ns){
            for(int j: i){
                System.out.printf("%d ", j);
            }
            System.out.println();
        }
    }
}
>>>
3
1 2 3 4 
5 6 7 8 
9 10 11 12 

命令行参数

Java程序的入口是main方法,而main方法可以接受一个命令行参数,它是一个String[]数组。

这个命令行参数由JVM接收用户输入并传给main方法:

public class Main {
    public static void main(String[] args) {
        for (String arg : args) {
            System.out.println(arg);
        }
    }
}

image-20210814181932877

posted @ 2023-01-08 23:37  seizer-zyx  阅读(32)  评论(0编辑  收藏  举报