Object类
toString 重写后可以直接打印对象
equals 重写后比较两个对象的内容
ClassCastException : 类型转换异常;
-------------------------------------------------
Objects类 public static boolean equals( Object a, Object b ){...} Objects.equals( Object a, Object b );
null 不能调方法,否则会抛出空指针异常;
--------------------------------------------------
Date类
精确到毫秒,1000毫秒=1秒;
System.currentTimeMillis() 获取当前系统时间(毫秒)
Date 导包 util
Date类的成员方法: public long getTime() 把日期转换为毫秒 date.getTime()
把毫秒转成时间 new Date(毫秒)
把时间转成毫秒 date.getTime 返回long类型的毫秒
获取当前系统时间
Date date = new Date();
Syestem.out.printlu(date);
--------------------------------------------------------
DateFormat抽象(父)类&SimpleDateFormat(子)类
DateFormat 成员方法:String format(Date date)
Date parse(String source)
public SimpleDateFormat(String pattern)
String pattern :指定的模式
y 年
M 月
d 日
H 时
m 分
s 秒
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH-mm-ss");
Date date = new Date();
SimpleDateFormat的对象.format(date) 把日期对象转成指定格式的字符串
Date date=SimpleDateFormat的对象.parse("字符串"); 把符合模式的 字符串解析成Date日期
ParseException解析异常 用throws,或者try ... catch 处理这个异常
------------------------------------------------------------------------------
Calendar类
Calendar c =Calendar.getInstance(); // 多态
public int get()
public void set()
public abstract void add()
public Date getTime()
int year = c.get(Calendar.YEAR) // 获取年份
c.set(Calendar.YEAR,9999) // 设置年为9999年
c.add(Calendar.YEAR,2) // 年份增加2年
c.add(Calendar.MOUTH,-3) // 月份减少3月
-----------------------------------------------------------------
System类
System.currentTimeMillis() 测试程序效率
System.arraycopy(object src,int srcPos,object dest , int destPos, int length)
------------------------------------------------------------------
StringBuilder类
在内存中始终是一个 数组,占用空间少,拼接效率高;
构造方法: public StringBuilder()
public StringBuilder(String str)
成员方法: public StringBuilder append(...) 使用append方法无需接收返回值
StringBuilder sb = new StringBuilder();
StringBuilder sb1=sb.append("abc").append("def")
public String toString()
链式编程:方法的返回值是一个对象,可以根据对象继续调用方法
将String 变成 StringBuilder :
StringBuilder sb = new StringBuilder (str);
将StringBuilder 变成 String:
String s = sb.toString();
-------------------------------------------------------------------------
包装类
装箱:
构造方法:
Integer (int value)
Integer(String s)
静态方法:
static Integer valueOf(int i)
static Integer valueOf(String s)
拆箱:
成员方法:
int intValue()以int类型 返回Integer 的值
自动装箱:
Integer in = 1;
自动拆箱:
in = in + 2;
------------------------------------------------------------------------
基本类型与字符串之间的转换
基本类型-->字符串:
1.基本数据类型的值+“”;
2.包装类的静态方法:
static String toString(int i)
3.使用String类中的静态方法:
static String valueOf(int i)
字符串-->基本类型:
1.public?static?int?parseInt(String?s) :用包装类将字符串参数转换为对应的int基本类型。
int i=Integer.parseInt("100")
-128~127之间的数字存在常量池中,同一个数字,地址值相同,其余范围数字在堆内存中,地址值不同;
Collection接口
集合储存的都是对象。
共性方法:
1.public boolean add(E e) 返回值不用接收,没有意义;
2.public boolean remove(E e) 删除存在的元素,返回true,删除不存在的元素,返回false;
集合中相同的元素,只会删除第一个;
3.public boolean contains(E e) 判断集合中是否包含指定的元素;
4.public boolean isEmpty(E e) 判断集合有没有元素;
5.public int size(); 集合中元素的个数;
6.public Object[ ] toArray(); 把集合的元素储存到数组中;
7.public void clear(); 清空集合中的元素;
-------------------------------------------------------------------------
Iterator<E>接口(迭代器)
常用方法:
boolean hasNext( ) 判断是否达到集合的末尾,是返回false,否返回true;
E next( ) 取出集合中的元素;
Iterator<E>的泛型跟着集合走
Iterator<String> it = coll.iterator( ); 集合调方法得到迭代器
b = it.hasNext( );
s = it.nest( );
优化:
while(it.hasNext){
String s = it.next( );
System.out.println(s);
}
for(String s : coll){
System.out.println(s);
}
----------------------------------------------------------------------------------------
集合按照其储存结构可以分为两大类,分别是单列集合java.util.Collection和双列集合java.util.Map。
Collection: 单列集合类的跟接口,用于储存一系列符合某种规则的元素,它有两个重要的子接口,分别是java.util.List和java.util.Set。其中,List的特点是元素有序、元素可重复。Set的特点是元素无序,而且不可重复。List接口的主要实现类有java.util.ArrayList和java.util.LinkedList,Set 接口的主要实现类有java.util.HashSet和java.util.TreeSet。
---------------------------------------------------------------------------------------------
迭代器的并发修改异常:ConcurrentModificationException
在使用迭代器的过程中,修改了集合的长度,增删了集合的元素;就会抛出这个异常。
创建Iterator 的时候会把集合的修改值复制一份给迭代器,之后如果每增、删集合元素一次,集合的修改值会加1,而迭代器的修改值不变,每次next()取元素的时候会先判断迭代器修改值是否与集合修改值一致,如果不一致就会抛出并发修改异常;
用listIterator的时候,添加元素后会把集合修改值复制给listIterator,所以不会抛出异常;
----------------------------------------------------------------------------------------------
泛型:未知的数据类型
创建对象的时候确定泛型的数据类型
定义泛型的方法:
修饰符 <泛型> 返回值类型 方法名称(参数列表(使用泛型))
调用方法时传的数据是什么类型,泛型就是什么类型。
接口的泛型:
1.定义接口的实现类,实现接口,直接指定接口的泛型;
2.接口使用什么泛型,实现类就用什么泛型。创建对象的时候指定泛型的具体类型。
泛型的通配符:
?:代表任意的数据类型 ,只能作为方法的参数使用。
泛型的上限:此时的泛型,必须是extends后面类的本身或子类;
泛型的下限:此时的泛型,必须是super后面类的本身或者父类;
数据结构
栈:出口和入口在同一侧,先进后出;
队列:出口和入口在两侧,先进先出;
数组:查询快,增删慢;
链表:查询慢(地址不是连续的),增删快;(单向,无序的;双向,有序的);
红黑树:(排序树:左子输小,右子树大,查询快);(平衡树:左孩子和右孩子相等);红黑树趋近于平衡树,查询速度非常快,查询叶子节点最大次数和最小次数不能超过2倍;节点可以是红色或者黑色的。
----------------------------------------------------------------------------
List接口
1.有序的集合,存储元素和取出元素的顺序是一致的;
2.有索引,包含了一些带索引的方法;
3.允许储存重复的元素。
方法:
对象.add(int index,E element );
对象.get(int index);
E e=对象.remove(int index);
E e=对象.set(int index,E element);
ArrayList 实现类,不是同步的,是多线程;底层是数组,查询快,增删快;数组中有索引
LinkedList实现类,底层是双向链表,查询慢,增删快;包含大量操作首尾元素的方法;使用特有方法,不能使用多态;也有get()方法,因为类中维护了索引;
Vector实现类,底层是一个数组,同步的,单线程;
--------------------------------------------------------------------------
Set接口
1.不允许存储重复的元素
2.不带索引,不能使用for循环遍历
HashSet实现类:
1.不允许存储重复的元素
2.没有索引,没有带索引的方法,不能使用for循环
3.是一个无序的集合
4.底层是一个哈希表结构(查询速度非常快)哈希表=数组+链表+红黑树
HashSet为什么去重:每次add的时候先调用hashCode和equals方法比较哈希值和内容。
LinkedHashSet实现类:
1.底层是一个哈希表(数组+链表/红黑树)+链表:多了一条链表记录元素的储存顺序,保证元素有序。
2.有序
3.不允许重复
---------------------------------------------------------------------------
可变参数
使用格式:定义方法时使用
修饰符 返回值类型 方法名(数据类型...变量名){}
注意:一个方法的参数列表,只能有一个可变参数
如果方法的参数有多个,那么可变参数必须写在参数列表的末尾;
终极可变参数:public static viod method ( Object...obj){}
-------------------------------------------------------------------------------
Collections
Collections.addAll(1,2,3,4,5,6) 一次向集合中添加多个元素
Collections.shuffle 打乱集合中元素的顺序
Collections.sort(list) 对list集合升序排序
被排序的集合里面储存的元素必须实现Comparable接口中的compareTo方法;排序规则:自己this-参数:升序;
Collections.sort(list,new Comparator<E>(){重写compare方法})
排序规则:对象比指定对象小,返回-1为降序,返回1为升序;返回0相等
对象比指定对象大,返回1为降序,返回-1为升序;返回0相等
Map<key,value>集合特点
1.Map集合是一个双列集合
2.Map集合中的元素,key和value数据类型可以相同,也可以不同
3.Map集合中的元素,key是不允许重复的,value可以重复;
4.kay和value是一 一对应
方法:
public V put(K key,V value) key 不重复,返回null,重复返回被替换的V;
public V get(K key ) key存在,返回对应的值value,不存在,返回null ;
public V remove(K key) key存在,返回对应的value,key不存在,返回null;
public boolean containsKey(K key) key存在,返回true,key不存在,返回false ;
public Set<K key> keySet() V value = map.get(K key)
public Set<Map.Entry<K key ,V value>> entrySet() Entry 对象中有 getKey() getValue()方法;
---------------------------------------------------------------------------
HashMap
JDK1.8之后 数组+单项链表、红黑树,查询速度特别快,线程不安全 能存空null
是一个无序的集合
LinkedHashMap
底层是哈希表+链表
是一个有序的集合
Hashtable
效率低 线程安全单线程 不能存空null
----------------------------------------------------------------------------------
Collections集合工具类
Collections.shuffle
Collections.addAll
Collections.sort
异常
程序执行过程中,出现的非正常情况,最追导致JVM非正常停止,异常本身是一个类
Throwable是异常顶层父类
Error 错误子类(严重问题) 必须修改源代码
Exception 异常子类 (小毛病)编译期异常
RunTimeException 运行时异常
处理异常:
1.往上抛,给JVM处理,打印异常,终止程序
2.try{}catch(){}处理异常,处理完之后程序继续执行
运行时异常,不用我们写抛异常代码 ; 编译期异常,需要我们写抛异常代码,或者try...catch
--------------------------------------------------------------------------------
throw 关键字 写在方法中 我们自己抛异常,我们可以自定义异常的信息 后面可以跟我们自己new出来的异常
格式:
throw new xxxException("异常产生的原因")
注意:
1.throw关键字必须写在方法的内部
2.throw关键字后边new的对象必须是Exception或Exception的子类
3.throw关键字抛出的指定异常对象,我们就必须处理这个异常对象
throw关键字后边创建的是RuntimeException或者是 RuntimeException的 子类对象,我们可以不处理,默认交给JVM处 理(打印异常对象,中断程序)
throw关键字后边创建的是编译异常(写代码的时候报错),我们就必 须处理这个异常,要么throws,要么try...catch
----------------------------------------------------------------------------------
throws关键字:异常处理的第一种方式,交给别人处理
throws 写在方法上 JVM帮我们抛异常,使用默认的异常信息 后面跟的是异常的类
作用:
当方法内部抛出异常对象的时候,那么我们就必须处理这个异常对象
可以使用throws关键字处理异常对象,会把异常对象声明抛出给方法的调用者处理( 自己不处理,给别人处理),最终交给JVM处理-->中断处理
使用格式:在方法声明时使用
修饰符 返回值类型 方法名(参数列表) throws AAAExcepiton,BBBExcepiton...{
throw new AAAExcepiton("产生原因");
throw new BBBExcepiton("产生原因");
...
}
注意:
1.throws关键字必须写在方法声明处
2.throws关键字后边声明的异常必须是Exception或者是Exception的子类
3.方法内部如果抛出了多个异常对象,那么throws后边必须也声明多个异常
如果抛出的多个异常对象有子父类关系,那么直接声明父类异常即可
4.调用了一个声明抛出异常的方法,我们就必须的处理声明的异常
要么继续使用throws声明抛出,交给方法的调用者处理,最终交给JVM
要么try...catch自己处理异常
NullPointerException 运行时异常
FileNotFoundException 编译时异常
-----------------------------------------------------------------------------------
try...catch:异常处理的第二种方式,自己处理异常
格式:
try{
可能产生异常的代码
}catch(定义一个异常的变量,用来接收try中抛出的异常对象){
异常的处理逻辑,异常异常对象之后,怎么处理异常对象
一般在工作中,会把异常的信息记录到一个日志中
}
...
catch(异常类名 变量名){
}
注意:
1.try中可能会抛出多个异常对象,那么就可以使用多个catch来处理这些异常对象
2.如果try中产生了异常,那么就会执行catch中的异常处理逻辑,执行完毕catch中的处理逻辑,继续执行try...catch之后的代码
如果try中没有产生异常,那么就不会执行catch中异常的处理逻辑,执行完try中的代码,继续执行try...catch之后的代码
--------------------------------------------------------------------------------------
finally代码块
格式:
try{
可能产生异常的代码
}catch(定义一个异常的变量,用来接收try中抛出的异常对象){
异常的处理逻辑,异常异常对象之后,怎么处理异常对象
一般在工作中,会把异常的信息记录到一个日志中
}
...
catch(异常类名 变量名){
}finally{
无论是否出现异常都会执行
}
注意:
1.finally不能单独使用,必须和try一起使用
2.finally一般用于资源释放(资源回收),无论程序是否出现异常,最后都要资源释放
3. 如果finally有return语句,永远返回finally中的结果,避免该情况.
------------------------------------------------------------------------------------
多个异常使用捕获又该如何处理呢?
1. 多个异常分别处理。
2. 多个异常一次捕获,多次处理。
一个try多个catch注意事项:
catch里边定义的异常变量,如果有子父类关系,那么子类的异常变量必须写在 上边,否则就会报错
3. 多个异常一次捕获一次处理。
------------------------------------------------------------------------------------
子父类的异常:
- 如果父类抛出了多个异常,子类重写父类方法时,抛出和父类相同的异常或者是父类异常的子类不抛出异常。
- 父类方法没有抛出异常,子类重写父类该方法时也不可抛出异常。此时子类产生该异常,只能捕获处理,不能声明抛出
注意:
父类异常时什么样,子类异常就什么样
-------------------------------------------------------------------------------------
自定义异常类:
java提供的异常类,不够我们使用,需要自己定义一些异常类
格式:
public class XXXExcepiton extends Exception | RuntimeException{
添加一个空参数的构造方法
添加一个带异常信息的构造方法
}
注意:
1.自定义异常类一般都是以Exception结尾,说明该类是一个异常类
2.自定义异常类,必须的继承Exception或者RuntimeException
继承Exception:那么自定义的异常类就是一个编译期异常,如果方法内部抛出了编译期异常,就必须处理这个异常,要么throws,要么try...catch
继承RuntimeException:那么自定义的异常类就是一个运行期异常,无需处理,交给虚拟机处理(中断处理
----------------------------------------------------------------------------------------
主线程:执行主(main)方法的线程
单线程程序:java程序中只有一个线程
执行从main方法开始,从上到下依次执行
JVM执行main方法,main方法会进入到栈内存
JVM会找操作系统开辟一条main方法通向cpu的执行路径
cpu就可以通过这个路径来执行main方法
而这个路径有一个名字,叫main(主)线程
----------------------------------------------------------------------------------------
创建多线程程序的第一种方式:创建Thread类的子类
java.lang.Thread类:是描述线程的类,我们想要实现多线程程序,就必须继承Thread类
实现步骤:
1.创建一个Thread类的子类
2.在Thread类的子类中重写Thread类中的run方法,设置线程任务(开启线程要做什么?)
3.创建Thread类的子类对象
4.调用Thread类中的方法start方法,开启新的线程,执行run方法
void start() 使该线程开始执行;Java 虚拟机调用该线程的 run 方法。
结果是两个线程并发地运行;当前线程(main线程)和另一个线程(创建的新线程,执行其 run 方法)。
多次启动一个线程是非法的。特别是当线程已经结束执行后,不能再重新启动。
java程序属于抢占式调度,那个线程的优先级高,那个线程优先执行;同一个优先级,随机选择一个执行
获取线程的名称:
1.使用Thread类中的方法getName()
String getName() 返回该线程的名称。
2.可以先获取到当前正在执行的线程,使用线程中的方法getName()获取线程的名称
static Thread currentThread() 返回对当前正在执行的线程对象的引用
-------------------------------------------------------------------------------------
设置线程的名称:(了解)
1.使用Thread类中的方法setName(名字)
void setName(String name) 改变线程名称,使之与参数 name 相同。
2.创建一个带参数的构造方法,参数传递线程的名称;调用父类的带参构造方法,把线程名称传递给父类,让父类(Thread)给子线程起一个名字
Thread(String name) 分配新的 Thread 对象。
---------------------------------------------------------------------------------------
public static void sleep(long millis):使当前正在执行的线程以指定的毫秒数暂停(暂时停止执行)。
毫秒数结束之后,线程继续执行
----------------------------------------------------------------------------------------
创建多线程程序的第二种方式:实现Runnable接口
java.lang.Runnable
Runnable 接口应该由那些打算通过某一线程执行其实例的类来实现。类必须定义一个称为 run 的无参数方法。
java.lang.Thread类的构造方法
Thread(Runnable target) 分配新的 Thread 对象。
Thread(Runnable target, String name) 分配新的 Thread 对象。
实现步骤:
1.创建一个Runnable接口的实现类
2.在实现类中重写Runnable接口的run方法,设置线程任务
3.创建一个Runnable接口的实现类对象
4.创建Thread类对象,构造方法中传递Runnable接口的实现类对象
5.调用Thread类中的start方法,开启新的线程执行run方法
实现Runnable接口创建多线程程序的好处:
1.避免了单继承的局限性
一个类只能继承一个类(一个人只能有一个亲爹),类继承了Thread类就不能继承其他的类
实现了Runnable接口,还可以继承其他的类,实现其他的接口
2.增强了程序的扩展性,降低了程序的耦合性(解耦)
实现Runnable接口的方式,把设置线程任务和开启新线程进行了分离(解耦)
实现类中,重写了run方法:用来设置线程任务
创建Thread类对象,调用start方法:用来开启新线程
--------------------------------------------------------------------------------------
匿名内部类方式实现线程的创建
匿名:没有名字
内部类:写在其他类内部的类
匿名内部类作用:简化代码
把子类继承父类,重写父类的方法,创建子类对象合一步完成
把实现类实现类接口,重写接口中的方法,创建实现类对象合成一步完成
匿名内部类的最终产物:子类/实现类对象,而这个类没有名字
格式:
new 父类/接口(){
重复父类/接口中的方法
};
----------------------------------------------------------------------------------------
解决线程安全问题的一种方案:使用同步代码块
格式:
synchronized(锁对象){
可能会出现线程安全问题的代码(访问了共享数据的代码)
}
注意:
1.通过代码块中的锁对象,可以使用任意的对象
2.但是必须保证多个线程使用的锁对象是同一个
3.锁对象作用:
把同步代码块锁住,只让一个线程在同步代码块中执行
解决线程安全问题的二种方案:使用同步方法
使用步骤:
1.把访问了共享数据的代码抽取出来,放到一个方法中
2.在方法上添加synchronized修饰符
格式:定义方法的格式
修饰符 synchronized 返回值类型 方法名(参数列表){
可能会出现线程安全问题的代码(访问了共享数据的代码)
解决线程安全问题的三种方案:使用Lock锁
java.util.concurrent.locks.Lock接口
Lock 实现提供了比使用 synchronized 方法和语句可获得的更广泛的锁定操作。
Lock接口中的方法:
void lock()获取锁。
void unlock() 释放锁。
java.util.concurrent.locks.ReentrantLock implements Lock接口
使用步骤:
1.在成员位置创建一个ReentrantLock对象
2.在可能会出现安全问题的代码前调用Lock接口中的方法lock获取锁
3.在可能会出现安全问题的代码后调用Lock接口中的方法unlock释放锁
---------------------------------------------------------------------------------------
进入到TimeWaiting(计时等待)有两种方式
1.使用sleep(long m)方法,在毫秒值结束之后,线程睡醒进入到Runnable/Blocked状态
2.使用wait(long m)方法,wait方法如果在毫秒值结束之后,还没有被notify唤醒,就会自动醒来,线程睡醒进入到Runnable/Blocked状态
唤醒的方法:
void notify() 唤醒在此对象监视器上等待的单个线程。
void notifyAll() 唤醒在此对象监视器上等待的所有线程。 |
|