cd + 路径
改变当前目录
cd ..
返回上级目录
cd \
返回根目录
dir
exit
cls
右键 - 标记 - 选中复制内容 - 右键
javac + .java源文件路径
java + .class文件路径(只写文件名,不写后缀)
在系统变量中增加
JAVA_HOME
赋值C:\Program Files\Java\jdk1.8.0_202
JDK路径在
Path
中增加%JAVA_HOME%\bin
(选择性配置)
CLASSPATH
赋值为.
代表当前路径(与不配置效果一样) — 寻找 .class 文件路径
Java SE(Java标准版)
Java EE(Java企业版)
JavaME(Java微型版)
JDK : Java 开发工具包
JRE : Java 运行时环境(包括 JVM )
JVM : Java 虚拟机
OOA :面向对象的分析
OOD:面向对象的设计
OOP:面向对象的编程
GC:垃圾回收(机制)
IDE:集成开发环境
API:应用程序编程接口
cache:池,缓存机制
OCP:开闭原则,对扩展开放,对修改关闭
// 单行注释
/* 多行注释 */
/** * javadoc 注释 * 会被 javadoc.exe 解析提取并生成帮助文档 */
只能由字母、数字、下划线
_
、美元符号$
构成,不能以数字开头严格区分大小写
不能使用关键字
遵循驼峰命名方式
- 类名、接口名:首字母大写
- 变量名、方法名**(动词)**:首字母小写
- 常量名:全部大写
Java 语言源代码采用 Unicode 编码,支持中文(UTF-8 居多)
'0'
-48
'a'
=65
'A'
=97
按声明位置分类
成员变量:类变量 [ 实例变量、静态变量 ](属性)
局部变量:方法体变量
按数据类型分类
基本数据类型
整数型:byte(1)、short(2)、int(4)、long(8 L)默认值0
浮点型:float(4 F)、double(8)默认值0.0
布尔型:boolean(1)默认值false
字符型:char(2)默认值\u0000
byte < short = char < int < long < float < double
引用数据类型
- 字符串:String、Class 默认值null
- 大类型转小类型,强制类型转换,高位截掉(损失精度)
- 整数型超过原容量上限,就要进行强制类型转换
- 十进制:默认
- 八进制:以
0
开头- 十六进制:以
0x
开头
- 逻辑运算符
不存在短路:
&
、|
、!
、^
(异或,不同为真)存在短路:
&&
、||
- 计算运算符
byte i = 10; i += 5; //等价于 i = (byte)(i + 5) i = i + 5 //等价于 i = i + 5 错误,i + 5 结果为 int 型
最先有数据的是方法区内存、变化最频繁的是栈内存、垃圾回收(GC)机制针对堆内存
- 只能有一个方法区内存
- .class方法片段
- 静态变量(类加载就开辟内存)
- 只能有一个堆内存
- Java 中没有指针,不可以直接操作堆内存,只能通过引用操作
- 引用数据类型 new 的**(实例对象、数组)**
- 字符串常量池:存储字符串(JDK7从方法区移到堆内)
- 一个线程一个栈内存
- 栈帧永远指向栈顶元素
- 栈顶元素处于活跃状态,其他元素静止
- 术语:
- 压栈 / 入栈:push
- 弹栈 / 出栈:pop
- 栈的存储结构特点
- 先进后出、后进先出
- 执行中的方法、局部变量
类 — [ 实例化 ] — 对象(实例 instance)
对象 — [ 抽象 ] — 类
引用 — [ 保存 ] — 对象的地址
访问类内属性不可以直接读写,通过get/set方法进行读写 (privet)
eclipse 中 右键 — Source — Generate Gerrers and Setters
基本语法
[修饰符列表] class 类名 extends 父类名{ //继承类 }
Java 仅支持单继承,但是可以间接继承,默认继承 java.lang.Object
私有的不支持继承
构造方法不支持继承,调用
super()
调用父类构造方法
上转型:子类型 — 父类型
编译期参考父类型方法,执行期参考子类型方法
继承中,多个子类型调用同一个父类型方法,即可传参子类型,方法接参父类型
子类型转父类型,可再转回原子类型,但不可以转换为其他子类型 异常:java.lang.ClassCastException
使用 instanceof 运算符避免异常 语法:引用 instanceod 类型名
返回 true(类型正确) / false(类型错误)
数组为引用型数据,实际元素存储在内存堆中,引用存储在内存栈中
优:查询效率高
- 内存空间地址是连续的,每一个元素类型相同,占用空间大小相同
- 通过下标可以直接计算某个下标元素的内存地址
**缺:增删元素效率低:**元素位移
**缺:不适合存储大数据量:**内存空间很难存在特别大的连续内存空间
int[] a = {3,2,5,6,1,4} a.length; //获取元素个数,输出 5 Arrays.sort(a); //排序数组
当数组元素不足时,创建一个大数组,将小数组元素拷贝到大数组
拷贝方法:
System.arraycopy(原数组, 原起始下标, 新数组, 新起始下标, 拷贝长度)
用于预留运行时传参,如DOS中
java .class文件名 参数1 参数2 参数3...
class test{ public static void main(String[] args){ A a_class = new a[new B(),new C()]; for(int i = 0; i < a_class.length; i++){ a_class[i].a(); //上转型 /* 输出结果: 子类B 子类C */ } for(int i = 0; i < a_class.length; i++){ if(a_class instanceof B){ //下转型 B b_class = (B)a_class[i]; b_class.otherB(); }else if(a_class instanceof C){ C c_class = (C)a_class[i]; c_class.otherC(); } /* 输出结果: 子类其他方法B 子类其他方法C */ } } } class A{ public void a(){ System.out.println("父类A"); } } class B extends A{ public void a(){ System.out.println("子类B"); } public void otherB(){ System.out.println("子类其他方法B"); } } class C extends A{ public void a(){ System.out.println("子类C"); } public void otherC(){ System.out.println("子类其他方法C"); } }
- 方法只有在调用时,才会动态给方法分配内存空间
- 方法代码片段属于.class字节码的一部分,字节码文件在类加载的时候载入到方法区内存中,每次调用方法在栈内存中分配独立空间。
- 调用方法压栈,方法结束出栈
构造方法写法
public class 类名 { public 类名(){ //构造方法 //eclipse 中 右键 — Source — Generate Constructor using Fields } }
直接调用构造方法
this()
- 重载指同一类内方法重名
- 重载要求参数列表不同,其余必须完全一致
- 重写指继承类方法重名
- 重写要求所有信息必须完全一致
- 重写方法访问权限不能更低,只能更高
- 抛出异常不能更过,只能更少
递归必须有结束条件,否则必定会栈溢出,即便有条件也可能存在栈溢出
Java 静态方法内不可以调用实例变量与方法(未被 static 修饰),不存在 this,需要实例化才可以调用
public class 类名 { static{ //类加载时刻执行 } }
public class 类名 { { //类实例时刻执行 } }
public static final String 全部大写名字 = 值
- 修饰的类无法被继承
- 修饰的方法无法被覆盖(重写)
- 修饰的变量赋值后无法改变
- 修饰的实例变量必须声明时赋值(或构造体)且不可改变
- 修饰的引用赋值后无法改变,且无法被垃圾回收器回收
修饰符名 | 使用权限 |
---|---|
public | 表示公开的,在任何位置都可以访问 |
protected | 表示受保护的,同包、子类可以访问 |
default(缺省) | 在同包可以访问 |
private | 表示私有的,只能在本类中访问 |
类只能使用 public 与 default 修饰
基本语法
[修饰符列表] abstract class 类名{
// 继承抽象类 extends
/*
1. 抽象类无法被实例化
2. final 与 abstract 不能联合使用,关键词是对立的
3. 抽象类可以继承抽象类(实现接口)
4. 抽象类有构造方法,供子类使用
5. 抽象类不一定存在抽象方法,但有抽象方法一定在抽象类中
6. 非抽象子类必须实现所有抽象方法,抽象子类可以不用写抽象方法
*/
public abstract void 方法名(); //抽象方法
}
面试题:Java 语言中没有方法体的方法都是抽象方法(×)
还存在 C++ 底层 native 等,表示调用 JVM 本地程序。
基础语法
[修饰符列表] interface 接口名{
// 实现接口 implements (高扩展性,低耦合)
/*
1. 接口是完全抽象的,抽象类是半抽象。接口是特殊的抽象类
2. 接口内部全部为抽象方法,public abstract 可以省略,常量 public static final 可以省略
3. 接口内部只能定义常亮、抽象方法
*/
public abstract void 方法名(); //抽象方法
}
基础语法
class 类名 extends 父类 implements 接口1,接口2 {
//类与接口没有继承关系,java 语法也允许上下转型
}
class Test{
static class inner1{ //静态内部类
}
class inner2{ //实例内部类
}
public void test(){
class inner3{ //局部内部类
}
}
public static void main(String[] args){
myMath m = new myMath();
m.mysum(new math(){ //匿名内部类,直接实现接口
public int sum(int a,int b){
return a+b;
}
}, 200, 300);
}
}
interface math{
int sum(int a, int b);
}
class myMath{
public void mysum(math c,int a,int b){
return c.sum(a,b);
}
}
public static void main(String[] args){ Result re = a(9); //Result.SUCCESS Result re = a(50); //Result.FAIL Result re = a(99); //Result.ON } public a(int x){ if(x<10){ return Result.SUCCESS }else if(x < 90){ return Result.FAIL }else{ return Result.ON } } enum Result{ SUCCESS,FAIL,ON }
- 专门负责加载类的命令 / 工具(classloader)
- 类加载过程:加载 — 验证 — 准备 — 解析
- 三个类加载器(以此执行,全部找到不执行,双亲委派机制保障安全)
- 启动类加载器:
\jre\lib\rt.jar
JDK核心类库- 扩展类加载器:
\jre\lib\ext\*.jar
扩展类- 应用类加载器:
classpath
类型... 数组名
- 可变长度个数0~N个
- 可变长度参数只能有一个,放在参数最后位置
- 可变长度参数当做一个数组看待
错误:Error 直接子类(发生错误,不可以处理,中止程序执行)
运行时异常(受检异常):Exception — RuntimeException 直接子类(在编写代码可以选择不处理)
编译时异常(非受检异常):Exception 直接子类(在编写代码必须处理)
ObjectThrowableErrorException直接子类RuntimeException直接子类
public class ExceptionTest{ public static void main(String[] args){ doSome(); //可能抛出异常但是未处理,报错(编译时异常) } /*public static void main(String[] args) throws ClassNotFoundException{ doSome(); //解决办法,抛给JVM,程序终止 }*/ //ClassNotFoundException 未找到类异常,属于编译时异常 public static void doSome() throws ClassNotFoundException{ //若存在异常抛给上一级 } }
public class ExceptionTest{ public static void main(String[] args){ try{ doSome(); //捕捉异常 } catch(ClassNotFoundException e){ e.printStackTrace(); } catch(Exception e){ // catch 拦截异常必须从小到大 } } //ClassNotFoundException 未找到类异常,属于编译时异常 public static void doSome() throws ClassNotFoundException{ //若存在异常抛给上一级 } }
public class ExceptionTest{ public static void main(String[] args){ NullPointerException e = new NullPointerException("空指针异常"); String msg = e.getMessage(); //空指针异常,获取异常简单描述 System.out.println(msg); e.printStackTrace(); //输出追踪信息(红字)打印异常堆栈信息,采用异步线程 } }
try{ return; //即使有 return finally 也会执行 System.exit(0); //此时 finally 不执行 }catch{ }finally{ //除了exit,代码一定执行 }
public class MyException extends Exception{ //自定义编译时异常 public MyException(){}; public MyException(String s){ super(s); }; } public class MyException extends RuntimeException{ //自定义运行是异常 public MyException(){}; public MyException(String s){ super(s); }; } public static void th() throws MyException{ throw new MyException("手动抛出自定义异常") //抛出自定义异常 } public static void main(String[] args){ try{ //捕捉自定义异常 th(); }catch{ System.out.println(e.getMessage()); //抛出异常信息 } }
public int m(){ //返回结果100 int i = 100; try{ return i; }finally{ i++; //一定执行 } } //反编译结果 public int m(){ //返回结果100 int i = 100; int j = i; i++; return j; }
java.util.*
所有集合与集合接口都在包下- 集合是一个容器,是一个载体,可以一次容纳多个对象
- 集合不能直接存储基本数据类型,不能直接存储 java 对象,存储的是引用(内存地址)
使用泛型后,List集合只允许存储对应引用数据类型数据,用泛型指定存储数据类型
List<Integer> myList = new ArrayList<Integer>(); Iterator<Integer> li = myList.iterator(); //泛型迭代器声明
**优点:**统一存储元素数据类型,不需要大量下转型
**缺点:**导致存储元素缺少多样性
List<Integer> myList = new ArrayList<>(); //自动类型推断(钻石表达式)
class MyIterator<T>{ //<>内部为标识符可以随意些,一般为E(element)和T(type) public T get(){ return null; } public static void main(){ MyIterator<Integer> it = new MyIterator<>(); String s1 = it.get(); //泛型指定为Integer类型,可以调用泛型内部方法 } }
int[] arr = {100,200,300} for(int i : arr){ //没有下标 System.out.println(i); }
List<String> myList = new ArrayList<>(); myList.add("www"); myList.add("baidu"); myList.add("com"); for(String s : myList){ System.out.println(s); }
没有使用"泛型"可以存储Object所有子类型,使用"泛型"只能存储具体的类型
boolean add(Object e)
Collection c = new ArrayList(); c.add(1230); //增加元素 c.add(new Object); c.add(true);
int size()
c.size(); //返回集合中元素个数 3
void clear()
c.clear(); //清空元素集合
boolean contains(Object e)
c.add(123); c.contains(333); //false //集合内部存储的是内存地址 String s1 = new String("赵宗泽"); c.add(s1); String s2 = new String("赵宗泽"); c.contains(s2); //本身不包含s2,但内部调用equals(重写过)方法,比较内容 结果为true
boolean remove(Object e)
c.remove(123); //移除元素 //集合内部存储的是内存地址 String s1 = new String("赵宗泽"); c.add(s1); String s2 = new String("赵宗泽"); c.remove(s2); //重写equals两者都删除,不重写equals则删除s2
boolean isEmpty()
c.isEmpty(); //true 判断是否为空
Object[] toArray()
c.add(123); c.add(true); c.add(5.2); Object[] objs = c.toArray(); //{123,true,5.2}
以下方式是 Collection 通用方式,Map 集合不可以使用
集合结构(包括增删元素)发生改变,迭代器必须重新获取,否则会报异常
获取迭代对象,相当于获取当前集合快照,所以改变会报异常
Collection c = new ArrayList(); c.add(1230); //增加元素 c.add(new Object); c.add(true); Iterator it = new Iterator(); //取得集合迭代器
boolean hasNext = it.hasNext(); //判断时候还有元素可以迭代 Object obj = it.next(); //取到指向元素 while(it.hasNext()){ //循环取出所有元素 Sytem.out.println(it.next()); }
it.remove(); //利用迭代器删除当前指向元素(迭代器不会报异常)
List 有下标可重复
void add(int index,E element)
List myList = new LinkedList(); myList.add('a'); //下标从0开始 myList.add('b'); myList.add('c'); myList.add(1,'d'); myList.add('b'); myList.add('f'); //{'a','d','b','c','b','f'}
void remove(int index)
myList.remove(5); //{'a','d','b','c','b'}
E get(int index)
Object obj = myList.add(2); //'b'
E set(int index,E element)
myList.set(3,"c2"); //{'a','d','b','c2','b'}
int indexOf(Object o)
int i =myList.indexOf('b'); //2
int lastIndexOf(Object o)
int i =myList.lastIndexOf('b'); //4
- 默认容量为0,点击第一个元素初始化容量10,底层为Object[],可以指定初始化容量长度
- 容量不足扩容1.5倍,减少扩容
- 向数组末尾添加元素效率很高,最常用为ArrayList,检索操作更多。
List l1 = new ArrayList(); //默认长度为0,添加第一个元素初始化容量为10 List l2 = new ArrayList(100); //设置长度初始化 Collection c = new HashSet(); c.add(100); c.add(200); List l3 = new ArrayList(c); //传出Collection类型初始化元素
LinkedList同样有下标,但是检索查找效率较低,因为内存地址不连续
默认容量为10,容量不足扩容2倍
不安全线程 ArrayList 转为安全线程,使用
java.util.collections
集合工具类List myList = new ArrayList(); //线程是不安全的 Collections.synchronizedList(myLsit); //变成线程安全的 myList.add(1); myList.add(2); myList.add(3);
V put(K key, V value)
Map<Integer, String> map = new HashMap<>(); map.put(1,"zzz"); //添加键值对 map.put(2,"ccc"); map.put(3,"aaa");
V get(Object key)
String a = map.get(2); //"ccc" 通过key获取value
void clear()
map.clear(); //清空Map集合
boolean containsKey(Object key)
//注意:contains方法内部调用equals进行比对,自定义类型重写equals方法 map.containsKey(2); //判断Map中是否包含key,返回true与false
boolean containsValue(Object value)
map.containsValue("ccc"); //判断Map中是否包含value,返回true与false
boolean isEmpty()
map.isEmpty(); //判断Map元素个数是否为0,返回true与false
V remove(Object key)
map.remove(2); //通过key删除键值对
int size()
int a = map.size(); //获取Map集合中键值对数量
Set keySet()
//获取Map集合所有的key,返回一个Set Set<Integer> keys = map.keySet();
Collection values()
//获取Map集合中所以的value,返回一个Collection Collection<String> values = map.values();
Set
> entrySet() //将Map集合转换为成Set集合,Map.Entry是Map中的静态内部类 Set<Map.Entry<Integer,String>> set = map.entrySet(); //遍历Map Iterator<Map.Entry<Integer,String>> it = set.iterator; while(it.hasNext()){ Map.Entry<Integer,String> node = it.next(); Integer key = node.getKey(); //Entry自带方法,适合大数据量 String value = node.getValue(); }
- 无序(存放链表不定)不可重复(value覆盖)
- HashMap集合的key会调用两个方法,一个hasCode(),一个equals(),两个方法都要重写
- hasCode设定为同一个值,则形成单链表,称为散列分布不均匀;hasCode设定为不同值,则形成一维数组,也称为散列分布不均匀;保证hasCode值得到每一个下标的概率相同,称为散列分布均匀
- HashMap默认初始容量为16(必须是2的倍数,可以达到散列分布均匀,提高存储效率),默认加载因子为0.75(数组容量达到75%,数组扩容),扩容为原来的2倍
- HashMap允许key和value为null(Hashtable的key与value不可以为null,报异常)
- equals方法重写,hasCode方法一定也要重写,且当equals为true,hasCode一定为true
- 两个方法重写利用IDE直接生成
哈希表是数组与单链表的结合体,发挥各自的优点
public class HashMap{ //HashMap 底层是一位数组 Node<K,V>[] table; //静态内部类 HashMap.Node static class Node<K,V>{ final int hash; //哈希值,通过 key 的 hasCode() 方法结果,hash值通过哈希函数/算法,可以转换成数组的下标 final K key;//存储到Map集合中的key V value;//存储到Map集合中的value Node<K,V> next;//下一个节点的地址 } }
- 将k,v封装到node对象中
- 底层调用k的hasCode()方法得出hash值,通过哈希算法,将hash值转换为数组下标
- 若下标无元素直接将Node添加到该位置,如下标存在链表,则用k与链表中每一个节点进行equals比较,如果无相同k节点,则插入到尾部,如存在相同k,则覆盖v值
- 数组下标如果为null,不需要执行equals
- 调用k的hasCode()方法得出hash值,通过hash算法转换为数组下标
- 如果数组下标无元素,返回null,如果下标存在链表,则用k与链表中每一个节点进行equals比较,如果无相同节点,返回null,如有相同节点,返回该节点v值
- 数组下标只有一个元素,不需要执行equals
如果哈希表单链表节点超过8个,将单链表转换为红黑树数据结构;当红黑树上节点小于6个,将红黑树转换为单链表数据结构。
- HashMap默认初始容量为11,默认加载因子为0.75(数组容量达到75%,数组扩容),扩容为原来的2倍+1
- Hashtable的key与value不可以为null,报异常(HashMap允许key和value为null)
- Properties是一个Map集合,key与value都是String类型,被称为属性类对象
setProperty
Properties pro = new Properties(); pro.setProperty("url","ww.baidu.com"); //写键值对 pro.setProperty("name","zzz");
getProperty
String s = pro.getProperty("url"); //读键值对
- TreeSet集合底层是一个TreeMap,TreeMap底层集合是一个二叉树
- TreeSet集合中的元素,等同于放在TreeMap集合的key部分
- 二叉树采用中序排列
TreeSet<String> ts = new TreeSet<>(); ts.add("wang"); ts.add("zhang"); ts.add("ayu"); //{"ayu","wang","zhuang"} 自动排序
- Comparable是java.lang包下的,Comparator是java.util包下的
- 当规则不发生变化且只有一个的时候,建议实现Comparable接口;当比较规则有多个且切换比较频繁,建议使用Comparator接口
- Comparator 接口设计符合而OCP原则
自定义类如何排序(方法一)
class 类名 implements Comparable<比较类名>{ int age; //接收参数 > 自身 返回正数为倒叙 public int conpareTo(类名 o){ //实现接口方法 if(this.age == o){ return 0; //相等返回0 }else if(this.age > o){ return 1; //返回正数 }else if(this.age < o){ return -1; //返回负数 } } }
自定义类如何排序(方法二)
//比较器实现Comparator接口 public class test{ public static void main(String[] args){ TreeSet<类名> ts = new TreeSet<>(new 类名比较器()); //构造器传参 } } class 类名 implements Comparable<比较类名>{ int age; } class 类名比较器 implemenets Comparator<比较类名>{ //比较器 public int conpare(类名 o1, 类名 o2){ if(o1 == o2){ return 0; }else if(o1 > o2){ return 1; }else if(o1 < o2){ return -1; } } }
synchronizedList
//将不安全线程变为安全线程 List<String> list = new ArrayList<>(); Collections.synchronizedList(list);
sort
//元素排序(自定义类要实现Comparable接口) list.add("abc"); list.add("adc"); list.add("ebc"); Collections.sort(list); //元素排序,传递比较器 Collections.sort(List, 比较器); //对Set集合进行排序 Set<String> set = new HashSet<>(); set.add("abc"); set.add("accc"); set.add("eec"); List<String> list = new ArrayList<>(set); //将Set转化为List进行排序 Collections.sort(list);
- java中所有流在
java.io.*
下- 所有流都实现了
java.io.Closeable
接口,都有close()方法,每次使用完关闭,不关闭会占用很多资源。- 所有输出流都实现了
java.io.Flushable
接口,都有flush()方法,每次输出完刷新,将未输出完的剩余数据强行输出,管道清空。
按照流的方向分类
- 输入流:(读)InputStream
- 输出流:(写)OutputStream
按照读取数据方式分类
字节流:按照字节的方式读取数据,一次读取1字节byte,万能流什么文件都可以读取
抽象类:
java.io.InputStream
字节输入流、java.io.OutputStream
字节输出流,以Stream结尾字符流:按照字符的方式读取数据,一次读取一个字符,只能读取普通文本文件(不包括word)
抽象类:
java.io.Reader
字符输入流、java.io.Writer
字符输出流,以Reader / Writer结尾
//文件专属 java.io.FileInputStream //字节 java.io.FileOutputStream java.io.FileReader //字符 java.io.FileWriter //转换流(字节流转换成字符流) java.io.InputStreamReader java.io.OutputStreamWriter //缓冲流专属 java.io.BufferedReader //自带缓冲区的数据流,不需要数组 java.io.BufferedWriter java.io.BufferedInputStream java.io.BufferedOutputStream //数据流专属 java.io.DataInputStream //写入数据与类型,文本文档打不开 java.io.DataOutputStream //标准输出流 java.io.printWriter java.io.printStream //默认输出控制台 //对象流专属 java.io.ObjectInputStream //反序列化 DeSerialize 文件恢复成java对象 java.io.ObjectOutputStream //序列化 Serialize java对象存储到文件
public class FileInputStream{ public static void main(String[] args){ FileInputStream fis = null; try{ //_创建流 fis = new FileInputStream(路径); //_循环方法一 int readData = 0; while((readData = fis.read()) != -1 ){ System.out.println(readData); } //_循环方法二 int readData = 0; byte[] bytes = new byte[4]; while((readData = fis.read(bytes)) != -1){ System.out.println(new String(bytes,0,readData)); } //_构造方法一 int readData = fis.read(); //返回读到字节本身,失败返回-1 //_构造方法二 byte[] bytes = new byte[4]; //如若剩余2字节,会覆盖01下标,23下标属于为上次数据 int readData = fis.read(bytes); //返回读到几个字节,失败返回-1 //_转换读取内容 new String(bytes,0,readData); //字节数组指定位置转为字符串 //_返回流中剩余的字节数量 fis.available(); byte[] bytes = new byte[fis.available()]; //可用于一次性读取(不适合大文件) //_跳过字节不读取 fis.skip(3); }catch(FileNotFoundException e){ //此为创建流异常 e.printStackTrace(); }catch(IOException e){ //此为read异常 e.printStackTrace(); }finally{ //finally内部关闭流 if(fis != null){ //判断流是否为null try{ fis.close(); //此为关闭流异常 }catch(IOException e){ e.printStackTrace(); } } } } }
public class FileOutputStream{ public static void main(String[] args){ FileOutputStream fos = null; try{ //_创建流,文件不存在自动创建 fos = new FileOutputStream(路径, true); //true为末尾添加,false为覆盖 //_写数据 byte[] bytes = {97,98,99,100}; fos.write(bytes); //全部输出 fos.write(bytes,0,2); //输出一部分 //_刷新 fos.flush(); }catch(FileNotFoundException e){ //此为创建流异常 e.printStackTrace(); }catch(IOException e){ //此为read异常 e.printStackTrace(); }finally{ //finally内部关闭流 if(fos != null){ //判断流是否为null try{ fos.close(); //此为关闭流异常 }catch(IOException e){ e.printStackTrace(); } } } } }
- 使用 FileInputStream + FileOutputStream 完成文件拷贝
- 拷贝过程一边读一边写,什么文件都可以拷贝
public class FileOutputStream{ public static void main(String[] args){ FileInputStream fis = null; FileOutputStream fis = null; try{ fis = new FileInputStream(路径); fos = new FileOutputStream(路径, true); //一边读一边写 byte[] bytes = new byte[1024*1024] //一次拷贝1MB int readCount = 0; while((readCount = fis.read(bytes)) != -1){ fos.write(bytes,0,readCount); } fos.flush(); }catch(FileNotFoundException e){ e.printStackTrace(); }catch(IOException e){ e.printStackTrace(); }finally{ if(fis != null){ //分开try,避免其中一个出现异常,另一个无法关闭 try{ fis.close(); }catch(IOException e){ e.printStackTrace(); } } if(fos != null){ try{ fos.close(); }catch(IOException e){ e.printStackTrace(); } } } } }
FileReader reader = null; try{ reader = new FileReader(路径); int readData = 0; char[] chars = new char[4]; //把byte数组编程char数组即可 while((readData = fis.read(chars)) != -1){ System.out.println(new String(chars,0,readData)); } }
FileWrite write = null; try{ write = new FileWrite(路径, true); char[] chars = {'我','中','国','人'}; //把byte数组编程char数组,且可写字符 write.write(chars); write.write(chars,0,2); write.flush(); }
- 使用 FileReader + FileWriter 完成文件拷贝
- 拷贝过程一边读一边写,只能拷贝普通文本
FileReader reader = null; FileWrite write = null; try{ reader = new FileReader(路径); write = new FileWrite(路径, true); int readData = 0; char[] chars = new char[1024*512]; //一次拷贝1MB while((readData = fis.read(chars)) != -1){ write.write(chars,0,readData); } write.flush(); }
public class BufferedReader{ public static void main(String[] args) throws Exception{ /*当一个流的构造方法中需要一个流的时 被传进去叫:节点流;外部负责包装的流叫:包装流(处理流) FileReader是节点流,BufferedReader是包装流*/ //_字节流传入 FileReader reader = new FileReader(路径); BufferedReader br = new BufferedReader(reader); //传入字符流,不能传字节流 //_字符流传入 FileInputStream in = new FileInputStream(路径); //_转换流 InputStreamReader reader = new InputStreamReader(in); //将字节流转为字符流 BufferedReader br = new BufferedReader(reader); //_循环读取一行 String s = null; while((s = br.readLine()) != null){ System.out.println(s); } //_读一行 br.readLine(); //读取失败返回null //包装流关闭,节点流自动关闭 br.close(); } }
public class BufferedWriter{ public static void main(String[] args) throws Exception{ //_字节流传入 FileWriter writer = new FileWriter(路径); BufferedWriter out = new BufferedWriter(writer); //传入字符流,不能传字节流 //_字符流传入 FileOutputStream ou = new FileOutputStream(路径); //_转换流 OutputStreamWriter writer = new OutputStreamWriter(ou); //将字节流转为字符流 BufferedWriter out = new BufferedWriter(writer); out.write(); out.flush(); out.close(); } }
public class DataOutputStream{ public static void main(String[] args) throws Exception{ DataOutputStream dos = new DataOutputStream(new FileOutputStream(路径)); byte b = 100; //写入数据与数据类型 int i = 50; boolean bo = false; char c = 'a'; dos.writeByte(b); dos.writeInt(i); dos.writeBoolean(bo); dos.writeChar(c); dos.flush(); dos.close(); } }
public class DataInputStream{ public static void main(String[] args) throws Exception{ DataInputStream dis = new DataInputStream(new FileInputStream(路径)); //读取与写入顺序要相同 byte b = dis.readByte; //写入数据与数据类型 int i = dis.readInt; boolean bo = dis.readBoolean; char c = dis.readChar; dos.flush(); dos.close(); } }
public class printStream{ public static void main(String[] args) throws Exception{ //_输出到控制台 printStream ps = System.out; ps.println("Hello world"); ps.println("Hello java"); //标准输出流不需要关闭 //_输出到文件 printStream ps = new printStream(new FileInputStream(路径)); System.setOut(ps); ps.println("Hello world"); ps.println("Hello java"); } }
public class Logger{ public static void log(String msg){ try{ //指向日志文件 printStream ps = new printStream(new FileInputStream(路径,true)); //改变输出方向 Sytem.setOut(ps); //获取日期 Date nowTime = new Date(0); SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss SSS"); String strTime = sdf.format(nowTime); System.out.println(strTime + ":" + msg); }catch(FileNotFoundException e){ e.printStackTrace(); } } }
public class ObjectOutputStream{ public static void main(String[] args) throws Exception{ //创建java对象 Student o = new Student(); //序列化 ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream(路径)); //序列化对象 oos.writeObject(s); //创建集合 List<Student> st = new Student<>(); st.add(new Student(1,"xxx")); st.add(new Student(2,"zzz")); st.add(new Student(3,"www")); //序列化集合 oos.writeObject(st); oos.flush(); oos.close(); } } //序列化对象必须实现接口:Serializable 只是一个标志接口,起标识作用,JVM自动生成序列化版本号 //序列化版本号用于区分不同类,自动生成的序列化版本号存在不可更改代码的缺点,代码修改编译会重新生成,建议手动写序列化版本号。 class Student implements Serializable{ //java虚拟机先识别类名,当类名一样识别序列号 private static final long serialVersionUID = -11568497521542368L; public int no; public transient String name; //transient 关键字,不参加序列化 public Student(int no,String name){ this.no = no; this.name = name; } }
public class ObjectInputStream{ public static void main(String[] args) throws Exception{ //创建java对象 Student o = new Student(); //反序列化 ObjectInputStream ois = new ObjectInputStream(new FileInputStream(路径)); //反序列化对象 Object obj = ois.readObject(); //反序列化集合 List<Student> st = (List<Student>)ois.readObject(); for(Student s : st){ //输出s } oos.close(); } } //序列化对象必须实现接口:Serializable 只是一个标志接口,起标识作用,JVM自动生成序列化版本号 class Student implements Serializable{ private static final long serialVersionUID = -11568497521542368L; public int no; public transient String name; //transient 关键字,不参加序列化 }
//写属性配置文件,建议以.properties结尾,Properties专门存属性配置的一个类 public class IoProperties{ public static void main(String[] args){ /*文件内容 username=zzz root=xxx */ FileReader reader = new FileReader(路径); //新建一个输入流 Properties pro = new Properties(); //新建一个Map集合 pro.load(reader); //调用load加载数据到Map,=左边为key,右边为value pro.getProperty("username") //获取username值 } }
- 进程
- 进程是一个应用程序(软件)
- 内存独立不共享
- 一个进程可以启动多个线程
- 线程
- 线程是一个进程中执行的场景 / 执行单元
- 在Java中堆内存和方法区内存共享,栈内存不共享,一个线程一个栈互不干扰。
用户线程:main方法
守护线程(后台线程):立即回收线程,一般是一个死循环,所有用户线程结束,守护线程自动结束。用于数据备份等。
Thread t = new Thread(); t.setDaemon(true); //设置为守护线程,程序结束,自动终止 t.start();
抢占式调度模型
线程优先级比较高,抢到CPU时间片的概率就会高一些,java采用抢占式调度模型
均分式调度模型
平局分配CPU时间片,每个线程占有CPU时间片的时间长度一样
安全问题存在时机
- 多线程并发
- 有共享数据
- 共享数据有修改行为(局部变量在栈中不共享,不存在线程安全问题)
解决线程安全问题
线程排队执行(不能并发),这种机制被称为“同步机制”,会牺牲一部分效率。
- 尽量使用局部变量代替实例变量和静态变量
- 必须是实例对象,考虑创建多个对象,实例变量不共享
- 不能使用局部变量,也不可以创建多个对象,使用synchronized线程同步机制
专业术语
异步编程模型
线程互不等待,多线程并发(效率较高)
同步编程模型
线程发生等待关系,线程排队执行(效率较低)
synchronized
//线程同步执行 //锁代码块 synchronized(多线程共享对象){ //同步代码块,越小效率越高 } public synchronized void 方法名(){ //同步整个方法体,可能无故扩大同步范围,导致执行效率降低;锁对象只能是this; } public synchronized static void 方法名(){ //synchronized出现在静态方法上为类锁,占据整个类 }
安全性类
- 局部变量推荐StringBuilder,不存在安全性问题,StringBuffer效率比较低
- ArrayList是非线程安全的,Vector是线程安全的
- HashMap / HashSet是非线程安全的,Hashtable是线程安全的
死锁
- 例:线程a先锁1,再锁2,线程b先锁2,再锁1,造成相互等待
- synchronized不要嵌套使用,容易造成死锁
方法一:继承
java.lang.Thread
父类,重写run方法public class Thread { public static void main(String[] args){ //main方法属于主线程,在主栈中运行 //创建分支线程 MyThread myThread = new MyThread(); /*调用start方法启动一个分支线程,在JVM中开辟一个新的栈空间,启动的线程自动调用run方法,并且run方法在栈底,相当于main方法,run与main平级*/ myThread.start(); //瞬间结束,启动分支栈就结束,自上而下 for(int i = 0; i < 1000; i++){ System.out.println("主线程:"i); } } } class MyThread extends Thread{ public void run(){ //继承Thread类,切重写run方法 for(int i = 0; i < 1000; i++){ System.out.println("分支线程:"i); } } }
方法二:实现
java.lang.Runnable
接口,重写run方法public class Thread { public static void main(String[] args){ //main方法属于主线程,在主栈中运行 //创建一个可运行的对象 MyRunnable r = new MyRunnable(); //将可运行的对象封装成一个线程对象 Thread t = new Thread(r); //启动线程 t.start(); for(int i = 0; i < 1000; i++){ System.out.println("主线程:"i); } } } class MyThread implements Runnable{ public void run(){ //继承Thread类,切重写run方法 for(int i = 0; i < 1000; i++){ System.out.println("分支线程:"i); } } }
方法三:实现
java.util.concurrent.FutureTask
接口,重写call方法,可获取线程返回值FutureTask task = new FutureTask(new Callable(){ public Object call() throws Exception{ //等同于run //线程执行任务可能存在执行结果 return null; } }); Thread t = new Thread(task); t.start(); Object obj = task.get(); //获取线程返回值,等待线程结束返回结果,进入阻塞
- 五大生命周期状态(进入锁池可以理解为阻塞)
//当线程没有设置名字,默认名字为 //Thread-0 //Thread-1 //... t.setName("名字"); String s= t.getName();
static Thread currentThread(); //获取当前线程 Thread t = Thread.currentThread();
//static void sleep(long millis) 静态方法,参数为毫秒,使当前线程进入阻塞状态 //在哪调用,休眠哪个线程!!! 对象.sleep();不等同于休眠该对象 try{ Thread.sleep(1000*5); //休眠5秒 }catch(InterruptedException e){ e.printStackTrace(); }
t.interrupt(); //中止 t 线程的睡眠(抛出异常进入catch,依靠java的异常处理机制)
t.stop(); //强行终止 t 线程,容易丢失数据,不建议使用
public class Thread { public static void main(String[] args){ MyRunnable r = new MyRunnable(); Thread t = new Thread(r); t.start(); r.run = false; //终止线程 } } class MyThread implements Runnable{ boolean run = true; //布尔值标记 if(run){ //判断布尔终止标记 public void run(){ for(int i = 0; i < 1000; i++){ System.out.println("分支线程:"i); } } }else{ //终止线程,可以保存数据 return; } }
getPriority / setPriority(实例方法)
/*最低优先级1 Thread.MIN_PRIORITY 默认优先级5 Thread.NORM_PRIORITY 最高优先级10 Thread.MAX_PRIORITY*/ int getPriority(); //获取线程优先级 void setPriority(int newPriority); //设置线程优先级
yield (静态方法)
/*暂停当前执行的线程,执行其他线程 不是阻塞方法,从“运行状态”转为“就绪状态” */ static void yield(); //让位方法
join(实例方法)
void join(); //合并线程 class MyThread1 extends Thread{ public void doSome(){ MyThread2 t = new MyThread(); t.join(); //当前线程进入阻塞,t 线程执行,直到 t 线程结束,当前线程才开始执行 } } class MyThread1 extends Thread{}
java.util.Timer
Timer timer = new Timer(true); //设置true为守护线程 timer.schedule(定时任务,第一次执行时间,间隔时间); class 类名 extends TimerTask{ //继承接口 public void run(){ //定时任务 } }
//wait / notify方法建立在synchronized基础上 Object obj = new Object(); obj.wait();//对象上的当前线程进入无期限的等待状态,并且释放对象的锁,直到调用nodify方法 obj.nodify(); //唤醒对象上等待的线程
通过java反射机制可以操作字节码文件(可以读和修改字节码文件)
java.lang.reflect.*
java.lang.Class
:代表整个字节码,代表一个类。java.lang.reflect.Method
:代表字节码中的方法字节码java.lang.reflect.Constructor
:代表字节码中的构造方法子字节码java.lang.reflect.Field
:代表字节码中的属性字节码
方法一:Class.forName静态方法
/*1.静态方法 2.方法参数是一个字符串 3.字符串需要的是一个完整类名 4.完整类名必须带包名,java.lang包不能省略*/ //c1代表String.class文件,或者说代表String类型 Class c1 = Class.forName("java.lang.String");
方法二:getClass实例方法
String s = "abc"; Class x = s.getClass(); //x代表String.class文件,或者说代表String类型
方法三:.class属性
Class z = String.class; //z代表String.class文件,或者说代表String类型
//实例化对象(会调用无参数构造方法与静态代码块[即类加载],若不存在无参构造方法会报异常) Object obj = c1.newInstance();
/*Thread.currentThread() 当前线程对象 getContextClassLoader() 线程对象方法,获取当前线程类加载器对象 getResource("") 类加载器对象方法,默认从类的根路径下加载资源 */ //获取绝对路径读取 String path = Thread.currentThread() .getContextClassLoader() .getResource("根路径相对路径") .getpath(); FileReader reader = new FileReader(path); //以流的方式读取 InputStream reader = Thread.currentThread() .getContextClassLoader() .getResourceAsStream("根路径相对路径"); //读取内容 Properties pro = new Properties(); pro.load(reader); reader.close();
java.util
包下提供一个资源绑定器,便于获取属性配置文件,调用绑定器,属性配置文件xxx.properties必须放在类的路径下(包含子目录,相对路径)ResourceBundle bundle = ResourceBundle.get("配置名不带后缀,在类路径下"); String className = bundle.getString("key值");
public class S{ public int no; protected float f; boolean i; private char sex; } public class Field{ public static void main(String[] args) throws Exception{ Class s = Class.forName("S"); s.getName(); //获取完整类名 s.getSimpleName();//获取简类名(不带包名) Field[] fields = s.getFields(); //取出 public 成员变量 Field[] fields = s.getDeclaredFields(); //取出所有成员变量 String fn = f[0].getName(); //取属性的名字 Class ft = f[0].getType(); //取属性的类型 String ftn = ft.getname(); //取属性的类型名字(带包名) String ftn = ft.getSimplename(); //取属性的类型名字(不带包名) int i = field.getModifiers(); //返回修饰符编号 String s = Modifier.toString(i); /*—————————————————————————————— 反 编 译 ————————————————————————————*/ Object obj = s.newInstance(); Field noField = s.getDeclaredField("no"); noField.set(obj, 2222); //给属性赋值 noField.get(obj); //获取属性的值 //若为私有属性,调用打破封装 noField.setAccessible(true); } }
Class s = Class.forName("S"); //获取所有method方法名 Method[] methods = s.getDeclaredMethods(); for(Method me : methods){ Modifier.toString(method.getModifiers()); //取修饰符列表 me.getReturnType().getSimpleName(); //取返回值类型 me.getName(); //取方法名 Class[] cl = method.getParameterTypes(); //获取所有参数类型 for(Class c : cl){ c.getSimpleName(); //获取参数类型 } } /*—————————————————————————————— 反 编 译 ————————————————————————————*/ Object obj = s.newInstance(); Method me = s.getDeclaredMethod("方法名",类型名.class,...); //获取方法 Object revalue = me.invoke(obj, 参数1, 参数2,...); //调用方法
Class s = Class.forName("S"); //获取所有method方法名 Constructor[] cos = s.getDeclaredConstructors(); for(Constructor co : cos){ Modifier.toString(co.getModifiers()); //取修饰符列表 co.getSimpleName(); //取构造方法名 Class[] cl = co.getParameterTypes(); //获取所有参数类型 for(Class c : cl){ c.getSimpleName(); //获取参数类型 } } /*—————————————————————————————— 反 编 译 ————————————————————————————*/ Constructor con = s.getDeclaredConstructor(类型名.class,...); //获取构造方法 Object ob = con.newInstance(参数1, 参数2,...); //调用方法
Class s = Class.forName("java.lang.String"); Class superClass = s.getSuperclass(); //获取父类 superClass.getName(); //获取父类名字 Class[] interfaces = s.getInterfaces(); //获取接口 for(Class in : interfaces){ in.getName(); //获取接口名字 }
注解类型:Annotation,是一种引用数据类型,会生成.class文件,可以出现在任何上方,注解是给编译器参考的,与运行阶段无关。
元注解:用来标注“注解类型”的“注解”,成为元注解。
Tatget
Retention
[修饰符列表] @interface 注解名{ //可包含属性,属性名为value时,调用可以省略名字 //属性类型可以是基本数据类型,String,Class,枚举,数组(数组调用只有1个元素大括号可以省略) }
@Override 只能注解方法,判断是否重写父类方法 @Target 标注注解可以出现哪个类型上 @Retention() 标注注解最总保存的位置 RetentionPolicy.SOURCE:注解只保留在java源文件中 RetentionPolicy.CLASS:注解保存在class文件中 RetentionPolicy.RUNTIME:注解保存在class文件中,并且可以被反射机制读取 @Deprecated 注解表示已过时
protected Object clone(); //负责对象克隆 protected native Object clone() throws CloneNotSupportedException;
int hasCode(); //获取对象哈希值,可以看做内存地址 public native int hasCode(); //源代码
boolean equals(Boject obj); //判断两个对象是否相等(对象比较内存地址,建议重写),String 类已重写该方法 public boolean equals(Boject obj) { if(obj == null || !(obj instanceof 类型)) //地址为空或类型不同 return false; if(this == obj) //地址相同为同一元素 return true; if(成员变量比较) return true; return false; }
String toString(); //将对象转换为字符串(建议重写),String 类已重写该方法 public String toString() { return 成员变量组合; }
protected void finalize(); // 不需要手动调用,JVM垃圾回收器负责调用,在即将销毁时调用 protected void finalize() throws Throwable { System.out.println("即将被销毁"); //当即将被销毁时输出 } System.gc(); //建议启动垃圾回收器(不一定启动)
Arrays.binarySearch(a,'a'); //二分法查找前先排序,查找数组 a 中元素 'a'
Arrays.sort(a); //排序数组 a
//方法一:创造字符串(最常用) String a = "Hello world"; System.out.println(a); //结果为 Hello world //方法二:传入byte数组 byte[] bytes = {97,98,99}; String b = new String(bytes); System.out.println(b); //结果为 abc //方法三:传入byte数组,与起始下标和长度 byte[] bytes = {97,98,99}; String c = new String(bytes,1,2); System.out.println(c); //结果为 bc //方法四:传入char数组 char[] chars = {'赵','宗','泽'}; String d = new String(chars); System.out.println(d); //结果为 赵宗泽 //方法五:传入char数组,与起始下标和长度 char[] chars = {'赵','宗','泽'}; String e = new String(chars,1,2); System.out.println(e); //结果为 宗泽 //方法五:传入字符串 String f = new String("Hello world"); System.out.println(e); //结果为 Hello world
char a = "赵宗泽".charAt(1); //宗
int a = "abc".compareTo("abc"); //0 int a = "aba".compareTo("abc"); //-1 int a = "abc".compareTo("aba"); //1
"helloworld.java".contains(".java"); //true
"test.txt".endWith(".txt"); //true "test.txt".startWith("te"); //true
"aBc".equalsIgnoreCase("abc") //true
byte[] bytes = "abcde".getBytes(); //{97,98,99,100,101}
"abcdecd".indexOf("cd"); //2 "abcdecd".lastIndexOf("cd"); //5
String a = ""; a.isEmpty(); //true a = null; a.isEmpty(); //空指针异常
String newString = "www.baidu.com".replace("baidu","bilibili"); //www.bilibili.com
String[] a = "1980-10-11".split("-"); //{"1980","10","11"}
"http://www.baidu.com".substring(7); //www.baidu.com "http://www.baidu.com".substring(7,10); //www(左闭右开)
char[] chars = "赵宗泽".toCharArray(); //{'赵','宗','泽'}
"AbcdEFGh".toLowerCase(); //abcdefgh "AbcdEFGh".toUpperCase(); //ABCDEFGH
" 我是 中 国 人 ".trim() //我是 中 国 人
//String 中唯一的静态方法 String.valueOf(true); //"true" String.valueOf(new Object()); //没重写toString()方法之前返回对象内存地址
- 判断数组长度是 length 属性,判断字符串长度是 length() 方法
StringBuffer中的方法都有
:synchronized
关键字修饰,表示在多线程环境下是安全的StringBuilder 中的方法都没有
:synchronized
关键字修饰,表示在多线程环境下是不安全的
//StringBuffer 底层是以数组的方式存贮字符串 //优化:在创建时尽可能给定合适的初始容量,较少扩容次数 StringBuffer stringbuffer = new StringBuffer(); //创建一个初始化 16 个 byte[] 数组 StringBuffer stringbuffer = new StringBuffer(100); StringBuilder stringbuilder = new StringBuilder(); //创建一个初始化 16 个 byte[] 数组
//底层数组追加,若数组已满,会自动扩容 stringbuffer.append("a"); stringbuffer.append(3.14); stringbuffer.append(true);
基本数据类型 包装类型 父类 byte java.lang.Byte Number short java.lang.Short Number int java.lang.Integer Number long java.lang.Long Number float java.lang.Float Number double java.lang.Double Number boolean java.lang.Boolean Object char java.lang.Character Object
Integer x = new Integer(100); //传入int Integer y = new Integer("200"); //传入String
//装箱:基本数据类型 — 转为 — 引用数据类型 Integer i = new Integer(123); //拆箱:引用数据类型 — 转为 — 基本数据类型 i.floatValue(); //123.0 i.intValue(); //123 //JDK 1.5 之后支持自动装箱 / 拆箱 Integer i =100; //装 int y = i; //拆
// 注意:为提高程序执行效率,类加载[-128 ~ 127]自动存放到整数常量池中 Integer a = 127; //提前存放,地址相同 Integer b = 127; a == b; //true Integer a = 128; //后期创建,地址不同 Integer b = 128; a == b //false
Integer.MAX_VALUE; //2147483647 Integer.MIN_VALUE; //-2147483648
int a = Integer.parseInt("123") //String 转为 int
import java.util.Date; Date time = new Date(); //获取毫秒级系统当前时间 Date time2 = new Date(1); //970年1月1日0时0分0秒0毫秒 + 1毫秒的时间 Date time2 = new Date(System.currentTimeMillis() - 1000*60*60*24); //昨天的当前时间
//Date 转 String SimpleDateFormat sdf = new SimpleDateFormat("yyyy-mm-dd HH-mm-ss SSS"); String nowtime = sdf.format(time); //String 装 Date SimpleDateFormat sdf = new SimpleDateFormat("yyyy-mm-dd HH:mm:ss SSS"); Date datetime = sdf.parse("2020-02-04 23:24:56 888"); //格式对应
//获取1970年1月1日0时0分0秒0毫秒到当前系统时间的毫秒数 long timeMillis = System.currentTimeMillis();
import java.text.DecimalFormat; //#任意数字 ,代表千分位 .代表小数点 0代表不够补0 DecimalFormat df = new DecimalFormat("###,####.0000"); String s = df.format(123456.89) //123,456.900
//用于财务系统,高精度 import java.math.BigDecimal; BigDecimal a = new BigDecimal(100); BigDecimal b = new BigDecimal(200);
BigDecimal c = a.add(b); //300
import java.util.Random; Random random = new Random();
int a = random.nextInt(); //产生一个int类型取值范围的随机数 int a = random.nextInt(101); //产生一个1~100范围的随机数(不包括101)
File是文件和目录路径的抽象表现形式
File f = new File(路径);
f.exists(); //存在返回true,不存在返回false
if(!f.exists()){ f.createNewFile(); //以文件形式新建 }
if(!f.exists()){ f.mkdirs(); //以目录形式新建 }
//方法一 String parentPath = f.getParent(); //方法二 File parentFile = f.getParentFile(); parentFile.getAbsolutePath(); //获取绝对路径
f.getName(); //获取文件名
f.isDirectory(); //判断是否是一个目录
f.isFile(); //判断是否是一个路径
long l = f.lastModified(); //文件最后修改时间,返回距离1970年的毫秒
f.length(); //获取文件大小,返回字节
File[] files = f.listFiles(); //获取文件夹下的子文件与目录
String - int)
int a = Integer.parseInt("123") //String 转为 int
import java.util.Date; Date time = new Date(); //获取毫秒级系统当前时间 Date time2 = new Date(1); //970年1月1日0时0分0秒0毫秒 + 1毫秒的时间 Date time2 = new Date(System.currentTimeMillis() - 1000*60*60*24); //昨天的当前时间
//Date 转 String SimpleDateFormat sdf = new SimpleDateFormat("yyyy-mm-dd HH-mm-ss SSS"); String nowtime = sdf.format(time); //String 装 Date SimpleDateFormat sdf = new SimpleDateFormat("yyyy-mm-dd HH:mm:ss SSS"); Date datetime = sdf.parse("2020-02-04 23:24:56 888"); //格式对应
//获取1970年1月1日0时0分0秒0毫秒到当前系统时间的毫秒数 long timeMillis = System.currentTimeMillis();
import java.text.DecimalFormat; //#任意数字 ,代表千分位 .代表小数点 0代表不够补0 DecimalFormat df = new DecimalFormat("###,####.0000"); String s = df.format(123456.89) //123,456.900
//用于财务系统,高精度 import java.math.BigDecimal; BigDecimal a = new BigDecimal(100); BigDecimal b = new BigDecimal(200);
BigDecimal c = a.add(b); //300
import java.util.Random; Random random = new Random();
int a = random.nextInt(); //产生一个int类型取值范围的随机数 int a = random.nextInt(101); //产生一个1~100范围的随机数(不包括101)
File是文件和目录路径的抽象表现形式
File f = new File(路径);
f.exists(); //存在返回true,不存在返回false
if(!f.exists()){ f.createNewFile(); //以文件形式新建 }
if(!f.exists()){ f.mkdirs(); //以目录形式新建 }
//方法一 String parentPath = f.getParent(); //方法二 File parentFile = f.getParentFile(); parentFile.getAbsolutePath(); //获取绝对路径
f.getName(); //获取文件名
f.isDirectory(); //判断是否是一个目录
f.isFile(); //判断是否是一个路径
long l = f.lastModified(); //文件最后修改时间,返回距离1970年的毫秒
f.length(); //获取文件大小,返回字节
File[] files = f.listFiles(); //获取文件夹下的子文件与目录