Java Skills
learn it again
基础知识
介绍
javaSE EE ME
Java SE:Standard Edition
Java EE:Enterprise Edition
Java ME:Micro Edition
┌───────────────────────────┐
│Java EE │
│ ┌────────────────────┐ │
│ │Java SE │ │
│ │ ┌─────────────┐ │ │
│ │ │ Java ME │ │ │
│ │ └─────────────┘ │ │
│ └────────────────────┘ │
└───────────────────────────┘
JDK JRE
JDK:Java Development Kit
JRE:Java Runtime Environment
┌─ ┌──────────────────────────────────┐
│ │ Compiler, debugger, etc. │
│ └──────────────────────────────────┘
JDK ┌─ ┌──────────────────────────────────┐
│ │ │ │
│ JRE │ JVM + Runtime Library │
│ │ │ │
└─ └─ └──────────────────────────────────┘
┌───────┐┌───────┐┌───────┐┌───────┐
│Windows││ Linux ││ macOS ││others │
└───────┘└───────┘└───────┘└───────┘
JRE是虚拟机,运行游戏就装JRE,运行Java字节码
JDK包括JRE和开发工具,提供了编译器、调试器等
java
:这个可执行程序其实就是JVM,运行Java程序,就是启动JVM,然后让JVM执行指定的编译后的代码;
javac
:这是Java的编译器,它用于把Java源码文件(以.java后缀结尾)编译为Java字节码文件(以.class后缀结尾);
jar
:用于把一组.class文件打包成一个.jar文件,便于发布;
javadoc
:用于从Java源码中自动提取注释并生成文档;
jdb
:Java调试器,用于开发阶段的运行调试。
程序基础
命名规范
public static void main(String[] args)
类名要求:GoodMorning
- 类名必须以英文字母开头,后接字母,数字和下划线的组合
- 习惯以
大写字母开头
方法名: goodMorning
- 首字母小写
- 之后每个单词首字母大写
变量和数据类型
计算机内存
的最小存储单元是字节(byte),一个字节就是一个8位二进制数,即8个bit。它的二进制表示范围从00000000~11111111,换算成十进制是0~255,换算成十六进制是00~ff。
整型
最高位的bit表示符号位(0表示正数,1表示负数)
byte(1位):-128 ~ 127
short(2位): -32768 ~ 32767
int(4位): -2147483648 ~ 2147483647
long(8位): -9223372036854775808 ~ 9223372036854775807
浮点型
对于float类型,需要加上f后缀
float f2 = 3.14e38f; // 科学计数法表示的3.14x10^38
double d = 1.79e308;
float(4位):可最大表示3.4x1038
double(8位):可最大表示1.79x10308
布尔型
Java语言对布尔类型的存储并没有做规定,因为理论上存储布尔类型只需要1 bit,但是通常JVM内部会把boolean表示为4字节
整数。
boolean b1 = true;
boolean b2 = false;
boolean isGreater = 5 > 3; // 计算结果为true
字符类型(2位)
注意char类型使用单引号’,且仅有一个字符
char a = 'A';
char zh = '中';
常量
定义变量的时候,如果加上final
修饰符,这个变量就变成了常量:
final double PI = 3.14; // PI是一个常量
根据习惯,常量名通常
全部大写
。
var关键字
使用var定义变量,仅仅是少写了变量类型而已
var sb = new StringBuilder();
编译完会变成
StringBuilder sb = new StringBuilder();
整数运算
移位运算
int n = 7; // 00000000 00000000 00000000 00000111 = 7
int a = n << 1; // 00000000 00000000 00000000 00001110 = 14
int b = n << 2; // 00000000 00000000 00000000 00011100 = 28
强制类型转换
int i = 12345;
short s = (short) i; // 12345
布尔运算
三元运算符
int x = n >= 0 ? n : -n;
上述语句的意思是,判断n >= 0是否成立,如果为true,则返回n,否则返回-n。这实际上是一个求绝对值的表达式。
字符和字符串
char 单引号’’ string 双引号i "”
String是引用类型,本质是class,所以有不可变特性
:每次重新赋值相当于开辟新的储存空间,并将命名的那个指针指过去
Java的编译器对字符串做了特殊照顾,可以使用+连接任意字符串和其他数据类型
\ 转义符号
- " 表示字符”
- ' 表示字符’
- \\ 表示字符\
- \n 表示换行符
- \r 表示回车符
- \t 表示Tab
- \u#### 表示一个Unicode编码的字符
int[] ns = new int[5];
与普通数组(比如整形)不一样,字符串数组本质使用的是指针指向不同字符串
流程控制
输入和输出
println
是print line的缩写,表示输出并换行。因此,如果输出后不想换行,可以用print()
格式化输出
使用System.out.printf()
,通过使用占位符%?
,printf()可以把后面的参数格式化成指定格式
%d 格式化输出整数
%x 格式化输出十六进制整数
%f 格式化输出浮点数
%e 格式化输出科学计数法表示的浮点数
%s 格式化字符串
double d = 3.1415926;
System.out.printf("%.2f\n", d); // 显示两位小数3.14
System.out.printf("%.4f\n", d); // 显示4位小数3.1416
double d = 3.1415926;
输入
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); // 格式化输出
}
}
if
判断引用类型相等
在Java中,判断值类型的变量是否相等,可以使用==
运算符。但是,判断引用类型的变量是否相等,==
表示“引用是否相等”,或者说,是否指向同一个对象。
判断变量内容相等
要判断引用类型的变量内容是否相等,必须使用equals()方法
执行语句s1.equals(s2)时,如果变量s1为null,会报NullPointerException
==和equal
java中有两种数据类型 基本数据类型和复合数据类型
基本类型包括
:short int byte long char 等 基本数据类型可以直接比较
复合数据类型
:当时用==比较的时候,比较的是他们的的内存地址
Object是所有类的基类,他其中有equal方法,也是比较的内存的地址
switch
int option = 2;
switch (option) {
case 1:
System.out.println("Selected 1");
case 2:
System.out.println("Selected 2");
case 3:
System.out.println("Selected 3");
default:
System.out.println("Not selected");
}
for&for-each
for each与python中的for用处基本相同
int[] ns = { 1, 4, 9, 16, 25 };
for (int n : ns) {
System.out.println(n);
}
toString
通过toString打印,但是效果速度适用面不如强制类型转换String()
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));
}
}
数组排序sort
import java.util.Arrays;
int[] ns = { 28, 12, 89, 73, 65, 18, 96, 50, 8, 36 };
Arrays.sort(ns);
String[] args
程序固定第一行
public static void main(String[] args)
其中 String[] args 可以接受一个命令行参数,它是一个String[]数组
$ java Main -t -l -xxx
意思就是可以在执行程序的时候输入一些参数,有点像做机器学习毕设时,在xxx.py后面加入了各种参数=多少的设定
OOP 面向对象
面向对象基础
private
作用域在实例中
this
- 它始终指向当前实例,通过this.field就可以访问当前实例的字段
- 如果没有命名冲突,可以省略this
可变参数
可变参数用类型...
定义,相当于数组
什么时候用?
在不确定方法需要处理的对象的数量时可以使用可变长参数,会使得方法调用更简单,无需手动创建数组 new T[]{…}
构造方法
多构造方法:this
集合 collection
List
:一种有序列表的集合,
Set
:一种保证没有重复元素的集合
Map
:一种通过键值(key-value)查找的映射表集合
list
List是最基础的一种集合:它是一种有序链表
boolean contains(Object o)方法来判断List是否包含某个指定元素
int indexOf(Object o)方法可以返回某个元素的索引,如果元素不存在,就返回-1
Map
boolean containsKey(K key) 遍历HasMap时,key是无序的,也不是存入的顺序!LikedHashMap额外保证了Map的遍历顺序与put顺序一致的有序性
HashMap
要遍历key可以使用for each循环遍历Map实例的keySet()方法返回的Set集合,它包含不重复的key的集合
for (String key : map.keySet()) {
Integer value = map.get(key);
System.out.println(key + " = " + value);
}
for (Map.Entry<String, Integer> entry : map.entrySet()) {
String key = entry.getKey();
Integer value = entry.getValue();
System.out.println(key + " = " + value);
}
TreeMap
TreeMap等所有SortedMap保证遍历时以Key的名称顺序来进行排序
底层使用红黑树
来实现的
如果作为Key的class没有实现Comparable接口,那么,必须在创建TreeMap时同时指定一个自定义排序算法Comparator(或者直接借助Integer.compare(int, int)也可以返回正确的比较结果)
Map<Student, Integer> map = new TreeMap<>(new Comparator<Student>() {
public int compare(Student p1, Student p2) {
if (p1.score == p2.score) {
return 0;
}
return p1.score > p2.score ? -1 : 1;
}
});
三种Map的使用场景:
-
TreeMap:需要基于排序的统计功能: 由于TreeMap是基于红黑树的实现的排序Map,对于增删改查以及统计的时间复杂度都控制在O(logn)的级别上,相对于HashMap和LikedHashMap的统计操作的(最大的key,最小的key,大于某一个key的所有Entry等等)时间复杂度O(n)具有较高时间效率。
-
HashMap:需要快速增删改查的存储功能: 相对于HashMap和LikedHashMap 这些 hash表的时间复杂度O(1)(不考虑冲突情况),TreeMap的增删改查的时间复杂度为O(logn)就显得效率较低。
-
LikedHashMap:需要快速增删改查而且需要保证遍历和插入顺序一致的存储功能:
相对于HashMap和LikedHashMap 这些 hash表的时间复杂度O(1)(不考虑冲突情况),TreeMap的增删改查的时间复杂度为O(logn)就显得效率较低。但是HashMap并不保证任何顺序性。LikedHashMap额外保证了Map的遍历顺序与put顺序一致的有序性。
Set
Set实际上相当于只存储key、不存储value的Map。我们经常用Set用于去除重复元素
队列Queue
队列Queue实现了一个先进先出(FIFO)的数据结构:
- 通过add()/offer()方法将元素添加到队尾;
- 通过remove()/poll()从队首获取元素并删除;
- 通过element()/peek()从队首获取元素但不删除。
要避免把null添加到队列。