API(Application Programming Interface)概述:就是java提供给我们使用的类,这些类将底层的实现封装了起来,我们不需要关心这些类是如何实现的,只需要学习这些类如何使用,我们可以通过查找帮助文档来了解java提供的API如何使用。
Object类
JDK1.0
类层次结构的根类,每个类都直接或者间接继承自Object类。 所有对象(包括数组)都实现了这个类的方法。
构造方法: public Object()
成员方法:
1 | public int hashCode() |
public int hashCode() 返回该对象的哈希码值
哈希值是根据哈希算法计算出来的一个值,这个值和地址值有关,但不是实际地址值,可以理解为地址值。
public final Class getClass() 返回此Object的运行时类。
//Class也是一个类,是Class对象建模的类的类型。它其中有个方法:
//public String getName() 以String的形式返回此Class对象所表示的全类名称
public String toString() 返回该对象的字符串表示
toString()方法的值等价于:getClass().getName()+’@’+Integer.toHexString(hashCode())
这个信息是没有任何意义的,所以建议所有子类都重写此方法。
重写:建议重写成把该类的所有成员变量值组成返回。(右键–resources–toString 自动生成,重写的最终版方案就是自动生成)
注意:直接输出一个对象的名称,其实就是调用该对象的toString()方法。
public boolean equals(Object obj) 指示其他某个对象是否与此对象“相等”
这个方法默认情况下比较的是地址值。
比较地址值一般意义不大,所以我们要重写该方法。重写完的方法一般是用来比较对象的成员变量值是否相同。
String的equals()方法是重写自Object类的,比较的是字符串的内容是否相同
重写的代码优化:提高效率,提高代码的健壮性。
最终版其实是自动生成。
==:基本类型:比较的就是值是否相同
引用类型:比较的就是地址值是否相同
equals:
只能比较引用类型:默认情况比较的是地址值,不过我们可以根据自己的情况重写该方法。一般重写都是自动生成,比较对象的成员变量值是否相同。
protected void finalize() 当垃圾回收器不存在对该对象的更多引用时,由对象的垃圾回收器调用此方法。永远垃圾回收,但是什么时候回收不确定。
protected Object clone() 创建并返回此对象的一个副本。
因为是prtected,所以需要重写该方法。
Cloneable:此类实现了Cloneable接口,以指示Object.clone()方法可以合法的对该类实力进行按字段复制。这个接口是****标记****接口,告诉我们实现该接口的类就可以实现对象的复制了。(就只是起个标记的作用,只有实现该接口的类才能被clone)
意义:clone之后改动对以前的数据无影响。而直接赋值引用改动会对以前的数据产生影响。(这只是浅克隆)
Scanner类
需要导包:import java.util.Scanner
JDK5以后用于获取用户的键盘输入
构造方法:public Scanner(InputStreamsource)
System类下有一个静态的字段: public static final InputStream in; 标准的输入流,对应着键盘录入。
成员方法:
hasNextXxx() ****判断****是否还有下一个输入项,其中Xxx可以是Int,Double等。如果需要判断的是否包含下一个字符串,可以省略Xxx
nextXxx() 获取下一个输入项。
默认情况下,Scanner使用空格,回车等作为分隔符。
常用的方法:
public int nextInt()
public String nextLine()
先获取一个数值,在获取一个字符串,就会出现问题(因为换行符号被当成是字符串输入)
解决:A.先获取一个数值后,再创建一个新的键盘录入对象获取字符串。
B.把所有的数据都先按照字符串获取,然后要什么在对应转换成什么。
键盘录入数据
1.导包:import java.util.Scanner (import必须出现在所有的class前面)
2.创建对象:Scanner sc=new Scanner(System.in)
3.接收数据:int x=sc.nextInt();
String s=sc.nextLine();
String类/StringBuffer类/StringBuilder类
字符串是由多个字符组成的一串数据(字符序列)
字符串可以看成是字符数组。
字符串字面值”abc”也可以看成是一个字符串对象。
字符串是常量,一旦被赋值,就不能被改变。字符串直接赋值的方式是先到方法区中的字符串常量池里面去找,如果有就直接返回,没有就创建返回。(赋的值不能变,引用可以变)
- String s=”hello”; s+=”world”; 则s的输出结果是:helloworld
因为s的赋值hello不能改变,但是+world后在方法区的常量池中会重新生成一个地址值指向栈的s。
- String s=new String(“hello”);和String s=”hello”; 的区别?
区别就是前者会生成2个或1个(可能常量池中已经存在hello常量)对象,而后者只会生成1个或0个对象。(因为前者会在堆内存中生成一个地址值,而后者是方法区中的常量池直接指向栈内存)
字符串如果是变量相加,先开空间,在拼接。
字符串如果是常量相加,直接加,然后在常量池中找,如果有就直接返回,否则就创建。
构造方法:
1 | public String() //空构造 |
方法:
1 | public int length() :返回此字符串的长度。 |
字符串内容为空(“”)和字符串对象为空(null)是两个概念。
空指针不能调用方法。
String类的获取功能:
1 | int length() 获取字符串的长度 |
String类的转换功能:
1 | byte[] getBytes() 把字符串转换成字节数组 |
String类的其他功能:
1 | 替换功能: |
字符串反转:定义一个新的字符串,将给定的字符串倒着遍历,拼接到新的字符串。
统计大串中小串出现的次数:定义一个统计变量,获取小串在大串中第一次出现的索引(用indexOf()方法,不存在的话会返回-1),将索引+小串的长度作为起始位置截取原始大串并赋值给原始大串(用int indexOf(String str,int fromIndex)方法),继续获取小串在大串中第一次出现的索引(用indexOf()方法,不存在的话会返回-1)。
匹配功能:
1 | 1. |
StringBuffer类
如果对字符串进行拼接操作,每次拼接都会构建一个新的String对象,既耗时又耗空间,所以产生了StringBuffer类。
线程安全的可变字符序列。
安全–同步–数据是安全的
不安全–不同步–效率高一些
StringBuffer和String的区别:前者长度和内容可变,后者不可变。
当字符串拼接时,前者不会浪费太多的资源。
StringBuffer的构造方法:
1 | public StringBuffer() 无参构造方法 |
StringBuffer的方法:
1 | public int capacity():返回当前容量。 理论值 |
类之间的转换:
A–B的转换:把A转换成B是为了使用B的功能
B–A的转换:要的结果是A类型,所以需要再转回来。
String和StringBuffer的相互转换:
String转成StringBuffer:
不能把字符串的值直接赋值给StringBuffer
方法1:通过构造方法:StringBuffer sb=new StringBuffer(s);
方法2:通过append方法:StringBuffer sb2=new StringBuffer(); sb2.append(s);
StringBuffer转成String:
方法1:通过构造方法:String s=new String(buffer);
方法2:通过toString方法:String str2 = buffer.toString();
StringBuilder类
一个可变的字符序列,此类提供一个与StringBuffer兼容的API(在单线程中完全可以替代StringBuffer),但不保证同步。在单个线程使用时很普遍,因为不保证安全,但是比StringBuffer类快。
1.String,StringBuffer,String Builder的区别:
String内容是不可变的,而StringBuffer、StringBuilder都是内容可变的。
StringBuffer是同步的,数据安全,效率低;StringBuilder是不同步的,数据不安全,效率高。
2.StringBuffer和数组的区别:
二者都可以看成是容器装其他数据,但是StringBuffer的数据最终是一个字符串数据,而数组可以放置多种数据,但必须是同一种数据类型。
\3. 形式参数问题:
基本类型:形式参数的改变不影响实际参数
引用类型:形式参数的改变直接影响实际参数
String作为参数传递:效果和基本类型作为参数传递是一样的。(因为String是一种特殊的基本类型,常量池)
StringBuffer作为参数传递:只有调用方法时才改变了值,一般的赋值=不改变原来值。
Arrays类和数组高级
Arrays类:需要导包import java.util.Arrays
是针对数组进行操作的工具类,提供了排序,查找等功能。
无构造方法。成员方法全是静态方法。
成员方法:不懂就去看源码。
1 | public static String toString(int[] a) 把数组转成字符串 |
数组高级:排序和查找
排序:
\1. 插入排序类:
(1)直接插入排序:(在小规模数据集或是基本有序时,该算法效率较高)每一步将一个待排序的元素,按其排序码的大小,插入到前面已经排好序的一组元素的适当位置上去,直到元素全部插入为止
(2)希尔排序:先对数据进行预处理,使其基本有序,然后再用直接插入排序算法排序。
\2. 选择排序类:
(1)简单选择排序:(每次选择一个最大(小)的,直到所有元素都被输出)从0索引开始,依次和后面元素比较,小的回到0索引;第一次完毕后,最小值出现在了最小索引处;第二次比较,有1个元素不比;比较的次数是array.length-1。
(2)堆排序:根节点是整个堆的最大值,将它移走;将剩余n-1个节点重新构造成一个堆,再将根节点移走;重复执行1,2。直到没有节点可移动,就生成了有序序列。
\3. 交换排序类:
(1)冒泡排序:(该算法比较简单,几乎所有语言涉及到算法时,都会涉及到冒泡算法)相邻元素两两比较,大的往后放;第一次完毕,最大值出现在最大索引处;第二次比较,有1个元素不比;比较的次数是array.length-1。
(2)快速排序:(利用“分而治之”的思想对集合进行排序)
4.归并排序类:
归并排序:归并排序(MERGE-SORT)是利用归并的思想实现的排序方法,该算法采用经典的分治策略(分治法将问题分成一些小的问题然后递归求解,而治的阶段则将分的阶段得到的各答案”修补”在一起,即分而治之)。
5.计数排序:计数排序统计小于等于该元素值的元素的个数i,于是该元素就放在目标数组的索引i位(i≥0)。
计数排序基于一个假设,待排序数列的所有数均为整数,且出现在(0,k)的区间之内。
如果 k(待排数组的最大值) 过大则会引起较大的空间复杂度,一般是用来排序 0 到 100 之间的数字的最好的算法,但是它不适合按字母顺序排序人名。
计数排序不是比较排序,排序的速度快于任何比较排序算法。
6.桶排序:将值为i的元素放入i号桶,最后依次把桶里的元素倒出来。
7.基数排序:取得数组中的最大数,并取得位数;arr为原始数组,从最低位开始取每个位组成radix数组;对radix进行计数排序(利用计数排序适用于小范围数的特点)
*排序算法* | *平均时间复杂度* | *最差时间复杂度* | *空间复杂度* | *数据对象稳定性* |
---|---|---|---|---|
冒泡排序 | O(n2) | O(n2) | O(1) | 稳定 |
选择排序 | O(n2) | O(n2) | O(1) | 数组不稳定、链表稳定 |
插入排序 | O(n2) | O(n2) | O(1) | 稳定 |
快速排序 | O(n*log2n) | O(n2) | O(log2n) | 不稳定 |
堆排序 | O(n*log2n) | O(n*log2n) | O(1) | 不稳定 |
归并排序 | O(n*log2n) | O(n*log2n) | O(n) | 稳定 |
希尔排序 | O(n*log2n) | O(n2) | O(1) | 不稳定 |
计数排序 | O(n+m) | O(n+m) | O(n+m) | 稳定 |
桶排序 | O(n) | O(n) | O(m) | 稳定 |
基数排序 | O(k*n) | O(n2) | 稳定 |
查找:
\1. 基本查找:查找的数组无序(从头找到尾)
\2. 二分(折半)查找:查找的数组有序
只要是无序的就不能使用二分查找,因为二分查找一旦排序就改变了元素在数组中的位置,其索引也就不对了。
*查找算法* | *平均时间复杂度* | *空间复杂度* | *查找条件* |
---|---|---|---|
顺序查找 | O(n) | O(1) | 无序或有序 |
二分查找(折半查找) | O(log2n) | O(1) | 有序 |
插值查找 | O(log2(log2n)) | O(1) | 有序 |
斐波那契查找 | O(log2n) | O(1) | 有序 |
哈希查找 | O(1) | O(n) | 无序或有序 |
二叉查找树(二叉搜索树查找) | O(log2n) | ||
红黑树 | O(log2n) | ||
2-3树 | O(log2n - log3n) | ||
B树/B+树 | O(log2n) |
基本类型包装类(Interger,Character)
为了对基本数据类型进行更多的操作,更方便的操作,java就对每一种基本类型提供了对应的类类型,包装类类型。
基本类型 | 包装类类型 |
---|---|
byte | Byte |
short | Short |
int | Integer |
long | Long |
char | Character |
boolean | Boolean |
float | Float |
double | Double |
常用于基本数据类型与字符串之间的转换。
Integer类:
Integer 类在对象中包装了一个基本类型 int 的值
该类提供了多个方法,能在 int 类型和 String 类型之间互相转换,还提供了处理 int 类型时非常有用的其他一些常量和方法
构造方法:
public Integer(int value)
public Integer(String s) 这个字符串s必须是由数字字符组成,不然就会报错。
int类型和String类型的相互转换
int – String:
\1. 字符串拼接:String s=””+number
\2. 调用String的方法:String s= String.valueOf(number);
\3. int–Integer–String:: Integer i=new Integer(number); String s= i.toString();
\4. 调用Integer的方法:String s= Integer.toString(number);
String – int:
\1. String–Integer–int: Integer ii= new Integer(s); int x = ii.intValue();
\2. 调用Integer的方法**:int x=Integer.parseInt(s); (这个方法很重要,是将字符串类型转换为基本数据类型,调用的是该基本数据类型的包装类的parseXxx方法)
成员方法:
常用的基本进制转换:
public static String toBinaryString(int i) 十进制到二进制
public static String toOctalString(int i) 十进制到八进制
public static String toHexString(int i) 十进制到十六进制
十进制到其他进制:
public static String toString(int i,int radix) radix代表int型数字(2-36),表示二到三十六进制(0-9,a-z)
其他进制到十进制
public static int parseInt(String s,int radix) 给出的s必须是radix可以转换的,不然会报错。
JDK5新特性:(通过反编译就可以发现)
自动装箱:把基本类型转换为包装类类型。
Integer x = new Integer(4);可以直接写成Integer x = 4;//自动装箱。
自动拆箱:把包装类类型转换为基本类型。
x = x + 5;//自动拆箱。通过intValue方法。
在使用时,Integer x = null;上面的代码就会出现NullPointerException。(所以要先判断对象是否为null)
1.5之后,加了个byte常量池:Integer的数据直接赋值,如果在-128到127之间,会直接从缓冲池里获取数据,而不会new一个新对象。
Character类:
Character 类在对象中包装一个基本类型 char 的值
此外,该类提供了几种方法,以确定字符的类别(小写字母,数字,等等),并将字符从大写转换成小写,小写转成大写
构造方法
public Character(char value)
成员方法:
public static boolean isUpperCase(char ch) 判断给定的字符是否是大写字符
public static boolean isLowerCase(char ch) 判断给定的字符是否是小写字符
public static boolean isDigit(char ch) 判断给定的字符是否是数字字符
public static char toUpperCase(char ch) 把给定的字符转换成大写字符
public static char toLowerCase(char ch) 把给定的字符转换成小写字符
正则表达式regex(Pattern,Matcher)
是指一个用来描述或者匹配一系列符合某个句法规则的字符串的单个字符串。其实就是一种规则。有自己特殊的应用。
组成规则:
规则字符在java.util.regex Pattern类中
常见组成规则:
- 字符:
x 字符x。举例:’a’ 表示字符a
\ 反斜线字符。因为一个\代表了转义。
\n 新行(换行)符 (‘\uoooA’)
\r 回车符 (‘\uoooD’)
- 字符类
[abc] a、b或c(简单类) abc中的任意一个,但只能是一个
[^abc] 任何字符,除了a、b或c(否定)
[a-zA-Z] a到z或A到Z,两头的字母包括在内(范围)
[0-9] 0到9的字符都包括
[]里不用转义字符,是什么就是什么
- 预定义字符类
. 任何字符。如果就是.本身,应该写为 \.
\d 数字:[0-9] 在写的时候都是\d表示 因为要先转义。
\D 非数字:[^ 0-9]
\w 单词字符(小w):[a-zA-Z_0-9] 在正则表达式里面组成单词的东西必须由这些东西组成(可以是A-Z,a-z,0-9,下划线都行)
\W
即(大W)表示除\w单词字符之外的其他所有字符
\S 匹配任何非Unicode空白的字符 [^\s]
\s 空格字符:[\ t\n\x0B\f\r\n]
- 边界匹配器
^ 行的开头
$ 行的结尾
\b 单词边界 就是不是单词字符的地方。(单词间隔就用这个字符占)
- 数量词
X? X,一次或一次也没有
X* X,零次或多次
X+ X,一次或多次
X{n} X,恰好n次
X{n,} X,至少n次
X{n,m} X,至少n次,但不超过m次
6.POSIX字符类
\p{Punct} 匹配任何标点字符 “#$%&'()* +, - 。/:; <=>?@ [\ _] ^ _> {|}
\p{Lower} 小写字母字符:[az]
\p{Upper} 大写字母字符:[AZ]
\p{ASCII} 所有ASCII:[\ x00-\x7F]
\p{Alpha} 字母字符:[\ p {Lower}\p {Upper}]
\p{Digit} 十进制数字:[0-9]
\p{Alnum} 字母数字字符:[\ p {Alpha}\p {Digit}]
\p{Graph} 一个可见的角色:[\ p {Alnum}\p {Punct}]
\p{Print} 可打印字符:[\ p {Graph}\x20]
\p{Blank} 空格或制表符:[\ t]
\p{XDigit} 十六进制数字:[0-9a-fA-F]
\p{Space} 一个空白字符:[\ t\n\x0B\f\r]
(?:pattern)
非获取匹配,匹配pattern但不获取匹配结果,不进行存储供以后使用。这在使用或字符“(|)”来组合一个模式的各个部分是很有用。例如“industr(?:y|ies)”就是一个比“industry|industries”更简略的表达式。
(?=pattern)
非获取匹配,正向肯定预查,在任何匹配pattern的字符串开始处匹配查找字符串,该匹配不需要获取供以后使用。例如,“Windows(?=95|98|NT|2000)”能匹配“Windows2000”中的“Windows”,但不能匹配“Windows3.1”中的“Windows”。预查不消耗字符,也就是说,在一个匹配发生后,在最后一次匹配之后立即开始下一次匹配的搜索,而不是从包含预查的字符之后开始。
(?!pattern)
非获取匹配,正向否定预查,在任何不匹配pattern的字符串开始处匹配查找字符串,该匹配不需要获取供以后使用。例如“Windows(?!95|98|NT|2000)”能匹配“Windows3.1”中的“Windows”,但不能匹配“Windows2000”中的“Windows”。
(?<=pattern)
非获取匹配,反向肯定预查,与正向肯定预查类似,只是方向相反。例如,“(?<=95|98|NT|2000)Windows”能匹配“2000Windows”中的“Windows”,但不能匹配“3.1Windows”中的“Windows”。
(?<!pattern)
非获取匹配,反向否定预查,与正向否定预查类似,只是方向相反。例如“(?<!95|98|NT|2000)Windows”能匹配“3.1Windows”中的“Windows”,但不能匹配“2000Windows”中的“Windows”。这个地方不正确,有问题
应用:
判断功能
String类的public boolean matches(String regex)方法
分割功能
String类的public String[] split(String regex)方法 根据给定正则表达式的匹配拆分此字符串成字符串数组(相当于是把regex这个字符删除了,剩下的分成小片段)
(硬盘上的路径,我们应该用\\
替代\,把它分割是\\\\
第一个\代表格式,第二个\代表转义,\\
代表字符串)
替换功能
String类的public String replaceAll(String regex,String replacement)方法: 使用给定的replacement替换此字符串所有匹配给定的正则表达式的子字符串 (应用:可以屏蔽一些子,密码的*等等)
获取功能
Pattern和Matcher类的使用
模式和匹配器的典型调用顺序:
\1. 把正则表达式编译成模式对象:Pattern p= Pattern.compile(“a*b”);
\2. 通过模式对象得到匹配器对象,这个时候需要的是被匹配的字符串:Matcher m=p.matcher(“aaaaab”);
\3. 调用匹配器对象的功能:
(1) boolean b=m.matches(); 调用的matches方法尝试将整个输入序列与该模式匹配
(2) lookingAt 尝试将输入序列从头开始与该模式匹配
(3) find方法扫描输入序列以查找玉该模式匹配的下一个子序列
以上三种方法都是返回boolean类型。find方法后还有一个group方法用来获取匹配的子字符串。
JAVA时间字符串去空格、冒号和横杠
1 | String date = "2017-09-19 14:40:01"; |
[[:punct:]]是指所有的符号!#$%&'()*+,-./:;<=>?@[]^
{}~`
\s匹配任何空白字符[\t\n\x0B\f\r],第一个\是转义
Math类/Random类/System类
Math 类包含用于执行基本数学运算的方法,如初等指数、对数、平方根和三角函数。
成员变量:
publi static final double PI
publi static final double E
成员方法(都是静态,不用创建对象)
public static int abs(int a) 绝对值
public static double ceil(double a) 向上取整
public static double floor(double a) 向下取整
public static int max(int a,int b) 最大值
public static double pow(double a,double b) a的b次幂
public static double random() 随机数[0.0,1.0)
public static int round(float a) 四舍五入(+0.5后向下取整)
public static double sqrt(double a) 正平方根
如果想得到任意范围的随机数:
int number=(int) (Math.random()*(end-start+1))+start;
Random类:util包中,此类的实例用于生成伪随机数流。
如果用相同的种子创建两个 Random 实例,则对每个实例进行相同的方法调用序列,它们将生成并返回相同的数字序列。
构造方法
public Random() 没有给种子,用的是默认种子,是当前时间的毫秒值
public Random(long seed) 给出指定的种子。 给定种子后,每次得到的随机数是相同的。
Random类成员方法
public int nextInt() 返回的是int范围内的随机数
public int nextInt(int n) 返回的是[0,n)范围内的随机数
System类:lang包
System 类包含一些有用的类字段和方法。它不能被实例化,全是静态。
成员方法
public static void gc() 运行垃圾回收器 不要一直调用们因为每一次执行垃圾回收,jvm都会强制启动垃圾回收器运行,这回耗费更多的系统资源,会与正常的java程序争夺资源,只有执行大量的对象的释放时,才会调用垃圾回收。
public static void exit(int status) 终止当前正在运行的java虚拟机,参数用作状态码,根据惯例,非0的状态码表示异常终止。(所以一般用System.exit(0);相当于按了x退出,后面的都不运行)
public static long currentTimeMillis() 返回以毫秒为单位的当前时间(可以用来计时)
为什么是1970年1月1日0点:一种说法是java起源于UNIX系统,而UNIX系统认为1970.1.1是时间纪元。因为当时的操作系统是32位,换算下来相当于68.1年就会达到最大值,从而回到起始值,所以将1970.1.1当作起点,让这个时间推迟到2038年,而现在已经出现了64位操作系统,所以时间无线大,解决了这个问题。
public static void arraycopy(Object src,int srcPos,Object dest,int destPos,int length) 从指定原数组中复制一个数组,复制从指定的位置开始,到目标数组的指定位置结束。arraycopy中c小写,因为刚开始命名不规范改不回去了。src代表原数组,srcPos代表原数组中的起始位置。dest目标数组,destPos代表目标数组中的起始位置。length代表要复制的数组元素的数量。相当于原数组不变,新数组的长度也不变,只是把原数组中的length长度元素替换到了新数组中。
BigInterger类/BigDecimal类
BigInteger类:
可以让超过Integer范围内的数据进行运算
构造方法
public BigInteger(String val)
BigInteger类的成员方法
public BigInteger add(BigInteger val) +
public BigInteger subtract(BigInteger val) -
public BigInteger multiply(BigInteger val) *
public BigInteger divide(BigInteger val) /
public BigInteger[] divideAndRemainder(BigInteger val) 返回的是商和余数的数组
BigDecimal类:
由于在运算的时候,float类型和double很容易丢失精度,演示案例。所以,为了能精确的表示、计算浮点数,Java提供了BigDecimal(金融方面就要用)
是不可变的、任意精度的有符号十进制数。
构造方法
public BigDecimal(String val)
BigDecimal类的成员方法
public BigDecimal add(BigDecimal augend)
public BigDecimal subtract(BigDecimal subtrahend)
public BigDecimal multiply(BigDecimal multiplicand)
public BigDecimal divide(BigDecimal divisor)
public BigDecimal divide(BigDecimal divisor,int scale, int roundingMode) 商,几位小数,如何取舍
判断 BigDecimal 是否为0:
new BigDecimal(“0.00”).compareTo(你的数据) == 0
Date类/DateFormat类/Calendar类
Date类:
类 Date 表示特定的瞬间,精确到毫秒。 大部分方法已经过时。
构造方法
public Date()
public Date(long date)
成员方法
public long getTime() 获取时间,以毫秒为单位
public void setTime(long time) 设置时间
Syste.ou.println(new Date(0)); 为什么打印的是8.而不是0.呢:因为存在系统时间和本地时间的间隔,系统时间依然是0点,而电脑的时区设置在东8区,所以打印的结果是8点。
DateFormat类:txt包
Date–String 格式化 public final String format(Date date)
String–Date 解析 public Date parse(String source)
DateFormat 是日期/时间格式化子类的抽象类,它以与语言无关的方式格式化并解析日期或时间。
DateFormat可以进行日期和字符串的格式化和解析,但由于是抽象类,所以使用其子类SimpleDateFormat
SimpleDateFormat类的构造方法:
public SimpleDateFormat() 默认模式
public SimpleDateFormat(String pattern) 给定的模式
API中有对应的模式举例:
年 y
月 M
日 d
时 H
分 m
秒 s
2020年11月14日 17:58:20
yyyy年MM月dd日 HH:mm:ss
在把一个字符串解析为日期的时候,请注意格式必须和给定的字符串格式匹配。
成员方法
public final String format(Date date)
public Date parse(String source)
Calendar类
Date类的很多都被Calendar类替代了。
Calendar 类是一个抽象类,它为特定瞬间与一组诸如 YEAR、MONTH、DAY_OF_MONTH、HOUR 等 日历字段之间的转换提供了一些方法,并为操作日历字段(例如获得下星期的日期)提供了一些方法。
成员方法
public static Calendar getInstance() 其实相当于多态,表面上返回的是Calendar,其实返回的是Calendar的一个实现子类。
public int get(int field) 返回给定日历字段的值。日历类中的每个日历字段都是静态的成员变量,并且是int类型。
public void add(int field,int amount) 根据给定的日历字段和对应的时间,来对当前的日历进行操作。 amount可以是 -3 3
public final void set(int year,int month,int date) 设置当前日历的年月日。
month都是0-11 所以适当+1
RunTime类
该类主要代表了应用程序的运行环境。一个RunTime就代表一个运行环境
方法
(1) getRuntime():该方法用于返回当前应用程序的运行环境对象。
(2) exec(String command):该方法用于根据指定的路径执行对应的可执行文件。
(3) freeMemory():该方法用于返回Java虚拟机中的空闲内存量,以字节为单位。
(4) maxMemory():该方法用于返回Java虚拟机试图使用的最大内存量。
(5) totalMemory():该方法用于返回Java虚拟机中的内存总量。
例子:
getRuntime().exec()
在java中,RunTime.getRuntime().exec()实现了调用服务器命令脚本来执行功能需要
用法:
public Process exec(String command)—–在单独的进程中执行指定的字符串命令。
public Process exec(String [] cmdArray)—在单独的进程中执行指定命令和变量
public Process exec(String command, String [] envp)—-在指定环境的独立进程中执行指定命令和变量
public Process exec(String [] cmdArray, String [] envp)—-在指定环境的独立进程中执行指定的命令和变量
public Process exec(String command,String[] envp,File dir)—-在有指定环境和工作目录的独立进程中执行指定的字符串命令
public Process exec(String[] cmdarray,String[] envp,File dir)—-在指定环境和工作目录的独立进程中执行指定的命令和变量
举例:
RunTime.getRuntime().exec(String command);
在windows下相当于直接调用 /开始/搜索程序和文件 的指令,比如 Process process = Runtime.getRuntime().exec("notepad.exe"); -------打开windows下记事本。
public Process exec(String [] cmdArray);
Linux下: Process process = Runtime.getRuntime().exec(new String[]{"/bin/sh","-c", "; Windows下: Process process = Runtime.getRuntime().exec(new String[]{ "cmd", "/c", cmds});
补充:#!/bin/bash和#!/bin/sh的区别
#! 是个指示路径的表示符,/bin/bash和/bin/sh指定了脚本解析器的程序路径
bash是sh的完整版,bash完全兼容sh命令,反之不行
OPTIONS:
-c string 该选项表明string中包含了一条命令.如 bash -c ls ~
-i 使Bash以交互式方式运行
-r 使Bash以受限方式运行
–login 使Bash以登录Shell方式运行
–posix 使Bash遵循POSIX标准
–verbose 使Bash显示所有其读入的输入行
–help 打印Bash的使用信息
–version 打印版本信息
Process的几种方法:
1.destroy():杀掉子进程
2.exitValue():返回子进程的出口值,值 0 表示正常终止
3.getErrorStream():获取子进程的错误流
4.getInputStream():获取子进程的输入流
5.getOutputStream():获取子进程的输出流
6.waitFor():导致当前线程等待,如有必要,一直要等到由该 Process 对象表示的进程已经终止。如果已终止该子进程,此方法立即返回。如果没有终止该子进程,调用的线程将被阻塞,直到退出子进程,根据惯例,0 表示正常终止
注意:在java中,调用runtime线程执行脚本是非常消耗资源的,所以切忌不要频繁使用!
在调用runtime去执行脚本的时候,其实就是JVM开了一个子线程去调用JVM所在系统的命令,其中开了三个通道: 输入流、输出流、错误流,其中输出流就是子线程走调用的通道。
waitFor是等待子线程执行命令结束后才执行, 但是在runtime中,打开程序的命令如果不关闭,就不算子线程结束。比如以下代码。
1 | private static Process p = null; |
以上代码中,打开windows中记事本。如果我们不手动关闭记事本,那么输出语句就不会被执行,这点是需要理解的。
process的阻塞:
在runtime执行大点的命令中,输入流和错误流会不断有流进入存储在JVM的缓冲区中,如果缓冲区的流不被读取被填满时,就会造成runtime的阻塞。所以在进行比如:大文件复制等的操作时,我们还需要不断的去读取JVM中的缓冲区的流,来防止Runtime的死锁阻塞。
1 | 在linux 上封装的方法: |