equals
(比较的是地址)
子类重写 (可以比较内容)
传进来的参数是对象,向下转,才能调用子类特有方法父类调用子类重写方法,父类对象向下转型(需要增加判断instanceof)
this 表示调用该方法的父类,比较对象是传入的对象向下转型后的P
返回
判断
直接alt + insert 重写equals()方法
Object类的equals()(方法之空指针异常,null不能调用方法)
为空时,比较地址值
alt + enter 好用
Date类
System.out.println(System.currentTimeMillis());输出毫秒值
Date类的构造方法和成员方法
Date()
Date(Long date)
long getTime()
DateFormat是一个抽象类,需要实现类来创建对象
直接子类:SimpleDateFormat
DateFormat类的format方法和pa
日期转文本
通过SimpleDateFormat的方法format(),传入date对象,将日期对象转为文本
文本转日期
创建SimpleDateFormat对象,传递指定的模式
parse()方法
Calendar类
Calendar是抽象类
直接子类:GregorianCalendar
Calendar有一个静态方法getInstance();返回一个calendar子类对象
Calendar类不能直接创建对象,使用多态调用静态方法getInstance();返回一个对象,就可以调用Calendar中的方法
Calendar类常用方法
Calendar类中有很多静态成员变量
get(int field)方法
set(int field,int value)方法
add(int field,int amount);
getTime()方法;
System类
currentTimeMilis()方法
一般用来算程序效率
for循环执行时间
arraycopy()方法
//输出数组内容,需要用Arrays的方法toString();
StringBuilder
字符串缓冲区
StringBuilder的构造方法
StringBuilder的常用方法
apped方法
返回值为对象
链式编程
当方法返回值为对象时,就可以方法调用方法
包装类
装箱与装箱
装箱(基本数值-->包装对象)
Integer(); Integer.valueOf();
拆箱(包装对象-->基本数值)
intValue();
自动装箱和自动拆箱
自动装箱
自动拆箱
基本类型与字符串转换
基本转字符串
1、加上字符串 2、Interger.toString 3、String.valueOf
字符串转基本
Integer.parseXXX() 字符串转基本,要看字符串属于哪种基本
总结:Integer方法
Integer in1 = new Interger(value) (装箱) Integer in = 1; (自动装箱)
Integer in2 = Interger.valueOf(value)(装箱)
int i = Integer对象 . intvalue(); (拆箱) in = in + 2;(自动拆箱)
Integer.toString(value) (基本转字符串)
String.valueOf(value) (基本转字符串)
int i = Integer.parseXXX(); (字符串转基本)
集合框架
底层集合
Vector
ArratList
LinkedList
TreeSet
HashSet
LinkedHashSet
两种类型接口
List 接口
有序集合,有索引
Set 接口(没有索引)
下面接口分有序和无序
无序集合TreeSet和HashSet,重复添加元素,也只会显示一个
collection(根接口) (没有索引)
集合框架的学习方法
学习顶层,使用底层
Collection常用功能
接口 Collection<E>
Collection表示一组对象
创建集合对象
打印结果不是地址,说明重写了toString方法
add(E e) (添加)
返回值 Boolean (true / false)
remove(E e) (删除)
返回值 Boolean (true / false)
contains(E e) (查找元素是否存在)
返回值 Boolean (true / false)
isEmpty() (判断空)
返回值 Boolean (true / false)
size() (返回集合元素个数)
返回集合中元素个数
toArray() (集合变成数组)
返回值为数组类型
clear() (清空集合)
以上方法为集合公用方法
改变创建的集合对象类型,方法也能用
遍历集合
使用迭代器
Iterator迭代器(用来遍历集合)
迭代概念:
获取迭代器
获取集合对应的迭代器,来遍历集合
Iterator中的方法
hasNext() :判断集合中有没有下一个元素,返回true/false
next() :返回迭代的下一个元素
Iterator创建实现类对象
Iterator接口,Collection接口中的方法iterator(),返回值--实现类对象
1、创建Collection实现类对象 coll
2、创建Iterator接口的实现类对象 it
3、循环调用 next () 方法
方法一 :直接while循环取 方法二:一个一个取
也可用for循环
for( 初始事表达式 ;布尔表达式 ;步进表达式 ) {}
迭代器实现原理
增强for循环
(专门用来遍历数组和集合,过程中不能增删查改)
()中是数据类型,就是放入的集合数组中的数据类型 ,变量名自己定义
常用遍历集合通常用增强for循环
注意事项:
可以循环嵌套
快捷键:数组名.for
泛型
不使用泛型
在集合中有不同类型的元素,需要向下转型,会出现类型转换异常
使用泛型
定义含有泛型的类(<E>放在类名之后)(创建对象时,选择要创建的类型)
方法参数也为E e
调用时,创建对象,想要什么样的类型对象,就创建什么类型
1、默认Object
2、Integer
3、String
含有泛型的方法(<E>泛型在返回值类型前)定义的方法中,参数也通过泛型定义
含有泛型的静态方法(静态方法用类名调用)
1、静态方法不建议用创建对象来调用
2、含有泛型的静态方法也可以传入任意类型的参数
含有泛型的接口(<E>放在接口名之后)
使用含有泛型的接口
方法一:
1、实现类implements接口时,指定接口的泛型为String
2、实现类重写的接口方法泛型也是String
方法二:
1、实现类implements接口时,不给定指定的泛型<E>
2、创建对象,再给定指定的泛型
泛型通配符<?> (不知道使用什么类型接收参数时)
创建对象,定义的时候不能用,参数传递的时候才能用,做参数,可传所有类型的集合
创建Integer,String两个集合对象
//参数类型选Integer,String,Object都不行
//调用方法时会出现错误
创建对象,定义的时候不能用
使用泛型的通配符<?>就可以实现了,传入不同类型的集合参数
通配符的高级使用-----受限泛型
案例说明:
斗地主发牌案例
代码实现
public class DouDiZhu {
public static void main(String[] args) {
/*
准备牌
*/
//创建集合
ArrayList<String> poker = new ArrayList<>();
//两个数组存花色和索引
String[] color = {"♠","♥","♣","♦"};
String[] num = {"2","A","K","Q","J","10","9","8","7","6","5","4","3"};
//先把大小王放入集合
poker.add("大王");
poker.add("小王");
//循环嵌套遍历两个数组,组装52张牌
for (String a : num) {
for (String b : color) {
// System.out.println(a+b);
poker.add(a+b);
}
}
/*
洗牌
用Collections方法public static void shuffle(List<?> list)
*/
Collections.shuffle(poker);
// System.out.println(poker);
/*
发牌
创建四个集合存三个玩家和底牌,用%3判断发给谁,用>=51保留底牌
注意:要先判断>=51
*/
ArrayList<String> player01 = new ArrayList<>();
ArrayList<String> player02 = new ArrayList<>();
ArrayList<String> player03 = new ArrayList<>();
ArrayList<String> dipai = new ArrayList<>();
for (int i = 0; i < poker.size(); i++) {
String p = poker.get(i);
if(i>=51){
dipai.add(p);
}else if(i%3==0){
player01.add(p);
}else if(i%3==1){
player02.add(p);
}else if(i%3==2){
player03.add(p);
}
}
/*
看牌
*/
System.out.println("农民1:"+player01);
System.out.println("农民2:"+player02);
System.out.println("地主:"+player03);
System.out.println("底牌:"+dipai);
}
数据结构
栈、队列、数组、链表、红黑树
栈:先进后出
队列:先进先出
数组:查询快,增删慢
List接口 (有序、有索引、允许重复)
注意要防止数组越界异常
创建List集合对象
使用List集合方法(add、get、remove、set)
add(int index, E element) 指定位置添加
get(int index) 指定位置获取
remove(int index) 指定位置删除
set(int index, E element) 指定位置替换
List集合遍历
1、for + get() (因为List接口有索引,可以使用for循环遍历)
2、迭代器(list对象方法iterator创建对象)
3、增强for
ArrayList集合 (查询快,增删慢)(增加新数组实现) (多线程速度快)
因为底层代码是调用新数组
LinkedList集合 (查询慢,增删快)(List接口的链表实现)
由于是List接口的链表实现,所以该集合有大量的操作首位的方法
创建LinkedList集合对象
常用方法(addFirst、addLast、isEmpty、push、add、getFirst、getLast、removeFirst、removeLast)
===
===
防止,判断是否为空
=====
vector集合 (底层是数组)(单线程速度慢)(所有单列集合的祖先)
Vector
类可以实现可增长的对象数组。与数组一样
set接口 (没有索引、不可重复)
方法跟Collection一致
HashSet (查询快、无序集合 )(哈希表结构(数组+链表/数组+红黑树))
无序,存入取出循序可能不一样
创建对象
集合遍历
哈希值
哈希值是通过Object类的hashCode()方法得到的,系统随机给的逻辑地址,与实际地址不同
hashCode()可以重写
------------------------------------------------------十进制
----十六进制
巧合
HashSet集合存储数据的结构
Set集合存储元素不重复的原理 (重写hashCode和equals(保证元素唯一))
逻辑地址一样,字符串内容一样,不会存放
逻辑地址一样,字符串内容不一样,可以存放
没有重写的equals方法比较的是地址值(实际地址)
HashSet存储自定义类型的元素
在Person类中重写hashCode和equals方法
equals和==区别
用==比较两个对象的时候,比较的是两个不同的对象的地址
如果一个变量指向的数据是对象类型的,那么,这时候涉及了两块内存,对象本身占用一块内存(堆内存),变量也占用一块内存,例如 Objet obj = new Object();变量obj是一个内存,newObject()是另一个内存,此时,变量obj所对应的内存中存储的数值就是对象占用的那块内存的首地址。对于指向对象类型的变量,如果要比较两个变量是否指向同一个对象,即要看这两个变量所对应的内存中的数值是否相等,这时候就需要用==操作符进行比较。equals 方法是用于比较两个独立对象的内容是否相同,就好比去比较两个人的长相是否相同,它比较的两个对象是独立的。例如,对于下面的代码:两条new 语句创建了两个对象,然后用a,b这两个变量分别指向了其中一个对象,这是两个不同的对象,它们的首地址是不同的,即a和b中存储的数值是不相同的,所以,表达式 a==b 将返回false,而这两个对象中的内容是相同的,所以,表达式a.equals(b)将返回 true。在 实际 开发 中, 我们 经常 要比 较传 递进 行来的字 符串 内容 是否等, 例如 ,String input= …;input.equals(“quit ”),许多人稍不注意就使用==进行比较了,这是错误的,记住,字符串的比较基本上都是使用equals 方法。如果一个类没有自己定义equals 方法,那么它将继承Object 类的equals 方法,Object 类的equals方法的实现代码如下:
boolean equals(Object o){
return this==o;}
这说明,如果一个类没有自己定义 equals 方法,它默认的equals 方法(从Object 类继承的)就是使用==操作符,也是在比较两个变量指向的对象是否是同一对象,这时候使用equals 和使用==会得到同样的结果,如果比较的是两个独立的对象则总返回false。如果你编写的类希望能够比较该类创建的两个实例对象的内容是否相同,那么你必须覆盖 equals 方法,由你自己写代码来决定在什么情况即可认为两个对象的内容是相同的。
LinkedHashSet集合(在HashSet的基础上加了一条链表记录存储顺序)
可变参数(数据类型 ... 变量名)
(底层是一个数组)根据传递参数不同,创建长度不同的数组,存储参数
注意事项:
1、一个方法的参数只能有一个可变参数
2、有多个参数时,可变参数放在最后
可变参数(终极写法)(Object ... obj)
Collections(集合工具类)
常用方法(addAll、shuffle、sort(1)、sort(2))
方法:
一、addAll(Collection<T> c, T ... element); -------- 往集合中添加一些元素
二、shuffle(List<?> list); --------打乱顺序
三、sort(List<T> list); --------将集合默认排序(升序)
1、对整型数据排序
2、对字符类型排序
3、对自定义类型排序
创建一个Person类集合
需要Person类实现Comparable<Person>接口
重写comparaTo(Person o)方法,按添加进的对象的Age排序。
最后调用sort()方法
注意事项:
Integer 和 String 都实现了 Compareble<?> 接口,并且重写了 compareTo() 方法,来对相应的类型排序
所以要想实现对自定义类型排序,被排序集合里面的元素,必须实现Comparabl<?>接口,并重写comparaTo方法
四、sort(List<?> list , Comparator<? super T>); ---------按指定规则排序
在参数调用时,使用匿名内部类的匿名对象,实现接口,并重写compara()方法
注意事项:
sort(List<T> list) 实现的是Comparable接口 和 sort(List<?> list , Comparator<? super T>)实现的是Comparator接口
Map集合
接口 Map<K,V>
K
- 此映射所维护的键的类型
V
- 映射值的类型 (K 夫 V妻 一妻多夫)
将键映射到值的对象。一个映射不能包含重复的键;每个键最多只能映射到一个值。
单列集合 双列集合
Map常用的子类
Map接口中常用的方法(put、remove、get、containsKey)
public V put(K key,V value) ,把指定的键和值添加到集合
创建Map对象 Map < String , String > 其中泛型数据类型可变
put返回值V(值), 如果集合中没有跟K(键)重复的,那么值Value返回null
如果驶入的K(键)在集合中有重复的,就将新的V(值)替换原来的值
输出结果 {A = B , C = D }
public V remove(object key)
把指定的键 所对应的键值对元素,在Map集合中删除,返回被删元素
此时Map<String,Integer>创建的键、值类型不同
null可以赋给Integer包装类,不能赋给int(会出现空指针异常)
删除没有的K(键),返回的是null
public V get(Object key) 输入key,返回value
bealoon containsKey(Object key) 判断集合中是否 包含指定的键
Map集合遍历键找值方法
第一种遍历方法: Map.keySet()获取Key值存入Set,遍历再用get(key),获取value
1、创建Map集合对象
2、使用Map集合中keySet(),将所有key取出存入到Set集合中
3、遍历Set集合中的每一个Key值,通过Map().get(key),获取键所对应的值
技巧:省略第二部,创建Set集合
第二种遍历方法:(Set<Map.Entry<K,V>> entrySet())返回的是一个是内部类对象
Entry键值对对象(内部类)
接口 Map.Entry<K,V>
1、取出Map集合中多个Entry对象,存储到一个Set集合中
(返回的是一个内部类Entry<K,V>对象),遍历时,通过该对象调用getKey()、getValue()
2、遍历Set集合,多去每一个Entry对象
HashMap存储自定义类型键值(Map(K,V)K必须唯一,V可重复)
保证唯一,无序,JDK1.2后
K为String或Integer,V为自定义类型键值(可不用重写hashCode+equals)
K为自定义类型键值,V为String或Integer(已经重写hashCode+equals)
LinkedHashMap
key不允许重复,无序
key不允许重复,有序
Hashtable
任何非 null
对象都可以用作键或值。Hashtable
是同步的
键值不能为null
Map练习
JDK9对集合添加的优化 of方法
Debug调试
异常
异常体系
的子类都是运行期异常
运行期异常
编译期异常(写错代码),编译不通过
方法一:抛出异常给虚拟机处理
方法二:try...catch,后续程序能运行
运行期异常,编译通过,运行出错
异常产生的过程
异常处理
运行时异常,可以可以不处理,默认交给JVM处理
throw(在指定的方法里面抛出指定的异常)
throw和throws区别
throws:自己不想对异常做处理,抛给方法调用者
throw:自己处理一个异常,要么try...catch,要么抛出https://blog.csdn.net/weixin_38011265/article/details/79149313
编译期异常:
运行期异常
Object非空判断
Object.requireNonNull(obj);判断非空,抛出异常
声明异常throws
捕获异常try...catch
try中抛出什么类型异常,catch中就传入对应的变量
Throwable类中3个异常处理的方法
finally代码块
异常注意事项
1、多个异常分别处理
2、多个异常一次处理,谁先被捕获,就输出谁的异常
多个catch中的异常变量如果有继承关系,子类应放父类前面
ArrayIndexOutOfBoundsException extends IndexOutOfBoundsExcepton,所以Array在前
父类写上面,就会发生多态,调用,子类变量就不会被赋值
异常注意事项
调用该方法,返回的永远是finally中的return
子父类异常
1、父类方法抛出多个异常,子类重写方法,抛出相同异常、抛出父类异常子类、不抛出异常
2、父类方法没有抛出异常,子类重写方法,也不能抛出异常
3、
自定义异常
// 父类的无参构造
// 父类的有参构造
public class Demo01RegisterException {
static String[] usernames = {"张三","李四","王五"};
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
String username = sc.next();//获取输入字符串
checkUsername(username);
}
public static void checkUsername(String username){
for (String name : usernames) {//静态方法不能访问非静态
if(name.equals(username)){
try {
throw new RegusterException("注册名已经存在");
} catch (RegusterException e) {
e.printStackTrace();
}
return;//使用try...catch抛出异常后,停止方法
}
}
System.out.println("注册成功");
}
}