Java开发环境搭建

Java语言特性

在Java语言中真正操作内存的是:JVM(Java虚拟机)

所有的Java程序都是运行在Java虚拟机当中的。

而Java虚拟机执行过程中再去操作内存。

Java语言底层是C++,所以JVM是用C++语言写好的一个虚拟的计算机。Java程序实际上没有直接和操作系统打交道。

术语

JavaSE:标准版;JavaEE:企业版;JavaME:微型版。

JDK:Java开发工具箱;JRE:Java运行环境。

Java的加载与执行原理

java HelloWorld的执行过程:

  1. 先启动JVM;
  2. JVM启动后,JVM会去启动类加载器,类加载器负责去硬盘上找“类”对应的“字节码”文件(HelloWorld.class);
  3. 类加载器如果在硬盘上找不到对应的字节码文件——错误:找不到或无法加载主类;类加载器如果找到了,类加载器会将字节码文件装载到JVM中,JVM启动解释器将字节码解释为二进制码,操作系统执行二进制码和硬件交互。

环境变量

安装Tomcat服务器需要配置JAVA_HOME环境变量。

让类加载器去指定的路径下加载字节码文件:设置一个环境变量,叫做classpath,classpath环境变量是java特有的。配置了classpath之后类加载器只会去配置的路径下去找不会再去当前路径下找。

注释

/**
*javadoc注释:这里的注释信息可以自动被javadoc.exe命令解析提取并生成到帮助文档中
*/

例如:

public class T{
	/**
	* 这是一个程序的入口
	* @param args是main方法的参数
	*/
    public static void main(String[] args){
        
    }
}

生成javadoc文档:

javadoc -d javaapi T.java

把javadoc放入javaapi文件夹。

接收键盘输入

public class HelloWorld {
    public static void main(String[] args) {
        java.util.Scanner s=new java.util.Scanner(System.in);
        int a=s.nextInt();
        System.out.println(a);
    }
}
import java.util.*;

public class HelloWorld {
    public static void main(String[] args) {
        Scanner s=new Scanner(System.in);
        int a=s.nextInt();
        System.out.println(a);
    }
}

在java中任何有效的代码必须写到类当中。

class A{
    
}

class B{
    
}

class C{
    
}

//编译通过

一个java源代码文件中有多个类,编译后有多个class文件。

public的类不是必须的。

class A{
    
}

public class B{
    
}

class C{
    
}

//编译报错

public的类可以没有,但如果有的话,public修饰的类名必须和源文件名保持一致。因此一个java文件里面public的类只能有一个。

class T1{
    public static void main(String[] args){
        System.out.println("T1...");
    }
}

class T2{
    public static void main(String[] args){
        System.out.println("T2...");
    }
}

class T3{
    public static void main(String[] args){
        System.out.println("T3...");
    }
}

//编译通过

想从哪个入口进去,就加载哪个类。例如:

java T1
java T2
java T3

变量

字面量

在Java中数据被称为字面量。例如10、1.23、true、’a’、”abc”,分别为整数型字面量、浮点型字面量、布尔型字面量、字符型字面量、字符串型字面量。

只有字面量内存是无法重复利用的,使用变量以后内存空间就得到了重复利用。

变量

变量是内存中存储数据的最基本的单元。

Java变量必须先声明再赋值才能访问(没有值相当于空间没有开辟)。

局部变量只在方法体中有效,方法体执行结束该变量的内存就释放了。

数据类型

类型 占用字节数量 取值范围
byte 1 [-128,127]
short 2 [-32768,32767]
int 4 [-2147483648,2147483647]
long 8
float 4
double 8
boolean 1
char 2 [0,65535]

字符型

字符编码

字符编码规定了一系列文字对应的二进制。

字符编码涉及到编码和解码两个过程。

ASCII码:英文;

国际标准组织制定ISO-8859-1(latin-1):向上兼容ASCII;

GB2312<GBK<GB18030:简体中文;

big5:繁体中文。

在Java中,采用Unicode编码,支持所有文字,具体的实现包括:UTF-8、UTF-16、UTF-32…

char可以存储一个汉字。

转义字符

\u表示后面的事一个字符的unicode编码。unicode编码是十六进制的。

例如:

char x='\u4e2d';
System.out.println(x);

//输出:中

整数型

进制

//十进制
int a=10;
//八进制
int b=010;
//十六进制
int c=0x10;
//二进制
int d=0b10;

默认

在任何情况下,整数型的字面量默认被当作int类型处理,浮点型的字面量默认被当作double类型处理。

当整数型字面量没有超出byte/short/char的取值范围,那么这个整数型字面量可以直接赋值给byte/short/char。

多种数据类型做混合运算的时候,最终的结果是最大容量对应的类型,但是byte、char、short做混合运算的时候,各自先转换成int。

char c1='a';
byte b=1;
short s=c1+b;	//理应是98,但是编译报错:从int转换到short可能会有损失,因为编译器不知道结果
short k=98;	//编译通过
short s1=(short)c1+b;	//编译报错
short s=(short)(c1+b);	//编译通过

int a=1;
short x=a;	//编译报错,编译器只知道a是int类型,不知道a中存储的是哪个值
System.out.println(x);

自动类型转换

小容量可以自动转换成大容量。

容量排序:

byte<short/char<int<long<float<double

例如:

//int自动转换成long
long b=200;
long e=2147483648;

//编译报错,超过int取值范围

强制类型转换

大容量不能直接赋值给小容量,需要使用强制类型转换符进行强制转换,但是运行时可能损失精度。

long x=100L;
int y=x;

//编译报错

二进制原码反码补码

反码是原码的符号位不变,其他位取反;补码是反码+1。

例如:

byte b=(byte)150;
//10010110(补码)
//10010101(反码)
//11101010(原码)
System.out.println(b);
//输出:-106

字符串连接运算符

当+运算符两边的任意一边是字符串类型,那么这个+会进行字符串拼接操作。

String属于引用数据类型。

标识符

概念

凡是有权利自己命名的单词都是标识符。例如类名、方法名(main也是,但是是固定的)、变量名、接口名、常量名。

命名规则

标识符只能由数字、字母(包括中文)、下划线、美元符号组成,中间不能有空格。

标识符不能以数字开头。

关键字不能作标识符。

区分大小写。

虽然java中的标识符严格区分大小写,但是对于类名来说,如果一个java源文件中同时出现了A类和a类,那么谁在前就生成谁。

标识符没有长度限制。

在123.java中不能定义public的类。

因为public修饰的类名必须和源文件名保持一致。

命名规范

驼峰命名。

类名、接口名每个单词首字母大写。

变量名、方法名首字母小写,后面每个单词首字母大写。

常量名全部大小,并且单词和单词之间采用下划线衔接。

关键字

java中的所有关键字全部小写,具有特殊含义。

数组操作

遍历数组

使用标准的for循环可以完成一个数组的遍历。

使用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 (int n : ns)循环中,变量n直接拿到ns数组的元素,而不是索引。

打印元素

import java.util.Arrays;

public class Main {
    public static void main(String[] args) {
        int[] ns = { 1, 1, 2, 3, 5, 8 };
        System.out.println(Arrays.toString(ns));
      	//输出[1, 1, 2, 3, 5, 8]
    }
}

数组排序

Java的标准库已经内置了排序功能,我们只需要调用JDK提供的Arrays.sort()就可以排序:

import java.util.Arrays;

public class Main {
    public static void main(String[] args) {
        int[] ns = { 28, 12, 89, 73, 65, 18, 96, 50, 8, 36 };
        Arrays.sort(ns);
        System.out.println(Arrays.toString(ns));
      	//输出[8, 12, 18, 28, 36, 50, 65, 73, 89, 96] 
    }
}

如果对一个字符串数组进行排序,例如:

String[] ns = { "banana", "apple", "pear" };

排序前,这个数组在内存中表示如下:

                   ┌──────────────────────────────────┐
               ┌───┼──────────────────────┐           │
               │   │                      ▼           ▼
         ┌───┬─┴─┬─┴─┬───┬────────┬───┬───────┬───┬──────┬───┐
ns ─────>│░░░│░░░│░░░│   │"banana"│   │"apple"│   │"pear"│   │
         └─┬─┴───┴───┴───┴────────┴───┴───────┴───┴──────┴───┘
           │                 ▲
           └─────────────────┘

调用Arrays.sort(ns);排序后,这个数组在内存中表示如下:

                   ┌──────────────────────────────────┐
               ┌───┼──────────┐                       │
               │   │          ▼                       ▼
         ┌───┬─┴─┬─┴─┬───┬────────┬───┬───────┬───┬──────┬───┐
ns ─────>│░░░│░░░│░░░│   │"banana"│   │"apple"│   │"pear"│   │
         └─┬─┴───┴───┴───┴────────┴───┴───────┴───┴──────┴───┘
           │                              ▲
           └──────────────────────────────┘

原来的3个字符串在内存中均没有任何变化,但是ns数组的每个元素指向变化了。

二维数组

public class Main {
    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); // 3
    }
}

因为ns包含3个数组,因此,ns.length3

二维数组的每个数组元素的长度并不要求相同,例如,可以这么定义ns数组:

int[][] ns = {
    { 1, 2, 3, 4 },
    { 5, 6 },
    { 7, 8, 9 }
};

要打印一个二维数组,可以使用两层嵌套的for循环:

for (int[] arr : ns) {
    for (int n : arr) {
        System.out.print(n);
        System.out.print(', ');
    }
    System.out.println();
}

或者使用Java标准库的Arrays.deepToString()

import java.util.Arrays;

public class Main {
    public static void main(String[] args) {
        int[][] ns = {
            { 1, 2, 3, 4 },
            { 5, 6, 7, 8 },
            { 9, 10, 11, 12 }
        };
        System.out.println(Arrays.deepToString(ns));
      	//输出[[1, 2, 3, 4], [5, 6, 7, 8], [9, 10, 11, 12]] 
    }
}