异常
为什么我们需要异常。
我觉得有这么几点
1、用户或者程序员需要知道出了什么问题。
2、如果出现了异常,但不不处理,程序终止,无法执行接下来的程序。
3、程序员预防程序出现未知的bug,为以后调试程序留下解决方案。
在java中我们对异常的几种用法
异常的继承关系
Throwable: 它是所有错误与异常的超类(祖宗类)
|- Error 错误
|- Exception 编译期异常,进行编译JAVA程序时出现的问题
|- RuntimeException 运行期异常, JAVA程序运行过程中出现的问题
如果异常是error类,就是出现了严重错误,是系统级别问题,(如出现了线程死锁)只能通过修改源码解决
我们处理异常一般都是处理exception类,这类异常都是因为程序逻辑错误造成的,是程序员逻辑考虑不得当引起的。
异常的最简单使用方法
实体(getter setter 方法省略)
student
package entity;
/**
* @author :hj
* @date :Created in 2021/4/19 9:15
* @description:学生
* @modified By:
* @version: $
*/
public class Student {
private String name;
private Integer appetite;
public void eat(Integer number)throws Exception{
if(this.appetite<=number){
System.out.println("吃饱了");
}else{
throw new Exception("人被胀死了");
}
}
}
bluemsun
package entity;
/**
* @author :hj
* @date :Created in 2021/4/19 9:24
* @description:蓝旭工作室成员
* @modified By:
* @version: $
*/
public class Bluemsun extends Student{
private String name;
private Integer appetite;
private double proportion;
public void eat(Integer number){
try {
proportion = (double)number/appetite;
if(proportion>1){
throw new Exception("胀死了");
}
} catch (Exception exception) {
exception.printStackTrace();
}finally {
System.out.println("吃了"+number+"的食物占了"+proportion);
}
}
}
thorw方法测试
package throwable;
import entity.Bluemsun;
import entity.Student;
/**
* @author :hj
* @date :Created in 2021/4/19 8:43
* @description:异常
* @modified By:
* @version: $
*/
public class Throw {
public static void main(String[] args) throws Exception {
// Student student = new Student();
// student.setAppetite(100);
// student.eat(101);
// student.eat(99);
// Bluemsun bluemsunStudent = new Bluemsun();
// bluemsunStudent.setAppetite(1000);
// bluemsunStudent.eat(100);
// bluemsunStudent.eat(1004);
Throw throw1 =new Throw();
Integer num=throw1.eat(-1);
Integer num = throw1.eat(100);
System.out.println(num);
}
public Integer eat(Integer num){
Integer food =num;
try {
if(food<0){
food =0;
throw new Exception("没东西,怎么吃");
}
return food;
} catch (Exception exception) {
food++;
exception.printStackTrace();
} finally {
food =10;
System.out.println("finally "+food);
}
return food;
}
}
经过上述代码 我们了解了最基础的异常处理 当然还可以自己根据业务逻辑写异常 不过能用官方的就不要自己写。
常用类
Object
Object类是所有类的父类,也就是说任何一个类在定义时如果没有明确地继承一个父类,那它就是Object类的子类,也就是说以下两种类定义的最终效果是完全相同的。
Object类提供无参构造方法 ,之所以提供这样的无参构造,是因为在子类对象实例化时都会默认调用父类中的无参构造方法,这样在定义类时即使没有明确定义父类为Object,读者也不会感觉代码的强制性要求。
object 有许多方法和线程有关,希望同学们课下了解
String
String():创建一个空的字符串
String(byte[] bys):通过字节数组创建字符串
String(char[] chs):通过字符数组创建字符串
String(byte[] bys,int offset,int length):通过字节数组一部分创建字符串
String(char[] chs,int offset,int length):通过字符数组一部分创建字符串
String(String original):通过字符串常量值创建字符串
2)成员方法
1》判断功能
equals(Object obj):比较两个字符串是否相等
equalsIngnoreCase(Object obj):忽略大小写比较两个字符串是否相等
contains(String str):是否包含指定字符串
startsWith(String str):是否以指定的字符串开头
endWith(String str):是否以指定的字符串结尾
isEmpty():是否为空
matches(String regex):判断字符串是否匹配给定的正则表达式。
2》获取功能
length():获取长度
charAt(int index): 获取指定索引位置处的字符
indexOf(int ch):获取指定字符第一次出现的索引值(从0开始)
indexOf(int ch,int fromIndex):获取从指定索引位置开始,获取指定字符第一次出现的索引值
indexOf(String s):获取指定字符串第一次出现的索引值
indexOf(String s,int fromIndex):获取从指定索引位置开始,获取指定字符串第一次出现的索引值
lastIndexOf(int ch):获取指定字符最后一次出现的索引值
substring(int start):从指定位置开始一直截取到末尾
substring(int start,int end):截取[start,end-1]范围
3》转换功能
byte[] getBytes():将字符串转成字节数组
char[] toCharArray():将字符串转成字符数组
static valueOf(char[] chs):将char[]转成字符串
static valueOf(int num):将int类型转成字符串
static valueOf(Object obj):将任意类型转成字符串
toLowerCase():转成小写
toUpcase():转成大写
concat(String str):字符连接
4》其他功能
replace(char old,char new):将old字符替换成new字符
replace(String old,String new):将old字符串替换成new字符串
trim():去除两边空格
int compareTo(String s):字典比较,如果前面值小于后面值返回负数,否则返回正数,先比较第一个元素,如果相等再比较第二个元素…返回元素之间的差值;如果比较字符串有包含关系,返回的值是它们长度的差值
int compareToIgnoreCase(String s):忽略大小写字典比较
String replaceAll(String regex, String replacement):使用给定的 replacement 替换此字符串所有匹配给定的正则表达式的子字符串。
String replaceFirst(String regex, String replacement):使用给定的 replacement 替换此字符串匹配给定的正则表达式的第一个子字符串。
String[] split(String regex): 根据给定正则表达式的匹配拆分此字符串。
String[] split(String regex, int limit): 根据匹配给定的正则表达式来拆分此字符串。
判断两个string实例是否相同一定要用equal 如果使用==对比的是地址
为什么有了string后我们还有stringbuffer和stringbuilder
Stringbuilder
线程不安全的可变字符序列
1)构造方法
StringBuilder():以默认容量创建空的StringBuilder对象
StringBuilder(int capacity):以指定容量创建空的StringBuilder对象
StringBuilder(String str):以指定的字符串创建StringBuilder对象
2)成员方法
获取功能
int capacity():获取容量
int length():获取长度
添加功能
append(int value):追加。可以追加多种类型
insert(int offset,String s):在指定的位置插入指定数据
删除功能
deleteCharAt(int index):删除指定索引处的元素
delete(int start,int end):删除[start,start-1]范围内的元素
替换功能
replace(int start,int end,String s):将[start,end-1]范围内的元素替换成指定字符串
反转功能
reverse():元素反转
截取功能
String subString(int start):截取指定位置一直到末尾
String subString(int start,int end):截取[start,end-1]范围
String、StringBuilder和StringBuffer的区别?
String内容不可改变
StringBuilder和StringBuffer内容可变
StringBuilder是线程不安全的,不同步,效率高
StringBuffer是线程安全的,同步,效率低
date
1、创建一个当前时间的Date对象
//创建一个代表系统当前日期的Date对象
Date d = new Date();
2、创建一个我们指定的时间的Date对象:
使用带参数的构造方法Date(int year, int month, int day) ,可以构造指定日期的Date类对象,Date类中年份的参数应该是实际需要代表的年份减去1900,实际需要代表的月份减去1以后的值。
//创建一个代表2014年6月12号的Date对象
Date d1 = new Date(2014-1900, 6-1, 12); (注意参数的设置)
还有很多常用类 如scanner math … 大家务必要多了解了解尤其是日期
容器以及泛型
容器以及泛型
代码主要都是从马士兵课上看的打下来。
看到个博客觉得这个图非常好
https://blog.csdn.net/weixin_42574142/article/details/87125363
public class Name implements Comparable{
private String firstName,lastName;
public Name(String firstName,String lastName){
this.firstName=firstName;
this.lastName=lastName;
}
public String getFirstName(){return firstName;}
public String getLastName(){return lastName ;}
public String toString(){return firstName+" " +lastName;}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (!(o instanceof Name)) return false;
Name name = (Name) o;
return firstName.equals(name.firstName) &&
lastName.equals(name.lastName);
}
@Override
public int hashCode() {
return firstName.hashCode();
}
public int compareTo(Object o){
Name n = (Name) o;
int lastCmp=
lastName.compareTo(n.lastName);
return(lastCmp!=0 ? lastCmp : firstName.compareTo(n.firstName));
}
}
先写一个name类过一会儿使用。
重写equals的时候记得重写hash,因为参与equals函数的字段,也必须都参与hashCode 的计算
我们先写一个
import java.util.*;
public class Test1{
public static void main(String[] args) {
Set a = new HashSet();
Set b = new HashSet();
a.add("hello");
a.add("String ");
a.add(new Name("zhang","san"));
a.add(new Name("zhang","san"));
a.add(new Integer(9));
System.out.println(a);
}
}
输出结果
[String , 9, hello, zhang san]
我们可以看出来hashset是无序无重复的
import java.util.Collection;
import java.util.HashSet;
import java.util.Iterator;
public class Test{
public static void main(String[] args) {
Collection c =new HashSet();
c.add(new Name("f3","l1"));
c.add(new Name("f2","l2"));
c.add(new Name("f1","l3"));
c.add(new Name("f4","l4"));
Iterator i =c.iterator();
while(i.hasNext()){
Name n =(Name )i.next();
System.out.println(n.getFirstName());
}
}
}
在这里我们使用了Iterator
什么是Iterator(迭代器)?
迭代器是一种设计模式,它是一个对象,它可以遍历并选择序列中的对象,而开发人员不需要了解该序列的底层结构。迭代器通常被称为“轻量级”对象,因为创建它的代价小。
Java中的Iterator功能比较简单,并且只能单向移动:
(1) 使用方法iterator()要求容器返回一个Iterator。第一次调用Iterator的next()方法时,它返回序列的第一个元素。注意:iterator()方法是java.lang.Iterable接口,被Collection继承。
(2) 使用next()获得序列中的下一个元素。
(3) 使用hasNext()检查序列中是否还有元素。
(4) 使用remove()将迭代器新返回的元素删除。
总而言之就是我们可以通过Iterator访问我们容器里面的元素并且可以更改,由最上图可以知道所有容器都有个Iterator接口
输出结果
f1
f2
f3
f4
import java.util.*;
public class Test3{
public static void main(String[] args) {
List a=new LinkedList();
a.add(new Name("zhangsan","o"));
a.add(new Name("wangwu","h"));
a.add(new Name("lier","g"));
a.add(new Name("xiaowang","q"));
System.out.println(a);
Collections.sort(a);
System.out.println(a);
}
}
list类分为LinkedList(有点链表的意思)和ArrayList(基本上就是数组)和Vector(类似于C++的动态数组)
list类里面就有排序的方法,再也不用自己写了,直接调用就完事儿
建议查下api文档,截图到markdown太麻烦
import java.util.*;
public class Test1 {
public static void main(String[] args) {
Map m1 = new HashMap();
Map m2 = new TreeMap();
// m1.put("one",new Integer(1));
m1.put("one",1);
// m1.put("two",new Integer(2));
m1.put("two",2);
// m1.put("three",new Integer(3));
m1.put("three",3);
// m2.put("A",new Integer(1));
m2.put("A",1);
// m2.put("B",new Integer(2));
m2.put("B",2);
System.out.println(m1.size());
System.out.println(m1.containsKey("one"));
System.out.println(m2.containsValue(new Integer(1)));
if(m1.containsKey("two")){
// int i = ((Integer)m1.get("two")).intValue();
int i=(Integer)m1.get("two");
System.out.println(i);
}
Map m3 = new HashMap(m1);
m3.putAll(m2);
System.out.println(m3);
}
}
map就是一个索引一个值,我们可以通过索引就可以找到这个值。
在这里大家都看到为什么没有用
m2.put("B",new Integer(2));
这个就要感谢我们的自动打包了,既减轻了程序负担,看起来也更加清晰。
import java.util.*;
public class Test2{
public static void main(String[] args) {
List<String> c =new ArrayList<String>();
c.add("aaa");
c.add("bbb");
c.add("ccc");
for(int i=0;i<c.size();i++){
String s= c.get(i);
System.out.println(s);
}
Collection<String> c2 =new HashSet<String>();
c2.add("aaa");c2.add("bbb");c2.add("ccc");
for (Iterator<String> it =c2.iterator();it.hasNext();){
String s=it.next();
System.out.println(s);
}
}
}
在这里我们使用了泛型,虽然还没体现出优点。但介绍一下
1.性能好
对值类型使用非泛型集合类,在把值类型转换为引用类型,和把引用类型转换为值类型时,需要进行装箱和拆箱操作。装箱和拆箱的操作很容易实现,但是性能损失较大。假如使用泛型,就可以避免装箱和拆箱操作。
2、类型安全
与ArrayList类一样,如果使用对象,可以在这个集合中添加任意类型。
可以让编译检查你装的是不是你想要的参数
import java.util.*;
public class Test16{
public static void main(String[] args) {
Map<String,Integer> m1 = new HashMap<String,Integer>();
m1.put("one",1); m1.put("two",2); m1.put("three",3);
System.out.println(m1.size());
System.out.println(m1.containsKey("one"));
if(m1.containsKey("two")){
int i=m1.get("two");
System.out.println(i);
}
}
}