网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。
需要这份系统化的资料的朋友,可以添加戳这里获取
一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!
}
package array;
/*
动态初始化二维数组
*/
public class Test12 {
public static void main(String[] args){
int[][] a = new int[3][4];
printArray(a);
printArray(new int[][]{{1,2,3},
{4,5,6},
{7,8,9,10}});
}
public static void printArray(int[][] a){
for (int i = 0; i< a.length; i++){
System.out.println();
for (int j = 0; j< a[i].length; j++){
System.out.print(a[i][j] + " ");
}
}
}
}
for (int i = 0;i<arr.length-1;i++){
for (int j = 0;j<arr.length-1-i;j++){
}
}
package array;
/*
冒泡算法
原始:3 2 7 6 8
拿着3和右边的2进行比较。如果左边>右边,交换位置
第一次:2 3 7 6 8
拿着上一次比较结果之后的右边较大的数据和后续的数据继续比较
第二次:2 3 7 6 8
第三次:2 3 6 7 8
第四次:2 3 6 7 8
*/
public class BubbleSort {
public static void main(String[] args){
int[] arr = {9,8,10,7,6,0,11};
int temp;
//经过冒泡排序算法,进行排序
for (int i = 0;i<arr.length-1;i++){
for (int j = 0;j<arr.length-1-i;j++){
if (arr[j]>arr[j+1]) {
temp = arr[j + 1];
arr[j + 1] = arr[j];
arr[j] = temp;
}
}
}
for (int i = 0;i<arr.length;i++){
System.out.print(arr[i]);
}
}
package array;
/*
二分法查找
10 11 12 13 14 15 16 17 18 19
通过二分法找出18这个元素的下标:
(0+10)/5------> 中间元素的下标
拿着中间这个元素和目标元素进行对比:
中间元素是:arr[5] —> 15
15 < 18 被动力节点JAVA基础老杜笔记查找的元素在中间元素的右边
所以开始元素的小标从0变成5+1
在重新计算中间元素下标:
5+1+10 / 2 = 8
8下标对应的元素为18,找到了中间元素和被找的元素相等,下标为8
二分法查找元素算法是基于排序的基础之上,没有排序的数据是无法查找的
*/
public class TwoSaerch {
}
package array;
/
- SUN公司已经为我们写好了一个数组工具类
- java.util.Array
*/
public class ArrayTest02 {
public static void main(String[] args){
int arr[] = {1,5,7,4,3,4};
Arrays.sort(arr);
for (int i = 0; i< arr.length ; i++){
System.out.print(arr[i] + " ");
}
package javaseString;
/*
关于String
1.String表示字符串类型,属于引用数据类型,不属于基本数据类
2.在Java随便使用双引号括起来的都是String对象。例如:”abc“,“def”,“hello world”,这三个String对象
3.Java中规定,双引号括起来的字符串是不可变的,也就是说”abc“从开始到最后,不能变成”abcd“
4.在JDK当中双引号括起来的字符串,都是直接存储在”方法区“的“字符串常量池“当中的
为什么sun公司把字符串存储在一个”字符串常量池“当中呢。因为字符串在实际开发中使用太频繁。为了执行效率,所以把字符串放到了
方法区的字符串常量池当中。
*/
public class Test01 {
public static void main(){
String s1 = “abcd”;
String s2 = “abcd” +“xy”;
//使用new方法来构建字符串对象
//凡是双引号括起来的都在字符串常量池中有一份,凡是new出来的对象都在堆内存中开辟空间
String s3 = new String(“xy”);
}
package javaseString;
public class UserTest {
public static void main(String[] args){
User user = new User(110,“x”);
}
class User{
private int id;
private String name;
public User(){
}
package javaseString;
public class Test02 {
public static void main(String[] args){
String s1 = “hello”;
//"hello"是存储在方法区中的字符串常量池中
//所以这个”hello“不会重建
String s2 = “hello”;
System.out.println(s1 == s2);//true
}
package javaseString;
/*
分析一下程序创建了几个对象
*/
public class Test03 {
public static void main(String[] args){
/*
一共三个对象:
字符串常量池有一个对象
堆内存中有两个String对象
*/
String s1 = new String(“hello”);
String s2 = new String(“hello”);
}
}
package javaseString;
/
* 关于String类中的构造方法
* String s = new String(“”);
* String s = “”; 最常用
* String s = new String(char数组);
* String s = new String(char数组,起始下标,长度)
* String s = new String(byte数组);
* String s = new String(byte数组,起始下标,长度)
*/
public class Test04 {
public static void main(String[] args){
//创建字符串最常用的方式
//这里只掌握常用的构造方法
String s1 = “hello world”;
//String类已经重写了toString方法
System.out.println(s1);
byte[] bytes = {97,98,99};//97a 98b 99c
String s2 = new String(bytes);//支持传入byte数组
//输出一个引用的时候会自动toString方法,默认Object的话,会自动输出对象的内存地址
System.out.println(s2);//abc
//通过输出结果可以得到一个结论,String类已经重写了toString方法。
//输出字符串对象的话,输出的不是对象的内存地址,而是字符串本身。
}
package javaseString;
import javax.crypto.spec.PSource;
import java.nio.charset.StandardCharsets;
import java.util.Locale;
public class Test05 {
public static void main(String[] args){
//String类当中的常用方法
//1.char charAt(int index)
char c= “中国人”.charAt(1);
System.out.println©;//输出国
String s = String.valueOf(x);
public static String valueOf(Object obj) {
return (obj == null) ? “null” : obj.toString();
}
*/
}
在实际开发当中,频繁的拼接字符串会出现在什么问题?
- java的字符串是不可变的,每一次拼接都会产生一个新的字符串,这样会占用大量的方法去内存,造成内存空间的浪费
- String s = “abc”;
- s += “hello”
- 以上两行代码,就导致在方法区字符串常量池中创建了3个字符串对象
package StringBuffer;
/
* 在实际开发当中,频繁的拼接字符串会出现在什么问题?
* java的字符串是不可变的,每一次拼接都会产生一个新的字符串,这样会占用大量的方法去内存,造成内存空间的浪费
* String s = “abc”;
* s += “hello”
* 以上两行代码,就导致在方法区字符串常量池中创建了3个字符串对象
*/
/
* 如果以后想要进行字符串的拼接,那么建议使用JDK中自带的:
* java.lang.StringBuffer/StringBuilder
* 优化StringBuffer性能
* 在创建StringBuffer的时候,尽量给定一个初始化容量
* 最好减少底层数组的扩容次数,预估计一下
* 关键点:给定一个合适的初始化容量,可以提高程序的效率
*
*/
public class Test01 {
public static void main(String[] args) {
//直接使用+=的方法会给方法区中的字符串常量池带来很大的压力
//创建一个初始化容量为16个byte[]数组
StringBuffer stringBuffer = new StringBuffer();
stringBuffer.append(“a”);
stringBuffer.append(“b”);
stringBuffer.append(“c”);
System.out.println(stringBuffer);
//StringBuffer会自动扩容
}
package StringBuffer;
/
- StringBuilder
- StringBuffer和StringBuilder的区别
- StringBuffer中的方法,都有关键字synchronized修饰,表示StringBuffer在多线程环境下运行是安全的
- StringBuilder中的方法都没有关键字synchronized修饰,表示StringBuilder在多线程环境下运行是不安全的。
* - StringBuffer是线程安全的
- StringBuilder是非线程安全的
*/
public class Test02 {
public static void main(String[] args) {
//扩容次数越少,效率越高
StringBuilder stringBuilder = new StringBuilder();
stringBuilder.append(“1”);
stringBuilder.append(“2”);
stringBuilder.append(“3”);
stringBuilder.append(“4”);
System.out.println(stringBuilder);
package Integer;
/*
关于Integer类的构造方法,有两个:
Integer(int)
Integer(String)
*/
public class Test02 {
public static void main(String[] args) {
//将数字100转换为Integer类型
Integer x = new Integer(100);
System.out.println(x);
//将字符串123转换为Integer类型
Integer y = new Integer(“123”);
System.out.println(y);
package Integer;
/*
在JDK1.5之后支持自动拆箱和自动装箱
*/
public class Test04 {
public static void main(String[] args) {
Integer x = 100;//自动装箱 int类型自动转换为Integer
int y = x;//自动拆箱 Integer自动转换为int
}
}
package Integer;
/*
总结所遇到的异常:
空指针异常:NullPointerException
类型转换异常:ClassCastException
数组下标越界异常:ArraryIndexOutOfBoundsException
数组格式化异常:NumberFormatException
*/
public class Test05 {
public static void main(String[] args) {
Integer x = 100;
int y = x;
System.out.println(y);
Integer z = new Integer(“123”);//字符串必须为一串数字,否则会出现数组格式化异常:NumberFormatException
System.out.println(z);
}
package Integer;
import java.io.StringWriter;
}
package Data;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
/*
java中对日期的处理
1.怎么获取当前系统时间
2.Date --> String
3.String --> Date
*/
public class Test01 {
public static void main(String[] args) throws ParseException {
//获取当前系统的时间
Date nowTime = new Date();
System.out.println(nowTime); //Mon Aug 09 09:44:49 CST 2021
* yyyy 年
* MM 月
* dd 日
* HH 时
* mm 分
* ss 秒
* SSS 毫秒
* 注意:在日期格式中,除了y M d H m s S这些字符不能随便写之外,剩下的符号格式自己随意组织
*/
SimpleDateFormat sdf = new SimpleDateFormat(“yyyy-MM-dd HH-mm-ss-SSS”);
String nowTimeStr = sdf.format(nowTime);
System.out.println(nowTimeStr);
}
package Data;
/*
自1970年1月1日 00:00:000到当前系统时间的总毫秒数
简单总结一下System类的相关属性和方法:
System.out out是System的静态变量
System.out.println() println()方法不是System类的,是PrintStream类的方法
System.gc() 建议启动垃圾回收器
System.currentTimeMillis() 自1970年1月1日 00:00:000到当前系统时间的总毫秒数
System.exit(0) 退出JVM
*/
public class Test02 {
public static void main(String[] args) {
long nowTimeMillis = System.currentTimeMillis();
System.out.println(nowTimeMillis);
}
package Data;
import java.text.SimpleDateFormat;
import java.util.Date;
/*
*/
public class Test04 {
public static void main(String[] args) {
//这个时间是:1970-01-01 00:00:00:001
Date time = new Date(1);//注意参数是1毫秒4
SimpleDateFormat sdf = new SimpleDateFormat(“yyyy-MM-dd HH:mm:ss SSS”);
String strTime = sdf.format(time);
System.out.println(strTime);
}
package Numbers;
import java.text.DecimalFormat;
public class DecimalFormatTest01 {
public static void main(String[] args) {
//专门负责数字格式化
//DecimalFormat df = new DecimalFormat(“数字格式”);
/
* 数字格式有哪些
* #代表任意数字
* ,代表千分位
* .代表小数
*
* ,,
* 表示:加入千分位,保留2个小数
*/
DecimalFormat df = new DecimalFormat(“,.”);
String s = df.format(1234.56);
System.out.println(s);
DecimalFormat df2 = new DecimalFormat(“,.0000”);//保留4个小数,不够补0
String s2 =df2.format(1234.56);
System.out.println(s2);
}
package Numbers;
import java.math.BigDecimal;
/*
1.BigDecimal 属于大数据,精度极高。不属于基本数据类型,属于java对象(引用数据)
这是SUN提供的一个类。专门用在财务软件中
2.注意:财务软件中Double是不够用的
财务数据是java.math.BigDecimal
*/
public class BigDecimalTest01 {
public static void main(String[] args) {
//这个100不是普通的100,是精度极高的100
BigDecimal v1 = new BigDecimal(100);
BigDecimal v2 = new BigDecimal(200);
//求和
//v1 + v2 都是引用数据类型不可以使用这个语法
//调用方法求和
BigDecimal v3 =v1.add(v2);
System.out.println(v3);
}
package Numbers;
/*
编写程序,生成5个不重复的随机数。重复的话重新生成
最终生成的5个随机数,放入数组里面,要求这五个随机数不重复
*/
public class RandomTest02 {
public static void main(String[] args) {
//准备一个长度为5的一维数组
int[] arr = new int[5];
for (int i =0; i< 5 ; i++){
arr[i] = -1;
}
int index = 0;
//循环
Random random = new Random();
while(index < arr.length){
int res = random.nextInt(101);
boolean flag = flag(arr,res);
if (!flag){
arr[index++] = res;
这个方法存在bug,有一半的数据不可以用
//排序
Arrays.sort(arr);
//二分法查找 元素所在的下标
int index = Arrays.binarySearch(arr, res);
}
package enumlei;//关键字不可以做标识符
/*
分析以下程序的缺陷,没有使用枚举类型
以下程序可以编译运行,程序本身没有问题
设计缺陷:这个方法的返回值类型不恰当,这个方法只是返回成功和失败,那么最好返回布尔类型,返回值已经偏离了需求。
*/
public class Test01 {
public static void main(String[] args) {
boolean res = divide(10,2);
System.out.println(res);
* 以下程序计算两个int类型的商,计算成功返回1,计算失败返回0
* @param a
* @param b
* @return 返回1表示成功,0表示失败
*/
/*
public static int divide(int a,int b){
try{
int c= a/b;
return 1;//表示执行成功
}catch (Exception e){
return 0;//表示执行失败
}
}*/
public static boolean divide(int a,int b) {
try {
int c = a / b;
return true;//表示执行成功
} catch (Exception e) {
return false;//表示执行失败
}
}
/*
思考:以上的方法设计没毛病,但是在以后的开发过程中,有可能遇到一个方法的执行结果可能包括几种情况
这时布尔类型就无法满足需求,这是需要使用java中的枚举类型
*/
}
package enumlei;
/*
枚举:
1.枚举是一种引用数据类型
2.枚举怎么定义
enum 枚举类型名{
枚举值1,枚举值2
}
3.只有两种类型建议使用布尔类型,超过两种的建议使用枚举类型
*/
public class Test02 {
public static void main(String[] args) {
Result r = divide(10,2);
System.out.println(r == Result.SUCCESS? “Sucess”:“Fail”);
*
* @param a
* @param b
* @return 返回枚举类型,SUCCESS表示成功,FAIL表示失败
*/
public static Result divide(int a,int b ){
try{
int c = a/b;
return Result.SUCCESS;
}catch(Exception e){
return Result.FAIL;
}
}
}
//枚举
enum Result{
//枚举编译成功之后也是生成class文件
//枚举也是一种引用数据类型
//枚举中的每一个值,可以看作是常量
//SUCCESS是枚举类中的一个值
//FAIL 也是枚举中的一个值
SUCCESS,FAIL
}
package exception;
/*
1.什么是异常,java提供异常处理机制有什么用?
以下程序执行过程中发生了不正常的情况,而这种不正常的情况叫做异常
java语言是十分完善的,提供了异常处理方式,以下程序出现了不正常的情况,java把该异常信息打印,
输出到控制台,供程序员参考。程序员看到异常信息之后,可以对程序进行修改,让程序更加健壮
2.以下程序执行控制台出现了:
Exception in thread “main” java.lang.ArithmeticException: / by zero
at exception.Test01.main(Test01.java:7)
这个信息我们称为:异常信息,这个信息是JVM打印的
*/
public class Test01 {
public static void main(String[] args) {
/* int a =10;
int b =0;
int c= a/b; // 实际上JVM执行到此处时会new一个异常对象
System.out.println©;*/
}
package exception;
import lei.NullPointerTest;
/*
Java语言中异常是以什么形式存在的
异常在Java中以类的形式存在,每一个异常类都可以创建异常对象
*/
public class Test02 {
public static void main(String[] args) {
NumberFormatException nfe = new NumberFormatException(“数字格式化异常”);
//也会调用toString
System.out.println(nfe);
//通过异常类,创建异常对象
NullPointerException npe = new NullPointerException(“空指针异常”);
System.out.println(npe);
}
}
package exception;
public class Test03 {
public static void main(String[] args) {
System.out.println(100/0);
/*
程序执行到此处,发生了一个ArithmeticException异常,底层new了一个ArithmeticException异常对象,然后抛出了,由于是main方法调用了100/0,
所以这个异常ArithmeticException抛给了main方法,main方法没有处理,直接抛给了JVM,JVM最终终止了程序的执行。
ArithmeticException继承了RuntimeException,属于运行时异常,在编写阶段不需要进行异常的预先处理
*/
System.out.println(“Hello Word”);
}
}
package exception;
/*
以下代码报错的原因是什么?
doSome方法声明位置上使用了:throws ClassNotFoundExcption,ClassNotFoundExcption是编译时异常,必须在编写代码时进行异常处理,否则报错。
*/
public class Test04 {
public static void main(String[] args) throws ClassNotFoundException {
//main方法中直接调用了doSome方法
//因为doSome方法声明位置上有:throws ClassNotFoundExcption
//我们调用doSome方法的时候必须对这种异常进行预先的处理,如果不处理,编译器报错
doSome();
}
* doSome方法在方法声明的位置上使用了:throws ClassNotFoundExcption
* 这个代码表示doSome()方法执行过程中,有可能会出现ClassNotFoundExcption异常
* @throws ClassNotFoundException 类没有找到异常,父类为Exception,所以该异常属于编译时异常
*/
public static void doSome() throws ClassNotFoundException{
System.out.println(“doSome”);
}
}
package exception;
public class Test05 {
//第一种处理方式:在方法声明的位置上继续使用:throws,来完成异常的上抛。抛给调用者
/*public static void main(String[] args) throws ClassNotFoundException {
doSome();
}*/
//第二种处理方式:try catch
//捕捉意味着把异常拦下了,把异常真正的解决了
public static void main(String[] args) {
try {
doSome();
}catch (ClassNotFoundException e){
e.printStackTrace();
}
}
}
package exception;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
/*
处理异常的第一种方式:在方法声明的位置上使用throws关键字抛出,谁调用这个方法,我就抛给谁
*/
public class Test06 {
/*
一般不建议在main方法上使用throws,因为这个异常如果真的发生了,一定会抛给JVM,那么JVM会终止程序的执行
异常处理机制的作用就是增强程序的健壮性,异常发生了也不会影响程序的执行,所以一般main方法中的异常建议使用try catch进行捕捉
main就不会继续上抛
*/
public static void main(String[] args) {
System.out.println(“main begin”);
try {
m1();
//出异常,这里不会执行
System.out.println(“Hello Word”);
} catch (FileNotFoundException e) {
System.out.println(e);
System.out.println(“文件不存在”);
}
System.out.println(“main end”);
}
public static void m1() throws FileNotFoundException{
System.out.println(“m1 begin”);
m2();
//出异常,这里不会执行
System.out.println(“m2 end”);
}
//抛FileNotFoundException的父类IOException,这样可以,因为IOException包括FileNotFoundException。
//throws可以抛出多个异常,可以使用逗号隔开
public static void m2() throws FileNotFoundException{
System.out.println(“m2 begin”);
m3();
//第二种方法进行捕捉
/*try {
m3();
} catch (FileNotFoundException e) {
System.out.println(“该文件不存在”);
}*/
编译报错的原因是什么?
第一:这里调用了一个构造方法:FileInputStream
第二:这个构造方法的声明位置上有:throws FileNotFoundException
第三:通过类的继承结构看到:FileNotFoundException 的父类为IOException,IOException的父类为Exception最终得知,
FileNotFoundException是编译时异常
编译时异常,要求程序员必须在编译过程中对他进行处理。
*/
//FileInputStream fileInputStream = new FileInputStream(“C:Users77DownloadsDocuments07-JavaSE进阶每日复习与笔记11.txt”);
FileInputStream fileInputStream = new FileInputStream(“C:Users77DownloadsDocuments07-JavaSE进阶每日复习与笔记1.txt”);
//出异常这里不会执行
System.out.println(“m3 end”);
}
}
package exception;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
/*
try catch
1.catch语句块后面()可以写本身的类型,也可以写父类型
2.catch可以写多个,建议catch的时候一个一个精确的处理
3.catch写多个的时候,必须遵循从上到下,从小到大
4.catch (FileNotFoundException | ArithmeticException e) JDK8的新特性
*/
public class Test07 {
public static void main(String[] args) {
try {
FileInputStream fileInputStream = new FileInputStream(“C:Users77DownloadsDocuments07-JavaSE进阶每日复习与笔记11.txt”);
fileInputStream.read();//需要处理IO异常
System.out.println(100/0);//运行时异常,编译时可以处理可以不处理
} catch (FileNotFoundException | ArithmeticException e) {
e.printStackTrace();
System.out.println(“文件不存在”);
}catch (IOException e){
e.printStackTrace();
}
/*try {
FileInputStream fileInputStream = new FileInputStream(“C:Users77DownloadsDocuments07-JavaSE进阶每日复习与笔记11.txt”);
} catch (IOException e) {//多态
e.printStackTrace();
System.out.println(“文件不存在”);
}*/
System.out.println(“后续代码可以执行”);
}
}
package exception;
/*
异常对象有两个非常重要的方法:
获取异常简单的描述信息:
String msg = exception.getMessage();
*/
public class Test08 {
public static void main(String[] args) {
//这里只是new了异常对象,没有将异常对象抛出,JVM认为这只是一个普通的Java对象
NullPointerException e = new NullPointerException(“空指针异常”);
//获取异常信息,这个信息实际上就是构造方法
System.out.println(e.getMessage());
}
package exception;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
/*
关于try catch中的finally子句:
1.在finally子句中的代码是最后执行的,是一定会执行的,即使try语句块中的代码出现了异常
finally语句必须和try一起出现,不能单独编写
2.finally语句通常使用在哪些情况下?
finally语句块中完成资源的释放/关闭
因为finally中的的代码比较有保障。
即使try语句块中的代码出现异常,finally中的代码块也会正常执行
*/
public class Test10 {
public static void main(String[] args) throws IOException {
//设置为全局变量
FileInputStream fileInputStream = null;
try {
//创建输入流对象
//这里的fileInputStream是一个局部变量
fileInputStream = new FileInputStream(“C:Users77DownloadsDocuments07-JavaSE进阶每日复习与笔记11.txt”);
String s= null;
s.toString(); //会出现空指针异常
System.out.println(“3”);
//即使以上程序出现异常,流也必须关闭,放在当前位置有可能不会关闭
//fileInputStream.close();
} catch (FileNotFoundException e) {
e.printStackTrace();
}catch (IOException e){
e.printStackTrace();
}catch (NullPointerException e){
e.printStackTrace();
}finally {
System.out.println(“1”);
//流的关闭放在这比较保险
if (fileInputStream != null){
//close方法有异常采用捕捉的方式
try {
fileInputStream.close();
}catch (IOException e){
e.printStackTrace();
}
System.out.println(“2”);
}
}
}
package exception;
public class Test11 {
public static void main(String[] args) {
/*
try和finally,没有catch
try不能单独使用
try finally可以联合使用
*/
try{
System.out.println(“try”);
return;
}finally {
//有return,finally也会执行
System.out.println(“finally”);
}
}
package exception;
public class Test12 {
public static void main(String[] args) {
try{
System.out.println(“try”);
System.exit(0);
//退出JVM finally不执行
}finally{
System.out.println(“finally”);
}
}
}
package exception;
/*
finally面试题
*/
public class Test13 {
public static void main(String[] args) {
int res = m();
System.out.println(res);//100
}
/*
java语法规则(有一些规则是不能破坏的)
java中有一条这样的规则:
方法体中的代码必须遵循自上而下顺序依次逐行执行
*/
public static int m(){
int i = 100;
try{
//这行代码出现在int i = 100;的下面,所以最终结果必须是返回100
// return语句还必须保证是最后执行的,一旦执行,整个方法结束
return i;
}finally {
i++;
}
}
}
/*
反编译之后的效果
public static int m(){
int i = 100;
int j = i;
i ++;
return j;
Exceptrion exception;
exception;
i++;
throw exception;
}
*/
package exception;
/*
final 关键字
final修饰的类无法继承
final修饰的变量无法修改
final修饰的方法无法覆盖
finally 关键字
finally和try连用
finally语句块中的代码必须执行
finalize 方法
是Object类中的一个方法名
这个方法是由垃圾回收器GC负责调用的
*/
public class Test14 {
public static void main(String[] args) {
//final是一个关键字,表示最终的不变的
final int i =100;
}
package exception;
/*
1.可以进行自定义异常
2.自定义异常的步骤:
第一步:编写一个类继承exception或者RuntimeException
第二步:提供两个构造方法,一个无参数的,一个带有String参数的
*/
public class Test15 {
public static void main(String[] args) {
//创建异常对象(没有手动抛出异常)
MyException myException = new MyException(“no”);
//打印异常信息
myException.printStackTrace();
String msg = myException.getMessage();
System.out.println(msg);
}
}
class MyException extends Exception{
public MyException() {
}
}
package exception;
//测试改良之后的栈
public class Test16 {
public static void main(String[] args) {
Mystack mystack = new Mystack();
//压栈
try {
mystack.push(new Object());
mystack.push(new Object());
mystack.push(new Object());
mystack.push(new Object());
mystack.push(new Object());
mystack.push(new Object());
mystack.push(new Object());
mystack.push(new Object());
mystack.push(new Object());
mystack.push(new Object());
mystack.push(new Object());
} catch (MyStackOperationException e) {
System.out.println(e.getMessage());
}
//弹栈
try {
mystack.pop();
mystack.pop();
mystack.pop();
mystack.pop();
mystack.pop();
mystack.pop();
mystack.pop();
mystack.pop();
mystack.pop();
mystack.pop();
mystack.pop();
} catch (MyStackOperationException e) {
e.printStackTrace();
}
}
package exception;
//测试改良之后的栈
public class Test16 {
public static void main(String[] args) {
Mystack mystack = new Mystack();
//压栈
try {
mystack.push(new Object());
mystack.push(new Object());
mystack.push(new Object());
mystack.push(new Object());
mystack.push(new Object());
mystack.push(new Object());
mystack.push(new Object());
mystack.push(new Object());
mystack.push(new Object());
mystack.push(new Object());
mystack.push(new Object());
} catch (MyStackOperationException e) {
System.out.println(e.getMessage());
}
//弹栈
try {
mystack.pop();
mystack.pop();
mystack.pop();
mystack.pop();
mystack.pop();
mystack.pop();
mystack.pop();
mystack.pop();
mystack.pop();
mystack.pop();
mystack.pop();
} catch (MyStackOperationException e) {
e.printStackTrace();
}
}
package exception;
/*
之前在讲解方法覆盖的时候,遗留了一个问题
重写之后的方法不能比重写之前的方法抛出更多的异常,可以更少
*/
public class Test17 {
}
class A{
public void doSome(){}
public void doOtger() throws Exception{}
}
class B extends A{
/*public void doSome() throws Exception{ //父类没有抛出异常,子类不可以抛
}*/
public void doOther(){ //不抛出异常不报错
}*/
public void doOther() throws Exception{
}*/
public void doOther() throws NullPointerException{
}
package collection;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;
/*
关于collection接口中的常用方法
1.Collection中能存放什么元素?
没有使用泛型之前,Collection中可以存储Object的所有子类型
使用“泛型”之后,Collection中只能存储某个具体类型
集合后期我们会学习“泛型”,Collection中什么都能存,只要Object子类型都行
(集合中不能直接存储基本数据类型,也不能存储Java对象,只存储Java对象的内存地址)
2.Collection中的常用方法
boolean add(Object e) add方法,向集合中添加元素
int size() 获取集合中元素的个数
void clear() 清空集合
boolean contains(Object o) 判断当前集合中是否包含元素o,包含返回true,不包含返回false
boolean remove(Object o) 删除集合中某个元素
boolean isEmpty() 判断集合中元素的个数是否为0
Object[] toArray() 调用这个方法可以把集合转换成数组
Iterator iterator() 返回在此 collection 的元素上进行迭代的迭代器。
*/
public class Test01 {
public static void main(String[] args) {
//创建一个集合对象
//Collection c = new Collection(); 接口是抽象的,无法实例化
Collection c = new ArrayList();//多态
//add方法,向集合中添加元素
c.add(1200);//自动装箱,实际上是放进去了一个对象的内存地址。Integer x = new Integer(1200);
c.add(3.14);
c.add(new Object());
c.add(true);
}
package collection;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashSet;
import java.util.Iterator;
/
* 关于集合遍历/迭代器
*
*/
public class Test02 {
public static void main(String[] args) {
//以下遍历方式/迭代方式,是所有的Collection通用的一种方式
//在Map集合中不能使用,在所有Collection以及子类中使用
//创建集合对象
Collection c = new ArrayList();
//添加元素
c.add(“abc”);
c.add(10);
c.add(2);
c.add(“world”);
//遍历/迭代
//第一步:获取集合的迭代器对象Iterator
Iterator iterator = c.iterator();
//第二步:通过以上的迭代器对象开始迭代/遍历集合
/*
以下方法是迭代器Iterator中的方法
boolean hasNext()
如果仍有元素可以迭代,则返回 true。
E next()
返回迭代的下一个元素。
*/
while(iterator.hasNext()){
Object obj = iterator.next();
System.out.println(obj);
}
}
}
package collection;
/*
深入Collection集合的contains方法
boolean contains(Object o)
判断集合是否包含某个对象o
如果包含返回true,如果不包含返回flase
*/
public class Test04 {
public static void main(String[] args) {
//创建集合
Collection c = new ArrayList();
//向集合中存储元素
String s1 = new String(“abc”);
String s2 = new String(“def”);
c.add(s1);
c.add(s2);
}
package collection;
/*
测试contains方法
*/
public class Test05 {
public static void main(String[] args) {
//创建集合对象
Collection c = new ArrayList();
User u1 = new User(“j”);
User u2 = new User(“h”);
c.add(u1);
c.add(u2);
//这里的class类没有重写equals方法
//所以contains方法为false
//重写了equals方法之后,返回true
User u3 = new User(“j”);
boolean flag = c.contains(u3);
System.out.println(flag);
}
}
class User{
private String name;
}
package collection;
/*
测试contains方法
测试remove方法
*/
public class Test05 {
public static void main(String[] args) {
//创建集合对象
Collection c = new ArrayList();
User u1 = new User(“j”);
User u2 = new User(“h”);
c.add(u1);
c.add(u2);
//这里的class类没有重写equals方法
//所以contains方法为false
//重写了equals方法之后,返回true
User u3 = new User(“j”);
boolean flag = c.contains(u3);
System.out.println(flag);
}
class User{
private String name;
}
Collection c = new ArrayList();
//此时获取的迭代器,指向的是那是集合中没有元素状态下的迭代器
//一定要注意:集合结构只要发生改变,迭代器就必须重新获取
//Iterator iterator = c.iterator();
c.add(1);
c.add(2);
c.add(3);
//迭代器没有重新获取那么会出现:ConcurrentModificationException异常
Iterator iterator1 = c2.iterator();
while(iterator1.hasNext()){
Object o = iterator1.next();
//c2.remove(o); 直接通过集合去删除元素,没有通知迭代器(导致迭代器的快照和原集合状态不同)
//删除元素之后,集合的结构发生了变化,应该重新去获取迭代器,
//但是,循环下一次的时候并没有重新获取迭代器,所以会出现异常
//使用迭代器来删除,不会出现异常
//迭代器删除时,会自动更新迭代器并且更新集合(删除集合中的元素)
iterator1.remove();//删除的一定是迭代器当前指向的元素
System.out.println(o);
}
package collection;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;
/*
关于集合的remove
重点:当集合的结构发生改变时,迭代器必须重新获取,如果不重新获取迭代器
那么就会出现异常ConcurrentModificationException。
重点:在迭代集合元素过程中,不能调用集合对象的remove方法,删除元素;
会出现ConcurrentModificationException。
*/
public class Test06 {
public static void main(String[] args) {
Collection c = new ArrayList();
//此时获取的迭代器,指向的是那是集合中没有元素状态下的迭代器
//一定要注意:集合结构只要发生改变,迭代器就必须重新获取
//Iterator iterator = c.iterator();
c.add(1);
c.add(2);
c.add(3);
//迭代器没有重新获取那么会出现:ConcurrentModificationException异常
}
package collection;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
/*
List接口中的常用方法
1.list集合存储元素特点:有序可重复
有序:有下表
2.list既然是Collection接口的子接口,那么一定有自己特有的方法:
以下只列出list接口特有的常用的方法:
void add(int index, E element)
在列表的指定位置插入指定元素(可选操作)。
E get(int index)
返回列表中指定位置的元素。
int indexOf(Object o)
返回此列表中第一次出现的指定元素的索引;如果此列表不包含该元素,则返回 -1。
int lastIndexOf(Object o)
返回此列表中最后出现的指定元素的索引;如果列表不包含此元素,则返回 -1。
E remove(int index)
移除列表中指定位置的元素(可选操作)。
E set(int index, E element)
用指定元素替换列表中指定位置的元素(可选操作)。
*/
public class ListTest01 {
public static void main(String[] args) {
//创建list类型的集合
List l1 = new ArrayList<>();
}
package collection;
/*
ArrayList集合:
1.默认初始化容量10,(底层先创建了一个长度为0的数组,当添加一个元素的时候,初始化容量为10)
2.集合底层是一个Object[]数组
3.构造方法:
new ArrayList();
new ArrayList(20);
4.ArrayList的集合扩容:
原容量的1.5倍
ArrayList集合底层是数组,尽可能减少扩容,因为数组扩容效率比较低,建议在使用ArrayList的时候预估计初始化容量。
5.数组的优点:检索效率比较高
6.数组的缺点:随机增删效率比较低,数组无法存储大数据量(很难找到一块非常巨大的连续空间)
7.数组末尾添加元素的效率很高,不受影响
8.这么多的集合中,用那个最多?
ArrayList,因为往末尾添加元素,效率不受影响。另外我们检索/查找某个元素的操作比较多
*/
public class ArrayListTest01 {
public static void main(String[] args) {
//默认初始容量为10
List list1 = new ArrayList();
System.out.println(list1.size());
//指定初始容量为20
List list2 = new ArrayList(20);
System.out.println(list2.size());
//size方法是获取当前集合元素的个数,不是获取集合的容量
}
List mylist1 = new ArrayList();
List myList2 = new ArrayList(100);
private void linkFirst(E e) {
final Node f = first;
final Node newNode = new Node<>(null, e, f);
first = newNode;
if (f == null)
last = newNode;
else
f.prev = newNode;
size++;
modCount++;
}
/
- Links e as last element.
*/
void linkLast(E e) {
final Node l = last;
final Node newNode = new Node<>(l, e, null);
last = newNode;
if (l == null)
first = newNode;
else
l.next = newNode;
size++;
modCount++;
}
package collection;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
/*
1.泛型这种语法机制,只在程序编译阶段起作用,只是给编译器擦参考的(运行阶段泛型没有用)
2.使用泛型的好处:
第一:集合中存储的元素类型统一了
第二:从集合中取出的元素是泛型指定的类型。不需要进行大量的”向下类型转换“
3.使用泛型的缺点:
导致结合中存储的元素缺乏多样性
大多数业务中,集合中元素的类型还是统一的,这种机制还是被认可的
*/
public class GenericTest01 {
public static void main(String[] args) {
//不适用泛型机制分析程序存在的缺点
/*List mylist= new ArrayList();
C c = new C();
B b = new B();
mylist.add©;
mylist.add(b);*/
while(iterator.hasNext()){
A obj = (A) iterator.next();
if (obj instanceof C){
C x = © obj;
x.move();
x.catchM();
}else if (obj instanceof B){
B x = (B) obj;
x.move();
x.fiy();
}
}*/
//利用泛型
//使用泛型list之后,表示list集合只允许存储Animal类型的数据
//用泛型来指定集合中的数据类型
//指定类为A,那么其他类型就会编译报错
//这样用了泛型之后,集合中元素的数据类型就更加统一的
List mylist = new ArrayList();
C c = new C();
B b = new B();
mylist.add©;
mylist.add(b);
///表示迭代器迭代的是A类型
Iterator iterator = mylist.iterator();
while(iterator.hasNext()){
//使用泛型迭代的数据,每一次返回的数据类型都是A
//这里不需要强制类型的转换
A a = iterator.next();
a.move();
//调用子类型特有的方法还是需要强制类型转换的
if (a instanceof C){
C C = ©a;
C.catchM();
}else {
B B = (B)a;
B.fiy();
}
}
}
class A{
public void move(){
System.out.println(“move”);
}
}
class C extends A{
public void catchM(){
System.out.println(“catch”);
}
}
class B extends A{
public void fiy(){
System.out.println(“fly”);
}
}
package collection;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
/*
JDK8之后引入了:自动类型推断机制
*/
public class GenericTest02 {
public static void main(String[] args) {
//ArrayList<这里的类型会自动推断>()
//自动类型推断
List mylist = new ArrayList<>();
mylist.add(new A());
mylist.add(new C());
mylist.add(new B());
}
package collection;
/*
自定义泛型:
自定义泛型的时候,<>尖括号中的是一个标识符,随便写
java源代码中常出现的是和
E:是element首字母
T:是Type的首字母
*/
public class GenericTest03/只是一个标识符随便写/ {
public void doSome(AA o){
System.out.println(o);
}
public static void main(String[] args) {
GenericTest03 gt = new GenericTest03<>();
gt.doSome(“abc”);
}
class MyIterator{
public T get(){
return null;
}
}
package collection;
/*
增强for循环
*/
public class ForEachTest01 {
public static void main(String[] args) {
int[] arr = {1,55,4,7,3,14};
for (int i = 0; i< arr.length ; i++){
System.out.println(arr[i]);
}
System.out.println(“-------------”);
//增强for
//缺点:没有下标,在需要使用下标的循环中,建议不使用
for(int e: arr){
System.out.println(e);
}
}
}
package collection;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
/*
集合使用增强foreach
*/
public class ForEachTest02 {
public static void main(String[] args) {
List list = new ArrayList<>();
list.add(“1”);
list.add(“2”);
list.add(“3”);
//遍历 使用迭代器的方式
Iterator it= list.iterator();
while(it.hasNext()){
System.out.println(it.next());
}
System.out.println(“----------”);
//使用下标的方式,只针对于有下标的集合
for (int i = 0; i< list.size(); i++){
System.out.println(list.get(i));
}
System.out.println(“----------------”);
//使用foreach
for (String i :list){
System.out.println(i);
}
}
package collection;
/*
HashSet集合:
无序不可重复
*/
public class HashsetTest01 {
public static void main(String[] args) {
Set str = new HashSet<>();
//添加元素
str.add(“11”);
str.add(“55”);
str.add(“44”);
str.add(“22”);
str.add(“11”);
str.add(“33”);
}
package collection;
/*
TreeSet集合存储元素的特点:
1.无序不可重复的,但是存储的元素可以自动按照大小顺序排序,称为:排序集合
2.无序,这里指的是存进去的顺序和取出来的顺序不同,并且没有下标
*/
public class HashsetTest02 {
public static void main(String[] args) {
Set strs = new TreeSet<>();
strs.add(“11”);
strs.add(“23”);
strs.add(“45”);
strs.add(“22”);
strs.add(“45”);
/*
11
22
23
45
从小到大自动排序
*/
for (String i : strs) {
System.out.println(i);
}
}
}
package collection;
import java.util.Collection;
import java.util.HashMap;
import java.util.Map;
/*
java.util.Map的常用方法:
1.Map和Collection没有继承关系
2.Map集合以key和value的方式存储数据:键值对
key和value都是引用数据类型
key和value都是存储对象的内存地址
key起主导作用,value是key的一个附属品
3.Map接口中常用的方法
V put(K key, V value) 向Map集合添加键值对
void clear() 清空Map
V get(Object key) 通过key获取value
boolean containsKey(Object key) 判断Map中是否包含某个key
boolean containsValue(Object value) 判断Map中是否包含某个value
boolean isEmpty() 判断Map集合中元素个数是否为0
Set keySet() 获取Map集合中所有的key (所有的键是一个Set集合)
V remove(Object key) 通过key删除键值对
int size() 获取Map集合中所有的键值对
Collection values() 获取所有的value
Set<Map.Entry<K,V>> entrySet() 将Map集合转换成Set集合
map集合
key value
1 z
2 s
3 w
Set set = map.entrySet();
set集合
1=z 【注意:Map集合通过wntrySet()方法转换成的Set集合,Set集合中的元素类型是Map.Entry<K,V> ,Map.Entry<K,V>是Map中的静态内部类】
2=s
3=w
*/
public class MapTest01 {
public static void main(String[] args) {
//创建Map对象,向Maop集合中添加键值对
Map<Integer,String> map = new HashMap<>();
//添加键值对
map.put(1,“zz”); //1在这里进行了自动装箱
map.put(2,“ss”);
map.put(3,“ww”);
System.out.println(“-----通过key来获取value-------”);
//通过key来获取value
String s = map.get(2);
System.out.println(s);
System.out.println(“-----获取键值对的数量-------”);
//获取键值对的数量
System.out.println(“键值对数量:”+map.size());
//通过key删除key-value
System.out.println(“-----通过key删除key-value-------”);
map.remove(1);
System.out.println(“键值对数量:”+map.size());
//判断是否包含某个key
//contains方法底层调用的都是equals方法进行比对的,所以自定义的类型都需要重写equals方法
System.out.println(“-----判断是否包含某个key-------”);
System.out.println(map.containsKey(1));
//判断是否包含某个value
System.out.println(“-----判断是否包含某个value-------”);
System.out.println(map.containsValue(“ww”));
//获取所有的value
System.out.println(“-----获取所有的value-------”);
Collection c= map.values();
for (String e:c){
System.out.println(e);
}
//清空集合
System.out.println(“-----清空集合-------”);
map.clear();
System.out.println(map.size());
//判断是否为空
System.out.println(“-----判断是否为空-------”);
System.out.println(map.isEmpty());
}
package collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
public class Myclass {
//声明一个静态内部类
private static class InnerClass{
public static void m1(){
System.out.println(“静态方法执行”);
}
public void m2(){
System.out.println(“静态内部类实例方法执行”);
}
}
}
class MyMap{
public static class Myentry<k,v>{
}
package collection;
import java.util.*;
/*
Map集合的便利
第一种方式:获取所有的key,来遍历value
第二种方式:Set<Map.Entry<K,V>> entrySet() 将Map集合转换成Set集合
把Map集合全部转换成Set集合
Set集合中元素的类型是:Map.Entry<K,V>
*/
public class MapTest02 {
public static void main(String[] args) {
Map<Integer,String> map = new HashMap<>();
map.put(1,“zz”);
map.put(2,“ss”);
map.put(3,“ww”);
}
package collection;
import java.util.HashSet;
import java.util.Objects;
import java.util.Set;
/*
1.向Map集合中存,以及从Map集合中取,都是先调用key的hashCode方法,然后再调用equals方法
equals方法可能调用,也可能不调用
拿put(k,v)举例,
k.hashCode()方法返回哈希值,哈希值经过哈希算法转换为数组下标,数组下标位置上如果是null,equals不需要执行
拿get(k,v)举例
如果数组下标为null,不需要执行;如果数组单向链表上有元素时,就需要equals
2.注意:如果一个类的equals方法重写了,那么hashCode方法也需要重写,并且如果equals方法返回true,hashCode方法返回值必须一样
3.重写方法直接使用IDEA方法生成,这两个方法要同时生成
4.结论:放在HashMap集合key部分,以及放在HashSet集合中的元素,需要同时从写hashCode方法和equals方法
*/
public class HashMapTest02 {
public static void main(String[] args) {
Student student1 = new Student(“zz”);
Student student2 = new Student(“zz”);
System.out.println(student1.equals(student2)); //重写之后相等
System.out.println(student1.hashCode()); //
System.out.println(student2.hashCode()); // 重写之后都是3935
}
class Student{
private String name;
if(obj == null || !(obj instanceof Student))return false;
if (obj == this) return true;
//类型转换
Student s = (Student) obj;
if (this.name == s.name)return true;
return false;
}*/
}
package collection;
import java.util.Properties;
/*
目前只需要掌握Properties属性类对象的相关方法即可
Properties是一个Map集合,继承Hashtable,Properties的key和value都是String类型
Properties是属性类对象
*/
public class PropertiesTest01 {
public static void main(String[] args) {
//创建一个Properties对象
Properties properties = new Properties();
//需要掌握Properties的两个方法,一个存,一个取
properties.setProperty(“url”,“http://”);
properties.setProperty(“driver”,“com.mysql.jac.Dirver”);
properties.setProperty(“uername”,“root”);
properties.setProperty(“password”,“123”);
//通过key获取value
String s1 = properties.getProperty(“url”);
String s2 = properties.getProperty(“driver”);
String s3 = properties.getProperty(“username”);
String s4 = properties.getProperty(“password”);
System.out.println(s1);
System.out.println(s2);
System.out.println(s3);
System.out.println(s4);
}
}
package collection;
import java.util.TreeSet;
/*
1.TreeSet集合底层实际上是一个TreeMap
2.TreeMap集合底层是一个二叉树
3.放到TreeSet集合中的元素,等同于放到TreeMap集合key部分
4.Treeset集合中的元素,:无序不可重复,但是可以按照元素的大小顺序自动拍戏。称为可排序集合
*/
public class TreeSetTest01 {
public static void main(String[] args) {
//创建一个TreeSet集合
TreeSet ts = new TreeSet<>();
ts.add(“zz”);
ts.add(“za”);
ts.add(“aa”);
ts.add(“wa”);
ts.add(“sd”);
for (String s:ts){
System.out.println(s);
}
TreeSet ts1 = new TreeSet<>();
ts1.add(100);
ts1.add(200);
ts1.add(45);
ts1.add(78);
ts1.add(150);
for (int i : ts1){
System.out.println(i);
}
}
}
package collection;
import java.util.TreeSet;
/*
对自定义类型来说,TreeSet可以排序吗?
以下程序中对于Person类型来说,无法排序,因为没有指定排序规则
以下程序出现了这个异常:
java.lang.ClassCastException: class collection.
Person cannot be cast to class java.lang.Comparable
*/
public class TreeSetTest02 {
public static void main(String[] args) {
Person p1 = new Person(20);
Person p2 = new Person(20);
Person p3 = new Person(20);
Person p4 = new Person(20);
Person p5 = new Person(20);
TreeSet treeSet = new TreeSet<>();
treeSet.add(p1);
treeSet.add(p2);
treeSet.add(p3);
treeSet.add(p4);
treeSet.add(p5);
for (Person p : treeSet){
System.out.println§;
}
}
}
class Person{
int age;
}
package collection;
/*
TreeSet集合元素可排序的第二种方式:使用比较器
结论:放在TreeMap或者TreeMap结合key部分的元素想要做到排序,包括两种方式:
第一种:放到集合java.lang.Comparable接口
第二种:再够在TreeMap或者TreeSet集合的时候给他传一个比较器对象
Comparator和Comparable怎么选择
当比较规则不会发生改变的时候,或者说当比较规则只有一个的时候,建议使用Comparable接口。
如果比较规则有多个,并且需要多个比较规则频繁切换,建议使用Comparator接口
Comparator接口符合OCP原则
*/
public class TreeSetTest06 {
public static void main(String[] args) {
//创建TreeSet的集合的时候,需要使用这个比较器
TreeSet w = new TreeSet<>(new Wcomparator());
w.add(new W(100));
w.add(new W(101));
w.add(new W(10));
w.add(new W(800));
w.add(new W(2000));
w.add(new W(1000));
for (W s :w){
System.out.println(s);
}
}
//单独编写一个比较器
//实现Comparator接口
class Wcomparator implements Comparator {
}
class W {
int age;
}
package collection;
import java.util.Collections;
import java.util.Comparator;
import java.util.TreeSet;
public class CollectionTest02 {
public static void main(String[] args) {
TreeSet ts = new TreeSet<>(new Comparator() {
@Override
public int compare(Integer o1, Integer o2) {
return o2-o1;
}
});
ts.add(1);
ts.add(100);
ts.add(150);
for (int i :ts){
System.out.println(i);
}
}
package collection;
import java.util.*;
/*
java.util.Collection 集合接口
java.util.Collections 集合工具类
*/
public class CollectionTest1 {
public static void main(String[] args) {
List list = new ArrayList<>();
//变成线程安全的
Collections.synchronizedList(list);
//排序
list.add(“avf”);
list.add(“abc”);
list.add(“qw”);
list.add(“wes”);
System.out.println(“------------------”);
Collections.sort(list);
for (String s:list){
System.out.println(s);
}
List list1 = new ArrayList<>();
list1.add(new W2(200));
list1.add(new W2(250));
list1.add(new W2(400));
list1.add(new W2(500));
list1.add(new W2(700));
//对list集合元素排序,需要保证list结合中的元素实现:Comparable接口
Collections.sort(list1);
for (W2 w2 :list1){
System.out.println(w2.age);
}
System.out.println(“------------------”);
Set set = new HashSet<>();
set.add(“king”);
set.add(“king1”);
set.add(“king2”);
set.add(“king32”);
set.add(“king4”);
//将Set集合转换为List
List mylist = new ArrayList<>(set);
Collections.sort(mylist);
for (String s:mylist){
System.out.println(s);
}
}
class W2 implements Comparable {
int age;
}
创建文件字节流文件
//以下都是采用了绝对路径的方式
//文件路径:C:Users77DownloadsDocuments07-JavaSE进阶每日复习与笔记 会制动把编程,因为java中的代表转义
//也可以写成C:/Users/77/Downloads/Documents/07-JavaSE进阶每日复习与笔记
package streamsIO;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
/*
java.io.FileInputStream
1.文件字节输入流,万能的,任何类型的文件都可以采用这个流来读
2.字节的方式,完成输入操作,完成读的操作(硬盘---->内存)
*/
public class FileInputTest01 {
public static void main(String[] args) {
FileInputStream fis = null;
//创建文件字节流文件
//以下都是采用了绝对路径的方式
//文件路径:C:Users77DownloadsDocuments07-JavaSE进阶每日复习与笔记 会制动把编程,因为java中的代表转义
//也可以写成C:/Users/77/Downloads/Documents/07-JavaSE进阶每日复习与笔记
try {
fis = new FileInputStream(“C:Users77DownloadsDocuments07-JavaSE进阶每日复习与笔记11.txt”);
int readData = fis.read();
System.out.println(readData);//这个方法的返回值是:读取到的字节本身
readData = fis.read();
System.out.println(readData);
readData = fis.read();
System.out.println(readData);
readData = fis.read();
System.out.println(readData);
readData = fis.read();
System.out.println(readData);//读取到末尾了,返回值为-1
//文件中为:abcd
}
package streamsIO;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
一次读取一个字节,这样内存和硬盘交互太频繁了,基本上时间、资源都耗费了
*/
public class FileInputTest02 {
public static void main(String[] args) {
FileInputStream fis = null;
try {
fis = new FileInputStream(“C:Users77DownloadsDocuments07-JavaSE进阶每日复习与笔记11.txt”);
/*while(true){
int readDate = fis.read();
if (readDate == -1){
break;
}
System.out.println(readDate);
}*/
//改进while
int readDate = 0;
while((readDate = fis.read())!=-1){
System.out.println(readDate);
}
}
package streamsIO;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
/*
int read(byte[] b)
一次最多读取b.length个字节
减少硬盘和内存的交互,提高程序的执行效率
往byte[]数组当中读
*/
public class FileInputTest03 {
public static void main(String[] args) {
FileInputStream fis = null;
try {
//使用相对路径
//IDEA当前的默认路径为,工程Project的根就是IDEA的默认当前路径
fis = new FileInputStream(“myfile.txt”);
//开始读,采用byte数组,一次读取多个字节,最多读取“数组.length”个字节
byte[] bytes = new byte[4];//一次最多读取四个字节
//xiaoqi
int readCount = fis.read(bytes);//4
System.out.println(readCount);
//以下方法是把byte数组全部转换成了字符串
//System.out.println(new String(bytes));
//不应该全部都转,应该是读取了多少个字节,转换多少个
System.out.println(new String(bytes,0,readCount));
}
package streamsIO;
/*
最后的版本
*/
public class FileInputTest04 {
public static void main(String[] args) {
FileInputStream fis = null;
try {
fis = new FileInputStream(“myfile.txt”);
//准备一个数组
byte[] bytes = new byte[4];
/*while(true){
int readCount = fis.read(bytes);
if (readCount==-1){
break;
}
System.out.println(new String(bytes,0,readCount));
}*/
int readCount = 0;
while((readCount = fis.read(bytes))!= -1){
System.out.println(new String(bytes,0,readCount));
}
}
package streamsIO;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
/*
其他常用的两个方法:
int available() 返回流当中剩余的没有读到的字节数量
long skip(long n) 跳过几个字节不读
*/
public class FileInputeTest05 {
public static void main(String[] args) {
FileInputStream fis = null;
try {
fis = new FileInputStream(“myfile.txt”);
//读一个字节
//int readByte = fis.read();//还剩下五个字节
//这个方法有什么用
//不需要循环了,直接读一次就可以
/*System.out.println(“字节数量:” + fis.available());
byte[] bytes = new byte[fis.available()];//这种方式不太适合太大的文件,因为bytes[]数组不能太大
int readCount = fis.read(bytes);
System.out.println(new String(bytes));*/
}
package streamsIO;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
/*
文件字节输出流,负责写
从内存到硬盘
*/
public class FileOutputTest01 {
public static void main(String[] args) {
FileOutputStream fos = null;
try {
//文件不存在时会自动创建新的文件
//这种方式需要谨慎使用,因为他会把源文件清空
//以追加的方式在文件末尾写入。不会清空源文件内容
fos = new FileOutputStream(“myfile.txt”,true);
//开始往文件中写
byte[] bytes = {97,98,99,100};
//将byte数组全部写出
fos.write(bytes);//abcd
//将bytes数组的一部分写出
fos.write(bytes,0,2);//写出ab
String s= “china”;
byte[] ss = s.getBytes();//将字符串转换为byte数组
fos.write(ss);
//写完之后一定要刷新
fos.flush();
} catch (IOException e) {
e.printStackTrace();
}finally {
if (fos != null)
try {
fos.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
package streamsIO;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
/*
使用Fileinput和FileOutput完成文件的拷贝
拷贝的过程应该是一边读一边写,
使用以上的字节流拷贝文件的时候,文件类型随意,万能的,什么样的文件都能拷贝
*/
public class Copy1 {
public static void main(String[] args) {
FileInputStream fis = null;
FileOutputStream fos = null;
try {
fis = new FileInputStream(“C:Users77DownloadsDocuments07-JavaSE进阶每日复习与笔记day34课堂笔记.txt”);
fos = new FileOutputStream(“D:学习day34课堂笔记.txt”);
//最核心的一边读一边写
byte[] bytes = new byte[1024*1024];
int readCount = 0;
while((readCount = fis.read(bytes)) != -1){
fos.write(bytes,0,readCount);
}
//输出流最后要刷新
fos.flush();
} catch (Exception e) {
e.printStackTrace();
}finally {
if (fos != null)
try {
fos.close();
} catch (IOException e) {
e.printStackTrace();
}
if(fis != null)
try {
fis.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
package streamsIO;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
/*
FileReader:
文件字符输入流,只能读取普通文本。
读取文本内容时,比较方便,快捷
*/
public class FileReaderTest01 {
public static void main(String[] args) {
FileReader reader = null;
try {
reader = new FileReader(“myfile.txt”);
char[] chars = new char[4];//一次读取四个字符
reader.read(chars);
for (char c : chars){ //按照字符的方式读取,第一次a 第二次b 第三次 小
System.out.println©;
}
} catch (IOException e) {
e.printStackTrace();
}finally {
if (reader!=null)
try {
reader.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
package streamsIO;
/*
FileWriter:
文件字符输出流,写
只能输出普通文本
*/
public class FileWriterTest01 {
public static void main(String[] args) {
FileWriter out = null;
try {
//创建文件字符输出流对象
out = new FileWriter(“file”,true);
}
package streamsIO;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
/*
使用FileReader和FileWriter进拷贝的话,只能拷贝普通文本文件
*/
public class Copy02 {
public static void main(String[] args) {
FileReader in = null;
FileWriter out = null;
try {
in = new FileReader(“file”);
out = new FileWriter(“file1”);
char[] chars = new char[1024 * 512];//1M
int readCount = 0;
while((readCount = in.read(chars))!= -1){
out.write(chars,0,readCount);
}
}
package streamsIO;
import lei.T;
import java.io.BufferedReader;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
/*
BufferReader:
带有缓冲区的字符输入流
使用这个流的时候不需要自定义char数组,或者说不需要自定义byte数组,自带缓冲
*/
public class BuggeredReaderTest01 {
public static void main(String[] args) {
FileReader reader = null;
BufferedReader buf = null;
try {
reader = new FileReader(“myfile.txt”);
//当一个流的构造方法中需要一个流的时候,这个被传进来的流叫做:节点流
//外部负责包装的流,叫做包装流,还有一个名字叫做:处理流
//像当前这个程序来说,FileReader就是一个节点流,BufferReader就是处理流
buf = new BufferedReader(reader);
/*//读一行
String firstLine = buf.readLine();
System.out.println(firstLine);
//在读一行
String SecondLIne = buf.readLine();
System.out.println(SecondLIne);//读到最后一行的时候返回null*/
}
package streamsIO;
import java.io.BufferedReader;
import java.io.FileInputStream;
import java.io.InputStreamReader;
public class BufferReadTest02 {
public static void main(String[] args) throws Exception {
FileInputStream fileInputStream = new FileInputStream(“file”);
//FileInputStream是一个字节流,不是一个字符流,BufferedReader里面需要传一个字符流
//BufferedReader buf = new BufferedReader(fileInputStream);
//fileInputStream是节点流,inputStreamReader是包装流
/*InputStreamReader inputStreamReader = new InputStreamReader(fileInputStream);//将节点流转换为字符流
//inputStreamReader是节点流,bufferedReader是包装流
BufferedReader bufferedReader = new BufferedReader(inputStreamReader);*/
BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(fileInputStream));
//合并
String line = null;
while((line = bufferedReader.readLine())!=null){
System.out.println(line);
}
//关闭,关闭最外层
bufferedReader.close();
}
}
package streamsIO;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.FileWriter;
import java.io.IOException;
/*
BufferWriter:带有缓存的字符输出流
*/
public class BufferWriterTest01 {
public static void main(String[] args) throws IOException {
BufferedWriter out = new BufferedWriter(new FileWriter(“file2”));
out.write(“xiaoqi”);
out.write(“ ”);
out.write(“1111”);
out.flush();
out.close();
}
}
package streamsIO;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.PrintStream;
/*
标准的字节输出流。默认输出到控制台
*/
public class PrintStreamTest {
public static void main(String[] args) throws FileNotFoundException {
//联合起写
System.out.println(“hello word”);
//分开写
PrintStream ps = System.out;
ps.println(“hello l”);
ps.println(“hello l”);
ps.println(“hello a”);
这些是之前System类的使用过的方法和属性
System.gc();
System.currentTimeMillis();
PrintStream ps1 = System.out;
System.exit();
*/
//标准输出流不再指向控制台,指向myfile文件
PrintStream printStream= new PrintStream(new FileOutputStream(“myfile”));
System.setOut(printStream);
System.out.println(“11”);
System.out.println(“222”);
System.out.println(“3333”);
}
}
package streamsIO;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.PrintStream;
import java.text.SimpleDateFormat;
import java.util.Date;
/*
日志工具
*/
public class LogUtil {
记录日志的方法
*/
try {
out = new PrintStream(new FileOutputStream(“log.txt”,true));
//改变输出方向
System.setOut(out);
//日期当前时间
Date date = new Date();
//格式化
SimpleDateFormat sdf = new SimpleDateFormat(“yyyy-MM-dd HH:mm:ss SSS”);
String strtime= sdf.format(date);
System.out.println(strtime + “:” + msg);
} catch (FileNotFoundException e) {
e.printStackTrace();
}
}
}
package streamsIO;
public class LogTest {
public static void main(String[] args) {
//测试工具类是否好用
LogUtil.log(“调用了System类的gc方法,建议启动垃圾回收器”);
LogUtil.log(“调用了UserService的doSome()方法”);
LogUtil.log(“用户尝试进行登录,验证失败”);
}
}
package streamsIO;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectOutputStream;
import java.io.Serializable;
/*
1.NotSerializableException: streamsIO.S: S类不支持序列化
2.参与学序列化和反序列化的对象,必须实现Serializable这个接口
3.注意:通过源代码发现,Serializable接口只是一个标志接口
public interface Serializable{
}
这个接口当中什么代码也没有
他起到一个标志的作用,Java虚拟机,看到这个类实现了这个接口,可能会对这个类进行特殊待遇
java虚拟机看到了这个接口之后,会为该类自动生成一个序列化版本号。
4.序列化版本号:
*/
public class ObjectOutputStreamTest01 {
public static void main(String[] args) {
S s = new S(111,“zz”);
ObjectOutputStream objectOutputStream = null;
//序列化
try {
objectOutputStream = new ObjectOutputStream(new FileOutputStream(“data”));
objectOutputStream.writeObject(s);
objectOutputStream.flush();
} catch (IOException e) {
e.printStackTrace();
}finally {
if (objectOutputStream!=null){
try {
objectOutputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
//继承一个可序列化接口
class S implements Serializable {
private int no;
private String name;
}
package streamsIO;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;
/*
一次序列化多个对象,可以把对象放到序列化集合当中
*/
public class ObjectOutputStreamTest02 {
public static void main(String[] args) throws Exception {
List list = new ArrayList<>();
list.add(new U(1,“z”));
list.add(new U(2,“x”));
list.add(new U(3,“P”));
ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream(“users”));
//序列化一个集合,一个集合有多个对象
oos.writeObject(list);
oos.flush();
oos.close();
}
class U implements Serializable {
private int number;
private String name;
}
package streamsIO;
import java.io.*;
public class ObjectInputeStreamTest01 {
public static void main(String[] args) throws IOException, ClassNotFoundException {
ObjectInputStream objectInputStream = new ObjectInputStream(new FileInputStream(“data”));
//反序列化
Object obj = objectInputStream.readObject();
//反序列化回来是一个学生对象的toString方法
System.out.println(obj);
objectInputStream.close();
}
}
package streamsIO;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.util.ArrayList;
import java.util.List;
public class ObjectInputStreamTest02 {
public static void main(String[] args) throws Exception{
ObjectInputStream ois = new ObjectInputStream(new FileInputStream(“users”));
/*Object obj = ois.readObject();
System.out.println(obj instanceof List);*/
List list = (List) ois.readObject();//向下类型转换
for (U u:list){
System.out.println(u);
}
ois.close();
}
}
package streamsIO;
/*
File
1.File类和四大家族没有关系,所有File类不能完成文件的读写
2.File对象代表,文件和路径名的抽象表示形式
C:Users77DownloadsDocuments07-JavaSE进阶每日复习与笔记 是File对象、
一个File对象可能是目录也可能是文件
File只是一个路径名的抽象表示形式
3.掌握File类的常用方法
*/
public class FileTest01 {
public static void main(String[] args) throws IOException {
File f1 = new File(“D:file”);
System.out.println(f1.exists());//判断是否存在的
}
package streamsIO;
import java.io.File;
import java.text.SimpleDateFormat;
import java.util.Date;
/*
File类的常用方法
*/
public class FileTest02 {
public static void main(String[] args) {
File f1 = new File(“myfile”);
//或取名文件
System.out.println(f1.getName());
}
package streamsIO;
import java.io.File;
/*
File中的listFiles方法
File[] listFiles()
返回一个抽象路径名数组,这些路径名表示此抽象路径名表示的目录中的文件。
*/
public class FileTest03 {
public static void main(String[] args) {
//File[] listFile()
//获取当前目录下的所有子文件
File f = new File(“D:”);
File[] files = f.listFiles();
for (File file:files){
System.out.println(file.getAbsoluteFile());//所有子文件
}
}
}
package streamsIO;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
public class Copy03 {
public static void main(String[] args) {
//拷贝源和拷贝目标
//调用方法拷贝
File f1 = null;
File f2 = null;
* 拷贝目录
* @param src
* @param dest
*/
private static void CopyDir(File src, File dest) {
if (src.isFile()){
//src是一个文件的话,递归结束
//是文件的时候需要拷贝
FileInputStream fileInputStream = null;
FileOutputStream fileOutputStream = null;
try {
fileInputStream = new FileInputStream(src);
byte[] bytes = new byte[1024*1024];
String path = dest.getAbsolutePath().endsWith(“”)?dest.getAbsolutePath(): dest.getAbsolutePath() + “” + src.getAbsolutePath().substring(3);
fileOutputStream = new FileOutputStream(path);
int readCount = 0;
while((readCount = fileInputStream.read(bytes))!= -1){
fileOutputStream.write(bytes,0,readCount);
}
fileOutputStream.flush();
} catch (Exception e) {
e.printStackTrace();
}finally {
if (fileInputStream != null){
try {
fileInputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if (fileOutputStream != null){
try {
fileOutputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
return;
}
//获取源下面的子目录
File[] files = src.listFiles();
for (File file: files){
//System.out.println(file.getAbsolutePath());//获取所有文件的绝对路径
//可能是文件、可能是目录
if (file.isDirectory()){
String srcDir = file.getAbsolutePath();//获取源目录的绝对路径
//System.out.println(srcDir);
String destDir = dest.getAbsolutePath().endsWith(“”)?dest.getAbsolutePath(): dest.getAbsolutePath() + “” + srcDir.substring(3);
//System.out.println(destDir);
File newFile = new File(destDir);
if (!newFile.exists()){
newFile.mkdirs();
}
}
CopyDir(file,dest);
}
}
}
package streamsIO;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.util.Properties;
/*
IO和Properties联合使用
非常好的设计理念:以后经常改变的数据,可以单独写到一个文件中,使用程序动态的读取
将来只需要修改这个文件的内容,Java代码不需要改动,不需要重新编译,服务器也不需要重新重启,就可以拿到动态的信息
类似于以上机制的这种文件被称为配置文件
并且当配置文件中的内容格式是:
key = value
的时候,我们把这种配置文件叫做属性配置文件
java规范中要求,属性配置文件建议以properties结尾,但是不是必须的
这种以properties对象是专门存放属性配置文件内容的一个类
*/
public class IOPropertiesTest01 {
public static void main(String[] args) throws Exception {
/*
Properties是一个Map集合,key和value都是String类型。
想将userinfo文件中的数据加载到Properties对象当中。
*/
//新建一个输入流对象
FileReader fileReader = new FileReader(“demosrcstreamsIO퇢nfo.properties”);
//新建一个Map集合
Properties properties = new Properties();
//调用Properties对象的load方法将文件中的数据加载到Map集合当中
properties.load(fileReader);//文件中的数据顺着管道,加载到Map集合中,其中=左边作为key,右边作为value username = admin
}
username=admin
password=123
在属性配置文件中#是注释
#属性配置文件的key重复的话,value会覆盖
#属性配置文件中可以有空格,但是最好不要有空格
#不建议中间使用:
#建议中间使用=的格式
package thread;
/*
分析程序有几个线程,除垃圾回收之外,有几个线程
一个线程(因为程序只有一个栈)
一个main方法中调用m1,m1调用m2,m2调用m3 都在一个栈中
*/
public class ThereadTest01 {
public static void main(String[] args) {
System.out.println(“main begin”);
m1();
System.out.println(“main over”);
}
}
// 定义线程类
public class MyThread extends Thread{
public void run(){
}
}
// 创建线程对象
MyThread t = new MyThread();
// 启动线程。
t.start();
package thread;
/*
实现线程的第一种方式:
编写一个类,直接继承java.lang。Thread,重写run方法
void run()
如果该线程是使用独立的 Runnable 运行对象构造的,则调用该 Runnable 对象的 run 方法;否则,该方法不执行任何操作并返回。
如何创建线程? new就可以了
怎么启动线程? 调用线程对象的short()方法
*/
public class ThreadTest02 {
public static void main(String[] args) {
//这里是main方法。这里的代码属于主线程,在主栈中运行
//新建一个分支线程对象
MyThread myThread = new MyThread();
//启动线程
myThread.start();
//这里的代码还是运行在主线程中
}
class MyThread extends Thread{
public void run(){
//编写程序,这段程序运行在分支线程中
}
}
package thread;
/*
实现线程的第一种方式:
编写一个类,直接继承java.lang。Thread,重写run方法
void run()
如果该线程是使用独立的 Runnable 运行对象构造的,则调用该 Runnable 对象的 run 方法;否则,该方法不执行任何操作并返回。
以下程序的输出结果有这样的特点:
有先有后,有多有少
*/
public class ThreadTest02 {
public static void main(String[] args) {
//这里是main方法。这里的代码属于主线程,在主栈中运行
//新建一个分支线程对象
MyThread myThread = new MyThread();
//启动线程
//myThread.run(); //如果只调用run方法不会启动线程,不会分配新的分支栈(这种方式就是单线程)
//start()方法的作用是:启动一个分支线程,在JVM中开辟一个新的栈空间,这段代码瞬间就结束
//这段代码的任务只是为了开启新的栈空间,只要新的栈空间开出来了,start()方法就结束了,线程就启动成功了。
//启动成功的线程就自动调用run方法,并且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(){
//编写程序,这段程序运行在分支线程中
for (int i = 0; i<1000;i++){
System.out.println(“分支线程 —>” + i);
}
}
}
package thread;
/*
实现线程的第二种方式,编写一个类实现java.lang.Runnable接口
*/
public class ThreadTest03 {
public static void main(String[] args) {
//创建一个可运行的对象
//MyRunnable myRunnable = new MyRunnable();
//将可运行的对象封装成一个线程对象
Thread thread = new Thread(new MyRunnable());//合并之后的代码
//启动线程
thread.start();
for (int i = 0; i<1000;i++){
System.out.println(“主线程 —>” + i);
}
}
}
//这并不是一个线程类,是一个可运行的类,他还不是一个线程
class MyRunnable implements Runnable{
@Override
public void run() {
for (int i = 0; i<1000;i++){
System.out.println(“分支线程 —>” + i);
}
}
}
package thread;
import lei.T;
/*
采用匿名内部类
*/
public class ThreadTese04 {
public static void main(String[] args) {
//创建线程对象,采用匿名内部类的方式
Thread thered = new Thread(new Runnable() {
@Override
public void run() {
for (int i = 0; i<1000;i++){
System.out.println(“分支线程 —>” + i);
}
}
});
//启动线程
thered.start();
for (int i = 0; i<1000;i++){
System.out.println(“主线程 —>” + i);
}
}
}
package thread;
/*
1.怎么获取当前线程对象
Thiead t = Thread.currentThread();
返回值t就是当前线程
2.获取线程对象的名字
线程对象。getName()
3.修改线程对象的名字
线程对象。setName(“线程名字”)
4.当没有设置线程名称的时候,线程的默认名字为
Thread-0
Thread-1
*/
public class ThreadTest05 {
public static void main(String[] args) {
//current就是当前线程
//这个方法出现在主线程中,这就是主线程
Thread current = Thread.currentThread();
System.out.println(current.getName());//main 主方法名字
//创建线程对象
M m = new M();
M m2 = new M();
//设置线程的名字
m.setName(“m1”);
m2.setName(“m2”);
//获取线程的名字
System.out.println(m.getName());//默认名字Thread-0
System.out.println(m2.getName());
//启动线程
m.start();
m2.start();
}
}
class M extends Thread{
@Override
public void run() {
for (int i = 0; i<10;i++){
//current就是当前线程
//当m线程执行run方法,当前线程就是m
//当m2线程执行,当前线程就是m2
Thread current = Thread.currentThread();
//System.out.println(current.getName() + " "+ i);
//System.out.println(super.getName() + " "+ i);
System.out.println(this.getName() + " "+ i);
}
}
}
package thread;
import lei.T;
/*
关于线程的sleep方法:
static void slep(long millis)
1.静态方法 Thread.sleep(1000);
2.参数是毫秒
3.作用:让当前线程进入休眠状态,进入休眠状态,放弃占有cpu时间片,让给其他线程使用
出现在那个线程中,就让那个线程休眠
4.Thread.sleep() 可以达到这种效果: 间隔一定的时间,去执行一段特定的代码。
*/
public class ThreadTest06 {
public static void main(String[] args) {
/*try {
//让当前线程进入休眠
Thread.sleep(1000*5);
} catch (InterruptedException e) {
e.printStackTrace();
}
//5秒后执行
System.out.println(“hello word”);*/
for (int i =0;i<10;i++){
System.out.println(Thread.currentThread().getName() + " — >" + i);
//睡眠一秒,执行一次
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
package thread;
/*
关于sleep方法
*/
public class ThreadTest07 {
public static void main(String[] args) {
M1 m = new M1();
m.setName(“m”);
m.start();
}
class M1 extends Thread{
@Override
public void run() {
for (int i =0;i<10;i++){
System.out.println(Thread.currentThread().getName() + " --> " + i);
}
}
}
package thread;
/*
唤醒一个正在睡眠的线程,这个不是中断线程的执行,是终止线程的睡眠
*/
public class ThreadTest08 {
public static void main(String[] args) {
Thread t = new Thread(new MyRunnable2());
t.setName(“t”);
t.start();
}
package thread;
/*
在java中强行终止一个线程
这种方式有很大的缺点:容易丢失数据,,因为这种方式是直接将线程杀死
线程没有保存的数据会丢失,不建议使用
*/
public class ThreadTest09 {
public static void main(String[] args) {
Thread thread = new Thread(new MyRunnable3());
thread.setName(“t”);
thread.start();
//模拟5秒睡眠
try {
Thread.sleep(1000*5);
} catch (InterruptedException e) {
e.printStackTrace();
}
//5秒之后强行终止t线程
thread.stop();//已过时
}
}
class MyRunnable3 implements Runnable{
@Override
public void run() {
for (int i =0;i<10;i++){
System.out.println(Thread.currentThread().getName() + “–>” + i);
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
package thread;
/*
合理终止线程
*/
public class ThreadTest10 {
public static void main(String[] args) {
MyRunnable4 myRunnable4 = new MyRunnable4();
Thread thread = new Thread(myRunnable4);
thread.setName(“t”);
thread.start();
//模拟五秒
try {
Thread.sleep(1000*5);
} catch (InterruptedException e) {
e.printStackTrace();
}
//终止线程
//想要什么时候终止t的执行,修改run为false
myRunnable4.run = false;
}
}
class MyRunnable4 implements Runnable{
boolean run = true;//设置一个布尔标记
@Override
public void run() {
for (int i =0; i<10;i++) {
if (run) {
System.out.println(Thread.currentThread().getName() + “—>” + i);
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
else{
//return就结束了,在结束之前还有什么没有保存的,在这里就可以保存
//save
return;
}
}
}
}
class MyThread1 extends Thread {
public void doSome(){
MyThread2 t = new MyThread2();
t.join(); // 当前线程进入阻塞,t线程执行,直到t线程结束。当前线程才可以继续。
}
}
package TgreadSAFE;
/*
不使用线程同步机制,多线程对同一个账户进行取款,出现了线程安全问题
*/
public class Account {
private String acton;//账户
private double balance;//余额
网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。
需要这份系统化的资料的朋友,可以添加戳这里获取
一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!
法
try {
m.sleep(1000);//在执行的时候还是会转换成 Thread.sleep() 这行代码的作用是当前线程进入休眠,main方法进入休眠
//这行代码出现在main方法中,main线程休眠
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(“hello world”);
}
}
class M1 extends Thread{
@Override
public void run() {
for (int i =0;i<10;i++){
System.out.println(Thread.currentThread().getName() + " --> " + i);
}
}
}
package thread;
/*
唤醒一个正在睡眠的线程,这个不是中断线程的执行,是终止线程的睡眠
*/
public class ThreadTest08 {
public static void main(String[] args) {
Thread t = new Thread(new MyRunnable2());
t.setName(“t”);
t.start();
}
package thread;
/*
在java中强行终止一个线程
这种方式有很大的缺点:容易丢失数据,,因为这种方式是直接将线程杀死
线程没有保存的数据会丢失,不建议使用
*/
public class ThreadTest09 {
public static void main(String[] args) {
Thread thread = new Thread(new MyRunnable3());
thread.setName(“t”);
thread.start();
//模拟5秒睡眠
try {
Thread.sleep(1000*5);
} catch (InterruptedException e) {
e.printStackTrace();
}
//5秒之后强行终止t线程
thread.stop();//已过时
}
}
class MyRunnable3 implements Runnable{
@Override
public void run() {
for (int i =0;i<10;i++){
System.out.println(Thread.currentThread().getName() + “–>” + i);
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
package thread;
/*
合理终止线程
*/
public class ThreadTest10 {
public static void main(String[] args) {
MyRunnable4 myRunnable4 = new MyRunnable4();
Thread thread = new Thread(myRunnable4);
thread.setName(“t”);
thread.start();
//模拟五秒
try {
Thread.sleep(1000*5);
} catch (InterruptedException e) {
e.printStackTrace();
}
//终止线程
//想要什么时候终止t的执行,修改run为false
myRunnable4.run = false;
}
}
class MyRunnable4 implements Runnable{
boolean run = true;//设置一个布尔标记
@Override
public void run() {
for (int i =0; i<10;i++) {
if (run) {
System.out.println(Thread.currentThread().getName() + “—>” + i);
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
else{
//return就结束了,在结束之前还有什么没有保存的,在这里就可以保存
//save
return;
}
}
}
}
class MyThread1 extends Thread {
public void doSome(){
MyThread2 t = new MyThread2();
t.join(); // 当前线程进入阻塞,t线程执行,直到t线程结束。当前线程才可以继续。
}
}
package TgreadSAFE;
/*
不使用线程同步机制,多线程对同一个账户进行取款,出现了线程安全问题
*/
public class Account {
private String acton;//账户
private double balance;//余额
网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。
需要这份系统化的资料的朋友,可以添加戳这里获取
版权声明:
本文来源网络,所有图片文章版权属于原作者,如有侵权,联系删除。
本文网址:https://www.bianchenghao6.com/h6javajc/20771.html