异常(之前说过)
程序无法正常执行完毕异常体系:
Throwable
/ \
Error Exception
Error : 错误,一般由虚拟机生成并脱出,无需要程序猿管理
Exception : 异常
CheckedException 编译时异常|检查时异常: 发生在程序编译期间
程序如果遇到编译时异常没有处理,程序无法正常运行
RuntimeException 运行时异常 : 发生程序运行期间
一般可以通过增强程序健壮性的代码处理 if注意 :
如果程序遇到异常没有处理,无法继续执行
常见的一些异常
- 空指针异常 NullPointerException
- 数组越界异常 ArrayIndexOutOfBoundsException
- 数组长度负数异常 NegativeArraySizeException
- 类型转换异常 ClassCastException
- 数学异常 ArithmeticException
- 数字格式异常 NumberFormatException
异常的处理方案
异常抛出:throws 把异常抛出到上一层,谁调用谁解决
异常捕获: try..catch
try{
有可能出现异常的代码;
}catch(FileNotFoundException e){
处理异常代码;
}catch(NullPointerException e){
处理异常代码;
}catch(Exception e){
所有异常都能接收;
}finally{
无论try中是否会出现异常,都会执行finally中的代码//所以可添加资源的关闭代码
}
一个try的后面可以接 1~n个catch
try中如果一旦出现异常,try下面的代码不会执行,直接进入catch的判断
catch从上到下一次判断,满足哪一个catch捕获的类型,就执行对应的语句体
异常一旦捕获,程序执行过程中出现的异常按照指定方案解决,不会影响后续代码的执行
public class Class002_Exception {
public static void main(String[] args) {
System.out.println("主方法开始了");
//异常捕获
try{
System.out.println("try开始了");
//System.out.println(5/0);
test();
System.out.println("try结束了");
}catch (FileNotFoundException e){
System.out.println("这是文件未找到异常");
e.printStackTrace();
}catch (Exception e){
e.printStackTrace();
}finally {
System.out.println("最终的代码无论是否出现异常都会执行");
}
System.out.println("主方法结束了");
}
public static void test() throws FileNotFoundException {
InputStream is = new FileInputStream("D:\\AAA\\DDD\\haha.txt");
}
}
自定义异常
自定义的异常类型
所有自定义的异常类型必须直接或者间接继承自Exception
如果自定义异常为运行时期异常,需要直接或者间接的继承自RuntimeException
throw 制造异常
public class Class003_DefinedException {
public static void main(String[] args) {
User user = new User();
user.setUsername("zhangsan");
int age = 8;
//增强程序健壮性
/*if(age>=18 && age<=100){
user.setAge(age);
}*/
try {
user.setAge(28);
} catch (AgeException e) {
try {
user.setAge(18);
} catch (AgeException ageException) {
ageException.printStackTrace();
}
}
System.out.println(user);
}
}
//自定义异常
class AgeException extends Exception{
public AgeException() {
}
public AgeException(String message) {
super(message);
}
}
class User{
private String username;
private int age;
public User() {
}
public User(String username, int age) {
this.username = username;
this.age = age;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public int getAge() {
return age;
}
public void setAge(int age) throws AgeException {
if(age<18 || age>100){
throw new AgeException(age+"不合法");
}
this.age = age;
}
@Override
public String toString() {
return "User{" +
"username='" + username + '\'' +
", age=" + age +
'}';
}
}
包装类
基本的数据包装类
基本数据类型 | 包装类 |
byte | Byte |
short | Short |
int | Integer |
long | Long |
char | Character |
boolean | Boolean |
float | Float |
doouble | Double |
包装类的优点:
1.类可以提供很多成员,功能...
2.集合中之能存储引用数据类型,想要存储基本数据类型数据的时候,可以先转为对应的包装类型,再存储
3.基本数据类型与对应包装类型数据的默认值不同,当在具体业务下,比如区分账户余额的0与null两种状态,可以使用包装类型表示账户余额
基本数据类型的优点:
有利于节约内存自动拆装箱:
1.自动装箱: 基本-->包装
2.自动拆箱: 包装-->基本
public class Class001_Data {
public static void main(String[] args) {
int i = 1;
//自动装箱 Integer.valueOf(int)
Integer in = 1;
//自动拆箱 in.intValue()
int i2 = in;
test(1.1,2.2); //自动装箱
}
static void test(Double d1,Double d2){
System.out.println(d1+d2); //自动拆箱
}
}
package com.xxxx.tercher;
/*
判断题:
总结:int,Integer,new Integer()三者之间比较是否相等
1.两个基本数据类型只要数据值相等,==比较结果就相等
2.两个new 包装类比较,无论数据值是否相等,都不相等,因为new在堆中创建新的地址空间
3.Integer i3,与Integer i4,两个自动装箱的对象比较,在[-128,127]范围之内相等,否则返回new Integer不相等
4.int与Integer|new Integer() ,只要数据值相等就相等,因为会发生自动拆箱
*/
public class Class002_Data {
public static void main(String[] args) {
int i1 = 127;
int i2 = 127;
//自动装箱 Integer.valueOf()
Integer i3 = 127;
Integer i4 = 127;
Integer i5 = new Integer(127);
Integer i6 = new Integer(127);
Integer i7 = 128;
Integer i8 = 128;
// == 基本数据类型:比较数据值 引用数据类型:对象地址
System.out.println(i1==i2); //true
System.out.println(i3==i4); //true [-128~127]
System.out.println(i5==i6); //false
System.out.println(i1==i3); //true
System.out.println(i1==i5); //true
System.out.println(i3==i5); //false
System.out.println(i7==i8); //false new Integer(128)
}
}
时间与日期
import java.util.Date;
/*
Date
Date类表示特定的时刻,精度为毫秒。
*/
public class Class001_Date {
public static void main(String[] args) {
//Date() 分配 Date对象并对其进行初始化,使其表示分配时间,测量 Date到毫秒。
Date date = new Date();
System.out.println(date);
//获取date日期的毫秒数 标准基准时间1970年1月1日00:00:00 GMT。
long time = date.getTime();
System.out.println(time);
//Date(long date) 分配 Date对象并初始化它以表示自标准基准时间(称为“纪元”)以来的指定毫秒数,即1970年1月1日00:00:00 GMT。
Date date2 = new Date(162634300000L);
System.out.println(date2);
//boolean after(Date when) 测试此日期是否在指定日期之后。
//boolean before(Date when) 测试此日期是否在指定日期之前。
System.out.println(date.before(date2)); //false
System.out.println(date.after(date2)); //true
System.out.println(date.toString());
}
}
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
/*
日期格式转换器 SimpleDateFormat
目标:
将指定格式的字符串转为日期对象 parse(str)
将日期对象转为指定格式的字符串 format(date)
*/
public class Class002_SimpleDateFormat {
public static void main(String[] args) throws ParseException {
//SimpleDateFormat() 默认格式
SimpleDateFormat simple = new SimpleDateFormat();
Date date = new Date();
//日期对象转为字符串--> 默认格式
String str = simple.format(date);
System.out.println(str);
// 2020-12-12 13:15:55
String strTime = "2020-12-12 13:15:55 888";
//指定格式的转换器 SimpleDateFormat(String pattern)
SimpleDateFormat simple2 = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss SSS");
//字符串转为日期对象
Date date3 = simple2.parse(strTime);
System.out.println(date3);
}
}
静态工厂Math
/*
Math 数学相关类
静态工厂--> 工具类
java.lang下不需要导包
*/
public class Class001_Math {
public static void main(String[] args) {
//static double abs(double a) 返回 double值的绝对值。
System.out.println(Math.abs(-300));
//static double ceil(double a) 返回大于或等于参数且等于数学整数的最小值(最接近负无穷大) double 。
System.out.println(Math.ceil(2.0));
System.out.println(Math.ceil(-2.2));
//static double floor(double a) 返回小于或等于参数且等于数学整数的最大值(最接近正无穷大) double 。
System.out.println(Math.floor(2.9));
//static double max(double a, double b) 返回两个 double值中较大的 double 。
//static int min(int a, int b) 返回两个 int值中较小的 int 。
System.out.println(Math.max(18,17));
//static double pow(double a, double b) 返回第一个参数的值,该值是第二个参数的幂。
System.out.println(Math.pow(2,3));
System.out.println(Math.pow(3,3));
//static double random() 返回带有正号的 double值,大于或等于 0.0且小于 1.0 。 [0.0,1.0)
/*
随机整数:
[min,max) (int)(Math.random()*(max-min)+min)
[0.0,1.0) * (max-min)
[0.0,max-min) + min
[min,max)
[min,max] (int)(Math.random()*(max-min+1)+min)
*/
//[5,10]
System.out.println((int)(Math.random()*(10-5+1)+5));
System.out.println((int)(Math.random()*(10-5+1)+5));
System.out.println((int)(Math.random()*(10-5+1)+5));
System.out.println((int)(Math.random()*(10-5+1)+5));
//static long round(double a) 返回与参数最接近的 long ,并将关系四舍五入为正无穷大。 只针对小数点后一位
System.out.println(Math.round(3.5));
System.out.println(Math.round(3.45));
//static double sqrt(double a) 返回 double值的正确舍入正平方根。
System.out.println(Math.sqrt(9));
System.out.println(Math.sqrt(4));
System.out.println(Math.sqrt(2));
System.out.println(Math.PI);
}
}
常用类之字符串
String 不可变长字符序列
StringBuilder 可变长字符序列,线程不安全|不同步,效率较高
StringBuffer 可变长字符序列,线程安全|同步,效率较低
String类表示字符串。 Java程序中的所有字符串文字(例如"abc" )都实现为此类的实例。
String str = "abc"; 创建一个字符串对象"abc",字符串常量 -->字符串常量池中
String str2 = new String("haha"); 2个对象 第1个new->在堆中 第2个"haha"-->字符串常量池中
String str2 = new String("abc"); 1个对象 第1个new->在堆中 "abc"->上面已经使用过,字符串常量池中已经存在字符串底层:
jdk11-->使用private final byte[] value; 字节数组存储字符串中的字符数据
jdk8--> private final char[] value;字符数组
public static void main(String[] args) throws UnsupportedEncodingException {
//String() 初始化新创建的 String对象,使其表示空字符序列。
String str1 = new String();
String str2 = "";
System.out.println(str1==str2); //false
//String(String original) 初始化新创建的String对象,使其表示与参数相同的字符序列; 换句话说,新创建的字符串是参数字符串的副本
String str3 = new String("abc");
System.out.println(str3);
//String(char[] value) 分配新的 String ,使其表示当前包含在字符数组参数中的字符序列。
//字符数组转为字符串
char[] arr = {'y','j','x','x','t'};
String str4 = new String(arr);
System.out.println(str4);
//String(char[] value, int offset, int count) 分配一个新的 String ,其中包含字符数组参数的子数组中的字符。
//字符数组中某一部分字符转为字符串
String str5 = new String(arr,1,3);
System.out.println(str5);
//String (byte[] bytes) 通过使用平台的默认字符集解码指定的字节数组构造新的 String 。
//不同的字符编码格式(转换方式参照不同的字符集) 1个汉字->gbk->2个字节 1个汉字->utf-8->3个字节
//字符串转为字节数组
byte[] arr2 = "你好".getBytes(); //默认字符编码格式utf-8
byte[] arr3 = "你好".getBytes("gbk"); //字符编码格式gbk
System.out.println(arr2.length);
System.out.println(arr3.length);
//要保证编码解码字符编码一致才不会出现乱码
//字节数组转为字符串-->注意编码格式问题
String str6 = new String(arr2);
System.out.println(str6);
//String(byte[] bytes, String charsetName) 构造一个新的String由指定用指定的字节的数组解码charset 。
String str7 = new String(arr3,"gbk");
System.out.println(str7);
//字节数组中某一部分字节数据转为字符串
//String(byte[] bytes, int offset, int length) 通过使用平台的默认字符集解码指定的字节子阵列来构造新的 String 。
//String(byte[] bytes, int offset, int length, String charsetName) 通过使用指定的字符集解码指定的字节子 String构造新的 String 。
String str8 = new String(arr2,3,3);
System.out.println(str8);
}
import java.util.Arrays;
/*
String 常用方法:
*/
public class Class002_String {
public static void main(String[] args) {
String str1 = new String("jintiantainqihenre");
String str2 = new String("jintiantainqihenre");
//char charAt(int index) 返回指定索引处的 char值。
System.out.println(str1.charAt(5));
//int codePointAt(int index) 返回指定索引处的字符(Unicode代码点)。
System.out.println(str1.codePointAt(5));
//int compareTo(String anotherString) 按字典顺序比较两个字符串。
//str1.compareTo(str2) 返回值 : 0-->str1=str2 >0--> str1>str2 <0-->str1<str2
System.out.println(str1.compareTo(str2));
//int compareToIgnoreCase(String str) 按字典顺序比较两个字符串,忽略大小写差异。
System.out.println(str1.compareToIgnoreCase(str2));
//String concat(String str) 将指定的字符串连接到此字符串的末尾。
System.out.println(str1.concat(str2));
System.out.println(str1);
//boolean contains(CharSequence s) 当且仅当此字符串包含指定的char值序列时,才返回true。
System.out.println(str1.contains("jin"));
//boolean endsWith(String suffix) 测试此字符串是否以指定的后缀结尾。
System.out.println(str1.endsWith("hao"));
//boolean startsWith(String prefix) 测试此字符串是否以指定的前缀开头。
System.out.println(str1.startsWith("jin"));
//字符串转为字节数组,可以指定编码格式
//byte[] getBytes()
//byte[] getBytes(String charsetName)
//void getChars(int srcBegin, int srcEnd, char[] dst, int dstBegin) 将此字符串中的字符复制到目标字符数组中。
char[] arr = new char[6];
str1.getChars(3,7,arr,1);
System.out.println(Arrays.toString(arr));
//int indexOf(String str) 返回指定子字符串第一次出现的字符串中的索引。
System.out.println(str1.indexOf("a"));
//int indexOf(String str, int fromIndex) 从指定的索引处开始,返回指定子字符串第一次出现的字符串中的索引。
System.out.println(str1.indexOf("a",6));
//int lastIndexOf(int ch) 返回指定字符最后一次出现的字符串中的索引。
//int lastIndexOf(int ch, int fromIndex) 返回指定字符最后一次出现的字符串中的索引,从指定的索引开始向后搜索。
System.out.println(str1.lastIndexOf("a"));
//String intern() 返回字符串对象的规范表示。
System.out.println(str1==str2);
System.out.println(str1.intern()==str2.intern());
//boolean isBlank() 如果字符串为空或仅包含 white space代码点,则返回 true ,否则 false 。
System.out.println(str1.isBlank());
System.out.println("".isBlank());
System.out.println(" ".isBlank());
System.out.println(" ".isBlank());
System.out.println(" ".isBlank());
//boolean isEmpty() 返回 true ,当且仅当, length()是 0 。
//int length() 返回此字符串的长度。
System.out.println();
//String repeat(int count) 返回一个字符串,其值为此字符串的串联重复 count次。
System.out.println(str1.repeat(3));
//String replace(CharSequence target, CharSequence replacement) 将此字符串中与文字目标序列匹配的每个子字符串替换为指定的文字替换序列。
System.out.println(str1.replace("a","A"));
//String[] split(String regex) 将此字符串拆分为给定 regular expression的匹配 项 。
System.out.println(Arrays.toString(str1.split("a")));
//去除前后空格 半角空格" " 全角空格" "
//String trim() 返回一个字符串,其值为此字符串,删除了所有前导和尾随空格,其中space被定义为其代码点小于或等于 'U+0020' (空格字符)的任何字符。 --> 只针对于半角空格
System.out.println(" abc ".trim());
//String strip() 返回一个字符串,其值为此字符串,并删除了所有前导和尾随 white space 。 --> 全角以及半角空格
System.out.println(" abc ".strip());
//String stripLeading() 返回一个字符串,其值为此字符串,并删除了所有前导 white space 。
//String stripTrailing() 返回一个字符串,其值为此字符串,并删除所有尾随 white space 。
//String substring(int beginIndex) 返回一个字符串,该字符串是此字符串的子字符串。
System.out.println(str1.substring(5));
//String substring(int beginIndex, int endIndex) 返回一个字符串,该字符串是此字符串的子字符串。 一般结束索引不包含
System.out.println(str1.substring(5,10));
//char[] toCharArray() 将此字符串转换为新的字符数组。
System.out.println(Arrays.toString(str1.toCharArray()));
System.out.println(str1.charAt(str1.length()-1));
//String toLowerCase() 使用默认语言环境的规则将此 String所有字符转换为小写。
//String toUpperCase() 使用默认语言环境的规则将此 String所有字符转换为大写。
System.out.println(str1.toUpperCase());
System.out.println(str2.toLowerCase());
///static String valueOf(boolean b) 返回 boolean参数的字符串表示形式。
System.out.println(String.valueOf(false));
}
}
StringBuilder
可变长字符序列
StringBuilder : 线程不安全,但不保证同步,相对效率较高
适合使用在单线程下大量操作字符串,效率高
StringBuffer : 线程安全的,相对效率较低
多线程下大量操作字符串建议使用StringBuffer
String : 少量修改字符串,适合使用String,因为表示字符串String对象简单,功能强大的API效率: StringBuilder > StringBuffer > String
扩容:
append--> int newCapacity = (oldCapacity << 1) + 2; 每次扩容原容量的2倍+2
public class Class003_StringBuilferStringBuffer {
public static void main(String[] args) {
//StringBuilder() 构造一个字符串构建器,其中不包含任何字符,初始容量为16个字符。
StringBuilder sb = new StringBuilder();
System.out.println(sb);
System.out.println(sb.length()); //字符个数
System.out.println(sb.capacity()); //内部存储数据的字节数组的长度
//StringBuilder(int capacity) 构造一个字符串构建器,其中没有字符,并且具有 capacity参数指定的初始容量。
StringBuilder sb1 = new StringBuilder(10);
System.out.println(sb1);
System.out.println(sb1.length());
System.out.println(sb1.capacity());
//StringBuilder(String str) 构造一个初始化为指定字符串内容的字符串构建器。
StringBuilder sb2 = new StringBuilder("abc");
System.out.println(sb2);
System.out.println(sb2.length());
System.out.println(sb2.capacity());
//StringBuilder append(boolean b) 追加
StringBuilder stringBuilder = sb.append(false);
System.out.println(sb);
System.out.println(stringBuilder==sb);
//StringBuilder delete(int start, int end) 删除此序列的子字符串中的字符。
System.out.println(sb.delete(1,4));
System.out.println(sb);
System.out.println(sb.length());
System.out.println(sb.capacity());
//测试扩容问题
sb.append("1234567890");
System.out.println(sb.length());
System.out.println(sb.capacity());
sb.append("1234");
System.out.println(sb.length());
System.out.println(sb.capacity());
sb.append("1");
System.out.println(sb.length());
System.out.println(sb.capacity());
//StringBuilder insert(int offset, String str) 将字符串插入此字符序列。
System.out.println(sb.insert(3,"haha"));
//StringBuilder reverse() 导致此字符序列被序列的反向替换。
System.out.println(sb.reverse());
System.out.println(sb);
//String 与 StringBuffer|StringBuilder转换问题:
//1.new StringBuilder|StringBuffer(String)
//2.toString() | new String(StringBuilder|StringBuffer)
System.out.println(sb.toString());
}
}
String、StringBuffer与StringBuilder的区别?
三者共同之处:都是final类,不允许被继承,主要是从性能和安全性上考虑的,因为这几个类都是经常被使用着,且考虑到防止其中的参数被参数修改影响到其他的应用。
StringBuffer是线程安全,可以不需要额外的同步用于多线程中;
StringBuilder是非同步,运行于多线程中就需要使用着单独同步处理,但是速度就比StringBuffer快多了;
首先说运行速度,或者说是执行速度,在这方面运行速度快慢为:StringBuilder > StringBuffer > String
String最慢的原因:String为字符串常量,而StringBuilder和StringBuffer均为字符串变量,即String对象一旦创建之后该对象是不可更改的,但后两者的对象是变量,是可以更改的。
String:适用于少量的字符串操作的情况
StringBuilder:适用于单线程下在字符缓冲区进行大量操作的情况
StringBuffer:适用多线程下在字符缓冲区进行大量操作的情况