JavaSe

一、Java简介

1.C/S,B/S 简介

_C/S_结构(Client/Server)

C/S架构,即Client/Server(客户端/服务器)架构,是一个典型的两层架构。通过将任务合理分配到客户端和服务器,降低了系统的通讯开销,需要安装客户端才可进行管理操作。

客户端包含一个或多个运行在用户计算机上的程序,有两个服务器,一个是数据库服务器,通过数据库连接客户端访问服务器端数据;另一种是套接字服务器,服务器通过套接字程序与客户端通信。

客户端和服务器端的程序不同,用户的程序主要在客户端,服务器端主要提供数据管理、数据共享、数据及系统维护和并发控制等,客户端程序主要完成用户的具体的业务。

开发比较容易,操作简便,但应用程序的升级和客户端程序的维护较为困难。

_B/S_结构(Browers/Server)

B/S架构,即Brower/Server(浏览器/服务器)架构。它由逻辑上相互分离的表示层、业务层和数据层构成。表示层向客户提供数据,业务层实施业务和数据规则,数据层定义数据访问标准;三层体系结构中的核心是组件对象模型。

B / S系统统一了客户端,无需特殊安装,拥有Web浏览器即可;它将系统功能实现的核心部分集中到服务器上,简化了系统的开发、维护和使用。

两者的区别:

1、建立基础不同

C/S是建立在局域网的基础上的;而,B/S是建立在广域网的基础上的。

2、硬件环境不同

C/S 一般建立在专用的网络上,小范围里的网络环境,局域网之间再通过专门服务器提供连接和数据交换服务。

B/S 建立在广域网之上的,不必有专门的网络硬件环境,例与电话上网,租用设备,信息自己管理。有比C/S更强的适应范围, 一般只要有操作系统和浏览器就行。

3、对安全要求不同

C/S 一般面向相对固定的用户群,对信息安全的控制能力很强。一般高度机密的信息系统采用C/S 结构适宜,可以通过B/S发布部分可公开信息.

B/S 建立在广域网之上, 对安全的控制能力相对弱, 面向是不可知的用户群。

4、对程序架构不同

C/S 程序更加注重流程, 可以对权限多层次校验, 对系统运行速度可以较少考虑。

B/S对安全以及访问速度的多重考虑, 建立在需要更加优化的基础之上。

5、软件重用不同

C/S 程序不可避免的考虑整体性, 构件的重用性不如在B/S要求下的构件的重用性好。

B/S对的多重结构,要求构件相对独立的功能, 能够相对较好的重用。

6、系统维护不同

C/S 程序由于整体性, 必须整体考察, 处理出现的问题以及系统升级。 升级难, 可能是再做一个全新的系统

B/S 构件组成,方面构件个别的更换,实现系统的无缝升级。 系统维护开销减到最小;用户从网上自己下载安装就可以实现升级。

7、处理问题不同

C/S 程序可以处理用户面固定, 并且在相同区域, 安全要求高需求, 与操作系统相关。 应该都是相同的系统

B/S 建立在广域网上, 面向不同的用户群, 分散地域, 这是C/S无法作到的;与操作系统平台关系最小。

8、用户接口不同

C/S 多是建立的Window平台上,表现方法有限,对程序员普遍要求较高

B/S 建立在浏览器上, 通过WEB服务或其他公共可识别描述语言可跨平台,使用更灵活。不仅可应用在Window平台上,还可应用于unix/Linux等平台。

9、信息流不同

C/S 程序一般是典型的中央集权的机械式处理, 交互性相对低

B/S 信息流向可变化, B-B B-C B-G等信息、流向的变化, 更象交易中心。

2.Java特点

简单-弱化指针概念

面向对象-贴近人的思考

分布式-可使用多台服务器支持一个服务

跨平台-Java虚拟机

安全性-内存管理,垃圾回收机制

健壮性-异常处理会让程序有更好的容错性

二、Java基本语法

1.数据类型

1.1基本类型

低—高

byte,short,char—int—long—float—double

  • int 4字节
  • byte 1字节

高到低强制转换,低到高自动转换(==范围小的变量可以直接转换为范围大的变量==)

1
2
3
4
5
6
7
float fv=0.2f;
float fv1=2;//有小数必须加f
double d=0.2d;//d可有可无
byte a=12;//0000 1100
int b = a ;//自动转换00000000 00000000 00000000 00001100
char c='a';
int B=c;//97
1
2
3
4
5
        int a=1;
double b=2;
byte c=1;
// int d =a+b+c;报错
double e =a+b+c;
1
2
3
//强制类型转换会造成数据丢失
int a =20;
byte b=(byte) a;

1.2数组

1
2
3
4
//动态初始化
int[] nums=new int[10];
//静态初始化
int[] arr={1,2,3};

1.3二维数组

1
2
3
4
5
int array[][]= new int[2][5];
array[1][1]=9;
int arrays[][]={{1,2},{2,3}};
System.out.println(array[1][1]);
System.out.println(arrays[1][1]);

2.常用api

2.1 Math

屏幕截图 2022-01-04 120626

2.2 短路运算

1
2
c=4;
if(c<4&&c++<4);//c<4不满足,c++不执行

2.3 三元运算符及随机数

1
2
3
a>b?a:b;
Random r = new Random();
int i = r.nextInt(100)+1;

2.4 字符串比较

1
2
3
4
String s1="abc";
String s2=new String("abc");
System.out.println(s1==s2);//Falese,地址不同
s1.equals(s2);//true

2.5 保留三位小数

1
printf("%.3f",c);

####2.6 toString

直接输出对象变量 sout(new Student);(可省略toString)

1
2
3
4
5
6
public class Test02 {
public static void main(String[] args) {
System.out.println(new Student("luaho",19).toString());
}
}
//Student{name='luaho', age=19}

2.7 equals

1
2
3
4
5
6
7
8
9
10
11
12
13
14
public class Student {
private String name;
private int age;
@Override
public boolean equals(Object o) {
if (o instanceof Student){
//判断o是不是学生类.s1.equals(s2),s2是o,s1是调用者
return this.name.equals(((Student) o).name);
//o需要强转
}else {
return false;
}
}
}
1
2
3
4
5
6
7
public class Test02 {
public static void main(String[] args) {
Student l1 = new Student("luhao", 19);
Student l2 = new Student("luhao", 19);
System.out.println(l1.equals(l2));
}
}
1
2
3
4
5
6
7
8
public boolean equals(Object o) {
//判断是不是一个对象
if (this == o) return true;
//判断是否为null
if (!(o instanceof Student)) return false;
Student student = (Student) o;
return getAge() == student.getAge() && Objects.equals(getName(), student.getName());
}

2.8 equals

更安全

1
2
3
4
5
6
7
8
public class Test02 {
public static void main(String[] args) {
String s = new String("luhao");
String s1=null;
//采用Objects不会有空指针异常,不出错
System.out.println(Objects.equals(s1, s));
}
}

源码:

1
2
3
public static boolean equals(Object a, Object b) {
return (a == b) || (a != null && a.equals(b));
}

2.9 System

2.9.1 exit

System.exit(0),JVM虚拟机停止运行

2.9.2 currentTimeMiller
1
2
3
4
5
6
7
8
9
10
public class Test02 {
public static void main(String[] args) {
long start=System.currentTimeMillis();
for (int i = 0; i < 100000; i++) {
System.out.println("输出"+i);
}
long end=System.currentTimeMillis();
System.out.println((end-start)/1000.0);
}
}
2.9.3 复制数组
1
2
3
4
5
6
7
8
9
public class Test02 {
public static void main(String[] args) {
int []array={10,20,30,40,50,60,70};
int []arr2=new int[6];
System.arraycopy(array,3,arr2,2,3);
System.out.println(Arrays.toString(arr2));
}
}
//[0, 0, 40, 50, 60, 0]

复制从array第3+1个开始,到arr2第2+1,开始粘贴,粘贴3个

2.10 BigDemical

解决精度问题

屏幕截图 2022-01-04 140956

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
public class Test02 {
public static void main(String[] args) {
double a=0.1;
double b=0.2;
System.out.println(a+b);
System.out.println("-------------");
BigDecimal c=BigDecimal.valueOf(b);
BigDecimal d=BigDecimal.valueOf(a);
BigDecimal e=c.add(d);
System.out.println(e);
}
}
//0.30000000000000004
//-------------
//0.3

除不尽:

1
2
3
4
5
6
7
8
9
10
public class Test02 {
public static void main(String[] args) {
BigDecimal c=BigDecimal.valueOf(10.0);
BigDecimal d=BigDecimal.valueOf(3.0);
//3.33333333
BigDecimal e=c.divide(d,2, RoundingMode.HALF_UP);
System.out.println(e);
}
}
//3.33

2.11 日期与时间

2.11.1 Calendar
1
2
3
4
5
6
7
8
9
10
11
12
13
14
public class Test02 {
public static void main(String[] args) throws ParseException {
Calendar ca =Calendar.getInstance();
int i = ca.get(Calendar.YEAR);
System.out.println(i);
int i1 = ca.get(Calendar.MONTH) + 1;
System.out.println(i1);
int i2 = ca.get(Calendar.DAY_OF_YEAR);
System.out.println(i2);
ca.add(DAY_OF_YEAR,6);
Date date =ca.getTime();
System.out.println(date);
}
}
1
2
3
4
2022
1
4
Mon Jan 10 17:27:35 CST 2022
2.11.2 Date
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
public class Test02 {
public static void main(String[] args) {
Date d1 = new Date();
System.out.println(d1);
System.out.println("--------------");
long time =d1.getTime();
System.out.println(time);
System.out.println("-------------");
long date =1000*60*60;
//设置时间从1970.1.1开始
long d3=System.currentTimeMillis();
Date d4 = new Date(d3);
System.out.println(d4);
System.out.println("---------- ----");
Date d2=new Date(date);
//时期毫秒值转成日期对象
System.out.println(d2);
}
}
1
2
3
4
5
6
7
Tue Jan 04 14:33:37 CST 2022
--------------
1641278017585
-------------
Tue Jan 04 14:33:37 CST 2022
--------------
Thu Jan 01 09:00:00 CST 1970
2.11.3 SimpleDateFormat

屏幕截图 2022-01-04 144336

EEE:星期几

a:上午还是下午

parse方法是将特定字符串时间转成看不懂的

1
2
3
4
5
6
7
8
9
10
11
12
public class Test02 {
public static void main(String[] args) {
Date date = new Date();
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss EEE a");
String d1 = sdf.format(date);
System.out.println(d1);
System.out.println("-----------");
long l = System.currentTimeMillis();
String F = sdf.format(l);
System.out.println(F);
}
}
1
2
3
2022-01-04 15:09:28 周二 下午
-----------
2022-01-04 15:09:28 周二 下午

解析时间

屏幕截图 2022-01-04 151314

1
2
3
4
5
6
7
8
9
10
11
public class Test02 {
public static void main(String[] args) throws ParseException {
String s="2021年08月06日 11:11:11";
SimpleDateFormat sdf = new SimpleDateFormat("yyyy年MM月dd日 HH:mm:ss");
Date parse = sdf.parse(s);
long time =parse.getTime()+(2L*24*60*60+14*60*60+49*60+6)*1000;
//运算结果可能很大因此要加L
String format = sdf.format(time);
System.out.println(format);
}
}
1
2021年08月09日 02:00:17

2.12 StringBuilder

1
2
3
4
5
6
7
StringBuilder sb = new StringBuilder();
sb.append(1).append(2).append(5);
sb.reverse();
System.out.println(sb);
String s = sb.toString();
StringBuilder sb1 = new
StringBuilder("abc");//可添加元素

三、Java核心

退出:System.exit(0);

1.修饰符权限

public>default>protected>private

屏幕截图 2022-01-03 161323

2.方法

构造器

  • 方法调用:初始化一个对象,并返回对象的地址

2.1.==静态方法==

实例方法和静态方法(static)

静态方法可以不用new引出

静态方法可以访问静态方法,不能访问非静态

非静态方法可以访问静态

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
1. 静态调用非静态
public class Helloworld {
public void Puppy(String name) {
System.out.println("dog name is : " + name);
}

public static void main(String[] args) {
Helloworld p = new Helloworld();
p.Puppy("dddd");
}
}

2. 静态调用静态
public class Helloworld {
public static void Puppy(String name) {
System.out.println("dog name is : " + name);
}

public static void main(String[] args) {
Puppy("dddd");
}
}
public static int obj=100;
private int age=1;
public static void main(String[] args) {
System.out.println(obj);//前提在一个类中
r1 r = new r1();
System.out.println(r.age);
System.out.println(r.obj);//(不推荐)

2.2.方法重载

1
2
3
4
5
6
public static int sum(int a,int b){
return a+b;
}
public static int sum(int a,int b,int c){
return a+b+c;
}

2.3 可变参数

一个方法只能有一个可变参数

可变参数必须放最后面

可变参数本质上是一个==数组==

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
public class Test03 {
public static void main(String[] args) {
sum();//1.不传参
sum(1,4);//2.传两个
sum(22,21,1,2,3);//3.传5个
sum(new int[]{1,3,4,5});
}
public static void sum(int...nums){
System.out.println(Arrays.toString(nums));
System.out.println(nums.length);
}
}
[]
0
[1,4]
2
[22,21,1,2,3]
5
[1,3,4,5]
4

3.成员变量和局部变量

  • 成员变量:方法外的变量,在堆内存中,随对象消失而消失

  • 局部变量:方法中,在栈中,随方法完毕而消失,==局部变量必须赋值==

    1
    2
    3
    4
    public static void sum(){
    int x;
    System.out.println(x);报错-------------因为X未进行赋值
    }

4.封装

java 封装,说白了就是将一大坨公共通用的实现逻辑玩意,装到一个盒子里(class),出入口都在这个盒子上。你要用就将这个盒子拿来用,连接出入口,就能用了,不用就可以直接扔,对你代码没什么影响。

5.==继承==

  1. 子类可以继承父类的属性和行为,但不能继承构造器

  2. 一个类继承一个父类,==子类继承了父类私有,但不能直接使用==,因为private

  3. 支持多层继承,==子类可以调用父类静态变量与方法==

  4. Object是所有类父类

  5. 就近原则,==先运行子类==

  6. ==子类的给构造方法都会去先访问父类的构造方法==

  7. ==构造方法的第一句默认是super==

  8. ==父类建议写无参构造器==

    测试变量

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    public class r2 {
    public static void main(String[] args) {
    wolf wo = new wolf();
    wo.showname();
    System.out.println(wo.name);
    }
    }
    class Animal{
    public String name="父类动物";
    }
    class wolf extends Animal{
    public String name="子类动物";
    public void showname(){
    String name="局部变量";
    System.out.println(name);
    System.out.println(this.name);
    System.out.println(super.name);
    }
    }
    //最终输出:

    //局部变量
    //子类动物
    //父类动物
    //子类动物

    测试方法

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    public class r3 {
    public static void main(String[] args) {
    newphone HUAWIE = new newphone();
    HUAWIE.call();
    }
    }
    class Phone{
    public void call(){
    System.out.println("打电话");
    }
    }
    class newphone extends Phone{
    @Override
    public void call(){
    super.call();
    System.out.println("智能手机打电话");
    }
    }
    //最终输出:

    //打电话
    //智能手机打电话

6.==多态==

==方法重载是多态的一种(编译时多态)==

==运行时多态:==

  1. 一个对象的编译类型和运行类型可以不一致

  2. 编译类型在定义对象就确定了,不能改变

  3. 运行类型可变

    1
    2
    Animal animal=new Dog();
    animal=new Cat();//编译类型仍是animal
  4. 编译看左边,运行看右边

为什么要多态?

一般来说,伴随着接口和类的继承,多态就会产生。在多态的过程中,我们需要关注其中的一些要点。

首先我们来演示一下类的继承。

父类和子类:

1
2
3
4
5
6
7
8
9
10
public class Zi extends Fu{ 
public void play(){
System.out.println("钓鱼");
}
}
public class Zi extends Fu{
public void play(){
System.out.println("LOL");
}
}

接下来,我们看类的继承中,多态是如何体现的。

假如有一天,儿子穿着父亲的衣服到他老子的单位里去玩耍。如果这个时候,他老子的同事请他去钓鱼,这个是不行的,因为他到底的爱好是LOL,如果强行调用了play方法,就会露馅。

现在,假设他老子有一个吃饭的方法,喜欢吃水煮鱼,这一点,他儿子也是如此,所以,就不需要重写这个方法。

1
2
3
4
5
6
7
8
9
10
public class Fu {

public void eat(){
System.out.println("我正在吃饭,吃水煮鱼!");
}

public void play(){
System.out.println("钓鱼");
}
}

那么,如果他儿子跟他老子的同事一起去吃饭,并且吃了水煮鱼,就不会露馅。

假如下班后,他儿子去网咖玩“吃鸡”,但是衣服还没有来得及换。现在,儿子有吃鸡的方法:

1
2
3
4
5
6
7
8
9
10
public class Zi extends Fu{

public void play(){
System.out.println("LOL");
}

public void eatChicken(){
System.out.println("大吉大利,今晚吃鸡!");
}
}

当他去了网吧,强行调用自己的吃鸡方法。

竟然报错了!!!

因为现在他对外的身份还是父亲,而父亲是没有吃鸡的方法的,所以无法调用了。

于是啊,他一气之下,在网咖里脱衣服,回归自己的原来身份!

1
2
3
4
5
6
7
8
9
10
public class Test04 {

public static void main(String[] args) {

Fu f = new Zi();

((Zi) f).eatChicken(); //强制转换

}
}

总结:

多态就是,子类继承父类后,用父类型new出自己的实例对象。就好比刚才例子中,儿子穿着他老子的衣服去他老子的公司做一些不可描述的事情。那些他老子没有,但是他没有的方法,不能使用,除非强制转换为子类的身份。

1
2
3
4
5
6
7
8
public interface Swimming {

public void goSwimming();
}
public interface Fly {

public void goFlying();
}

让子类去实现游泳接口,表示其已经拥有了游泳的能力,和类的继承不同,如果一个类实现了某一个接口,就必须重写接口内所有的方法。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
public class Zi extends Fu implements Swimming{


public void play(){
System.out.println("LOL");
}

public void eatChicken(){
System.out.println("大吉大利,今晚吃鸡!");
}

@Override
public void goSwimming() {
System.out.println("我已使出洪荒之力来游泳!");
}
}

编写一个飞鸟类,实现这个飞行的接口:

1
2
3
4
5
6
7
8
public class Bird implements Fly{

@Override
public void goFlying() {
System.out.println("I can Fly , can you ?");
}

}

那么,多态的体现就是,我们可以用接口类型去new出所有实现该接口的子类对象。

我们发现,new出来的子类对象除了Object类中方法之外,只能调用接口里的方法,不能调用自己的方法。就连他继承自父类的方法也不能调用!!

看到这里,大家可能会困惑,说这个多态有什么好,多态了之后,自己的方法好多都访问不了了!

韩顺平P309

image-20220917145700004

  • 编译看左边,运行看右边.

  • 变量调用:都看右边

  • public abstract class Animals {
        public String name="父类动物";
        public abstract void run();
    }
    public class r6 {
        public static void main(String[] args) {
            Animals dog= new Dogs();
            dog.run();
            System.out.println(dog.name);
        }
    }
    class Dogs extends Animals{
        public String name="狗子";
        @Override
        public void run() {
            System.out.println("dogs跑");
        }
    }
    
    1
    2
    3
    4

    * ```java
    //dogs跑
    //父类动物
  • ==多态下,不能访问子类独有功能,除非强转,如下==

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    public class r6 {
    public static void main(String[] args) {
    Animals dog= new Dogs();
    dog.run();
    System.out.println(dog.name);
    if (dog instanceof Dogs) {
    Dogs dogs1 = (Dogs) dog;
    dogs1.lookDoor();
    }
    }
    }
    class Dogs extends Animals{
    public String name="狗子";
    @Override
    public void run() {
    System.out.println("dogs跑");
    }
    public void lookDoor(){
    System.out.println("狗在看门");
    }
    }

    instanceof确认其类型

7.==接口==

  • 接口是被类实现的(implements),实现类可以理解为子类
  • 可多实现,一个接口实现类必须重写其接口所有方法否则,就要设为抽象类
  • 前提:存在一个类或接口,可以是具体类也可以是抽象类

####7.1 ==抽象类和接口的区别==

我们从我们实际设计场景中来切入这个话题

先来举一个简单的例子:

狗都具有 eat() 、sleep() 方法,我们分别通过抽象类和接口定义这个抽象概念

1
2
3
4
5
6
7
8
9
10
11
//通过抽象类定义
public abstract class Dog {
public abstract void eat();
public abstract void sleep();
}

//通过接口定义
public interface Dog {
public abstract void eat();
public abstract void sleep();
}

但是我们现在如果需要让狗拥有一项特殊的技能——钻火圈 DrillFireCircle(),如何增加这个行为呢?

思考:

1. 将钻火圈方法与前面两个方法一同写入抽象类中,但是这样的话,但凡继承这个抽象类狗都具有了钻火圈技能,明显不合适
2. 将钻火圈方法与前面两个方法一同写入接口中,当需要使用钻火圈功能的时候,就必须实现 接口中的eat() 、sleep() 方法(重写该接口中所有的方法)显然也不合适

那么该如何解决呢 ? 我们可以仔细想一想,eat和sleep都是狗本身所应该具有的一种行为,而钻火圈这种行为则是后天训练出来的,只能算是对狗类的一种附加或者延伸, 两者不应该在同一个范畴内,所以我们考虑将这个单独的行为,独立的设计一个接口,其中包含DrillFireCircle()方法, Dog设计为一个抽象类, 其中又包括eat() 、sleep() 方法.

一个SpecialDog即可继承Dog类并且实现DrillFireCircle()接口

下面给出代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
//定义接口,含有钻火圈方法
public interface DrillFireCircle() {
public abstract void drillFireCircle();
}

//定义抽象类狗类
public abstract class Dog {
public abstract void eat();
public abstract void sleep();
}

//继承抽象类且实现接口
class SpecialDog extends Dog implements drillFireCircle {
public void eat() {
//....
}
public void sleep() {
//....
}
public void drillFireCircle() () {
//....
}
}

总结:

继承是一个 “是不是”的关系,而 接口 实现则是 “有没有”的关系。如果一个类继承了某个抽象类,则子类必定是抽象类的种类,而接口实现则是有没有、具备不具备的关系,比如狗是否能钻火圈,能则可以实现这个接口,不能就不实现这个接口。

7.2 接口实现多继承

1
2
3
public interface law {
void followlaw();
}
1
2
3
public interface Eats {
void eat();
}
1
2
3
public interface sport extends Eats,law{
void run();
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
public class MakeTrue implements sport{

@Override
public void eat() {
System.out.println("吃早餐");
}

@Override
public void followlaw() {

}

@Override
public void run() {

}
}
1
2
3
4
5
6
public class r7 {
public static void main(String[] args) {
sport sp = new MakeTrue();
sp.eat();
}
}

7.3 接口经典案例

屏幕截图 2022-01-03 222353

1
2
3
public interface SpeakEnglish {
void speak();
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
public abstract class People {
private String name;
private int age;

public People() {
}

public People(String name, int age) {
this.name = name;
this.age = age;
}

public String getName() {
return name;
}

public void setName(String name) {
this.name = name;
}

public int getAge() {
return age;
}

public void setAge(int age) {
this.age = age;
}
public abstract void eat();
}
1
2
3
4
5
6
7
8
9
10
public abstract class jiaolian extends People{
public jiaolian() {
}

public jiaolian(String name, int age) {
super(name, age);
}

public abstract void teach();
}
1
2
3
4
5
6
7
8
9
public abstract class Sportman extends People{
public Sportman() {
}

public Sportman(String name, int age) {
super(name, age);
}
public abstract void study();
}
1
2
3
4
5
6
7
8
9
10
11
12
public class BasketPlayer extends Sportman{

@Override
public void eat() {
System.out.println("篮球运动员吃篮球");
}

@Override
public void study() {
System.out.println("篮球运动员学篮球");
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
public class PPQplayer extends Sportman implements SpeakEnglish{
@Override
public void eat() {
System.out.println("PPQ运动员吃PPQ");
}

@Override
public void study() {
System.out.println("PPQ运动员学PPQ");
}

@Override
public void speak() {
System.out.println("PPQ学员说英语");
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
public class PPQjiaolian extends jiaolian implements SpeakEnglish{
@Override
public void eat() {
System.out.println("ppq教练吃球拍");
}

@Override
public void teach() {
System.out.println("PPQ教练教PPQ");
}

@Override
public void speak() {
System.out.println("PPQ教练说英语");
}
}
1
2
3
4
5
6
7
8
9
10
11
public class basketjiaolian extends jiaolian{
@Override
public void eat() {
System.out.println("篮球教练吃学员");
}

@Override
public void teach() {
System.out.println("篮球教练教篮球");
}
}
1
2
3
4
5
6
7
public class Test {
public static void main(String[] args) {
PPQplayer PPq = new PPQplayer();
PPq.speak();
PPq.eat();
}
}

7.4 接口中的默认方法

当接口中需要添加一个新的方法,其实现类就会报错

解决方法如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
public class D7 {
public static void main(String[] args) {
Showable s = new Maketrue();
s.show1();
s.show2();
s.show3();
}
}
public interface Showable {
void show1();
void show2();
default void show3(){
System.out.println("show3");
};
}

默认方法也可被重写,重写去掉defult关键字

1
2
3
4
5
6
7
8
9
10
11
12
13
14
public class Maketrue implements Showable{
@Override
public void show1() {
System.out.println("show1");
}
@Override
public void show2() {
System.out.println("show2");
}
@Override
public void show3() {
System.out.println("show3");
}
}

7.5 接口中静态方法

startic方法和类的加载是一起的,优先于对象产生,可以通过类名调用,同理接口应该也一样

不能通过对象产生,通过类名.方法名产生

因为可能会混淆,实现类实现两个接口,如果接口名字有重复则无法判断

1
2
3
4
5
public interface Showable {
static void show4(){
System.out.println("静态方法实现了");
}
}
1
2
3
4
5
6
public class D7 {
public static void main(String[] args) {
Showable s = new Maketrue();
Showable.show4();
}
}

7.6 接口中私有方法

方便实现封装简化代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
public interface Showab {
default void show1(){
System.out.println("show1方法调用了");
// System.out.println("初级工程师");
// System.out.println("中级工程师");
// System.out.println("高级工程师");
method();
System.out.println("show1方法结束了");
}
default void show2(){
System.out.println("show2方法调用了");
// System.out.println("初级工程师");
// System.out.println("中级工程师");
// System.out.println("高级工程师");
method();
System.out.println("show2方法结束了");
}
private void show() {
System.out.println("初级工程师");
System.out.println("中级工程师");
System.out.println("高级工程师");
}//适用于1,2
static void method1(){
System.out.println("method1方法调用了");
// System.out.println("初级工程师");
// System.out.println("中级工程师");
// System.out.println("高级工程师");
method();
System.out.println("method1方法结束了");
}
static void method2(){
System.out.println("method2方法调用了");
System.out.println("初级工程师");
System.out.println("中级工程师");
System.out.println("高级工程师");
method();
System.out.println("method2方法结束了");
}
private static void method(){
System.out.println("初级工程师");
System.out.println("中级工程师");
System.out.println("高级工程师");
}
}
1
2
public class True implements Showab{
}
1
2
3
4
5
6
7
8
9
10
11
12
public class Test01 {
public static void main(String[] args) {
Showab showab = new True();
showab.show1();
System.out.println("----------");
showab.show2();
System.out.println("----------");
Showab.method1();
System.out.println("----------");
Showab.method2();
}
}

7.7 继承和接口的区别

实际概念区别:

  1. 在面向对象编程中可以有多继承!但是只支持接口的多继承,不支持’继承’的多继承而继承在java中具有单根性,子类只能继承一个父类
  2. 在接口中只能定义全局常量,和抽象方法而在继承中可以定义属性方法,变量,常量等…
  3. 某个接口被类实现时,在类中一定要实现接口中的抽象方法,而继承想调用那个方法就调用那个方法,毫无压力

接口是:对功能的描述 继承是:什么是一种什么

始终记者:你可以有多个干爹(接口),但只能有一个亲爹( 继承)

==举例:==

  如果狗的主人只是希望狗能爬比较低的树,但是不希望它继承尾巴可以倒挂在树上,像猴子那样可以飞檐走壁,以免主人管不住它。

那么狗的主人肯定不会要一只猴子继承的狗。

  设计模式更多的强调面向接口。猴子有两个接口,一个是爬树,一个是尾巴倒挂。我现在只需要我的狗爬树,但是不要它尾巴倒挂,那么我只要我的狗实现爬树的接口就行了。同时不会带来像继承猴子来带来的尾巴倒挂的副作用。这就是接口的好处。

四、内部类

内部类可以用protected,private修饰

1. 局部内部类

鸡肋语法

2. 成员内部类

  • 可以直接访问外部类静态成员,实例方法中可以直接访问外部类实例成员
  • 无static 属于外部类对象
  • 外部类.内部类名 对象名=new 外部类构造器.new内部类构造器();
  • 相当于汽车对象里的发动机对象
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
public class Outer {
public static int a=100;
private String hobby;
public Outer(String hobby) {
this.hobby = hobby;
}
public class Inner{
private String name;
private int age ;
public Inner() {
}
public Inner(String name, int age) {
this.name = name;
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public void show(){
System.out.println("内部类使用");
System.out.println(100);
System.out.println(hobby);
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
}
}
1
2
3
4
5
6
public class Test01 {
public static void main(String[] args) {
Outer.Inner inner = new Outer("111").new Inner();
inner.show();
}
}

屏幕截图 2022-01-04 104351

案例如下

1
2
3
heartbeat
this.heartbeat
People.this.heartbeat

3. 静态成员内部类

  • 相对于两个独立的类合并在一起(不适合真实场景)
  • 使用与普通类一样
  • 可以直接访问外部类静态成员,布恩那个访问外部类实例成员
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
public class Outer {
public static int a=100;
private String hobby ="A";
//在内部类中不能直接被使用,要创建对象,hobby属于外部对象
public static class Inner{
private String name;
private int age ;
public Inner() {
}
public Inner(String name, int age) {
this.name = name;
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public void show(){
System.out.println("内部类使用");
System.out.println(100);
System.out.println(new Outer().hobby);
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
}
}
1
2
3
4
5
6
7
8
9
public class Test01 {
public static void main(String[] args) {
Outer.Inner oi=new Outer.Inner();
oi.show();
oi.setAge(19);
}
}
//内部类使用
//100

4. ==匿名内部类==

修改前:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
public class Test01 {
public static void main(String[] args) {
Animal animal = new Tiger();
animal.run();
}
}
abstract class Animal{
public abstract void run();
}
class Tiger extends Animal{
@Override
public void run() {
System.out.println("老虎跑");
}
}

修改后:

1
2
3
4
5
6
7
8
9
10
11
12
13
public class Test01 {
public static void main(String[] args) {
Animal animal = new Animal(){
@Override
public void run() {
System.out.println("老虎跑的快");
}
};
}
}
abstract class Animal{
public abstract void run();
}

屏幕截图 2022-01-04 110936

可与理解为重写

屏幕截图 2022-01-04 111313

五、其他知识

1. 正则表达式

==API文档pattern==

matches() 方法用于检测字符串是否匹配给定的正则表达式。
调用此方法的 str.matches(regex) 形式与以下表达式产生的结果完全相同:
Pattern.matches(regex, str)
语法
public boolean matches(String regex)
参数
regex – 匹配字符串的正则表达式。
返回值
在字符串匹配给定的正则表达式时,返回 true。

屏幕截图 2022-01-04 220804

2. 枚举

屏幕截图 2022-01-16 215036

屏幕截图 2022-01-16 215149

屏幕截图 2022-01-16 214613

3. 泛型

3.1 (自定义泛型类)原理:

屏幕截图 2022-01-05 154747

3.2 泛型方法

屏幕截图 2022-01-05 160049

3.3 自定义泛型接口

泛型接口可以约束实现类,实现类可以在实现接口时,传入自己的数据类型,这样重写的方法是针对该类型的操作

6

3.4 类型通配符

案例:

Benz集合相当于男厕,Bmw集合相当于女厕,Car集合,彼此毫无关系,虽然有继承关系,因为是集合与集合,集合没有继承

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
public class Test02 {
public static void main(String[] args) {
ArrayList<Benz> benzs = new ArrayList<>();
benzs.add(new Benz());
benzs.add(new Benz());
benzs.add(new Benz());
benzs.add(new Benz());
go(benzs);//报错---------------------------------------------

ArrayList<BMW> bmws = new ArrayList<>();
bmws.add(new BMW());
bmws.add(new BMW());
bmws.add(new BMW());
bmws.add(new BMW());
go(bmws);//报错-----------------------------------------------
}
public static void go(ArrayList<Car> cars){}
}
class Car{}
class BMW extends Car{}
class Benz extends Car{}

正确如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
public class Test02 {
public static void main(String[] args) {
ArrayList<Benz> benzs = new ArrayList<>();
benzs.add(new Benz());
benzs.add(new Benz());
benzs.add(new Benz());
benzs.add(new Benz());
go(benzs);

ArrayList<BMW> bmws = new ArrayList<>();
bmws.add(new BMW());
bmws.add(new BMW());
bmws.add(new BMW());
bmws.add(new BMW());
go(bmws);

ArrayList<Dog> dogs = new ArrayList<>();
dogs.add(new Dog());
go(dogs);//-----------------------------------报错
}
public static void go(ArrayList<? extends Car> cars){}
}
class Car{}
class BMW extends Car{}
class Benz extends Car{}
class Dog{}

==上限==,? extends Car,Car必须是其子类,泛型上限

==下限==,?extends Car,Car必须是其父类,泛型下限

4. 包装类

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
public static void main(String[] args) throws ParseException {
Integer a=100;
Integer b=a;
//自动装箱
int i=b;
//自动拆箱
String d="99.9";
String s = a.toString();
String c = Integer.toString(a);
//转字符串
int i1 = Integer.parseInt(s);
//转数字
double v = Double.parseDouble(d);
//转double
int f=Integer.valueOf(s);
double g=Double.valueOf(d)
}

包装类的默认值是null,容错率更高

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
public static void main(String[] args) throws ParseException {
Integer a=100;
Integer b=a;
//自动装箱
int i=b;
//自动拆箱
String d="99.9";
String s = a.toString();
String c = Integer.toString(a);
//转字符串
int i1 = Integer.parseInt(s);
//转数字
double v = Double.parseDouble(d);
//转double
}

5. 异常

5.1 异常简介

黑马143

屏幕截图 2022-01-07 172350

屏幕截图 2022-01-07 174410

屏幕截图 2022-01-07 175125

5.2 异常处理

屏幕截图 2022-01-07 202004

5.2.1.throws抛出

屏幕截图 2022-01-07 202321

5.2.2.try catch

==建议Exception==

屏幕截图 2022-01-07 205330

5.2.3.两者相结合

能够知道底层情况

屏幕截图 2022-01-07 210433

5.3 运行时异常

也建议处理,能够继续运行

屏幕截图 2022-01-07 210719

5.4 异常案例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
public class Q2 {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
while (true) try {
{
System.out.println("请输入合法的价格: ");
String s = sc.nextLine();
double price=Double.valueOf(s);
if (price>0){
System.out.println("价格是: "+price);
}else {
System.out.println("您输入的价格不合法!!!");
}
}
} catch (Exception e) {
System.out.println("您输入的价格有毛病!!!!!!!!!!!");
}
}
}

5.6.自定义异常

屏幕截图 2022-01-07 212603

5.6.1 编译时异常
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
public class Q3 {
public static void main(String[] args) {
try {
checkAge(10000);
} catch (Exception e) {
e.printStackTrace();
}
}
public static void checkAge(int age) throws shuaigeLuhaoException {
if (age<0||age>2000){
//抛出一个异常对象给调用者
throw new shuaigeLuhaoException("卢浩帅到程序出错!!!!!");
}else {
System.out.println("年龄合法");
}
}
}
1
2
3
4
5
6
7
8
public class shuaigeLuhaoException extends Exception{
public shuaigeLuhaoException() {
}

public shuaigeLuhaoException(String message) {
super(message);
}
}
1
2
3
heimaSe.Review.R8.shuaigeLuhaoException: 卢浩帅到程序出错!!!!!
at heimaSe.Review.R8.Q3.checkAge(Q3.java:14)
at heimaSe.Review.R8.Q3.main(Q3.java:6)
5.6.2 运行时异常
1
2
3
4
5
6
7
8
9
10
11
12
13
public class Q3 {
public static void main(String[] args) {
checkAge(10000);
}
public static void checkAge(int age) throws shuaigeLuhaoException {
if (age<0||age>2000){
//抛出一个异常对象给调用者
throw new shuaigeLuhaoException();//可以加内容
}else {
System.out.println("年龄合法");
}
}
}

5.7 throw和throws区别

throw:就是自己处理一个异常,有两种方式要么是自己捕获异常try…catch代码块,要么是抛出一个异常(throws 异常)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
public class TestThrow{
public static void main(String[] args)
{
try
{
//调用带throws声明的方法,必须显式捕获该异常
//否则,必须在main方法中再次声明抛出
throwChecked(-3);
}
catch (Exception e)
{
System.out.println(e.getMessage());
}
//调用抛出Runtime异常的方法既可以显式捕获该异常,
//也可不理会该异常
throwRuntime(3);
}
public static void throwChecked(int a)throws Exception{
if (a > 0)
{
//自行抛出Exception异常
//该代码必须处于try块里,或处于带throws声明的方法中
throw new Exception("a的值大于0,不符合要求");
}
}
public static void throwRuntime(int a)
{
if (a > 0)
{
//自行抛出RuntimeException异常,既可以显式捕获该异常
//也可完全不理会该异常,把该异常交给该方法调用者处理
throw new RuntimeException("a的值大于0,不符合要求");
}
}
}

六、线程

并发与并行

并发:Cpu分时执行(抢占)

并行:同一时刻同时进行

1. 生命周期

Thread.state();

线程的六种状态:

  1. 新建状态
  2. 就绪状态
  3. 阻塞状态
  4. 等待状态
  5. 即使状态
  6. 结束状态

2. 多线程常用方法

1.得到名字:Thread.currenThread().getName()

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
public class Test04 {
public static void main(String[] args) {
//主线程
Thread th = new Thread(new Runnable() {
@Override
public void run() {
for (int j = 0; j < 5; j++) {
System.out.println(Thread.currentThread().getName()+j);
}
}
});
th.start();
System.out.println(Thread.currentThread());
for (int i = 0; i < 5; i++) {
System.out.println("主线程启动"+i);
}
}
}
class MyRunnable implements Runnable{
@Override
public void run() {
for (int j = 0; j < 5; j++) {
System.out.println("子线程启动:"+j);
}
}
}

2.若在public类中可用 this.getName()

1
2
3
4
5
6
public class Mythread extends Thread {
@Override
public void run() {
System.out.println(this.getName());
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
public class Test06 {
public static void main(String[] args) {
Thread th = new Mythread("1");
System.out.println(Thread.currentThread());

Thread T1 = Thread.currentThread();
for (int i = 0; i < 5; i++) {
System.out.println(T1.getName()+i);
}
}
}
public class Mythread extends Thread {
public Mythread() {
}

public Mythread(String name) {
super(name);
}

@Override
public void run() {
System.out.println(this.getName());
}
}

4.Runnable取名字

1
2
3
4
5
6
7
8
9
        Thread th = new Thread(new Runnable() {
@Override
public void run() {
for (int j = 0; j < 5; j++) {
System.out.println(Thread.currentThread().getName()+j);
}
}
},"1");
new Thread(new runnable,"名字");

5.休眠

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
public class Test06 {
public static void main(String[] args) throws InterruptedException {
Thread th = new Mythread("1");
System.out.println(Thread.currentThread());

Thread T1 = Thread.currentThread();
for (int i = 0; i < 5; i++) {
System.out.println(T1.getName()+i);
if (i==3){
Thread.sleep(3000);
//休眠
}
}
}
}

==进程==:正在运行的应用程序

实现多条执行路径的技术

屏幕截图 2022-01-06 104156

2.1 方式一实现多线程

缺点:线程类已经继承Thread,不能继承其他类,不利于扩展

主线程子线程同时运行,随即输出

==th.run==,普通调用

th.start()线程调用

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
public class Test04 {
public static void main(String[] args) {
//主线程
Mythread th = new Mythread();
th.start();
for (int i = 0; i < 5; i++) {
System.out.println("主线程启动"+i);
}
}
}
class Mythread extends Thread{
@Override
public void run() {
for (int j = 0; j < 5; j++) {
System.out.println("子线程启动:"+j);
}
}
}
1
2
3
4
5
6
7
8
9
10
子线程启动:0
主线程启动0
子线程启动:1
主线程启动1
子线程启动:2
主线程启动2
子线程启动:3
主线程启动3
子线程启动:4
主线程启动4

==不能把主线程放子线程之前==,程序会认为是单线程,优先走完主线程

2.2 方式二(Runable接口)

屏幕截图 2022-01-06 094000

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
public class Test04 {
public static void main(String[] args) {
//主线程
Runnable my = new MyRunnable();
Thread th = new Thread(my);
th.start();
for (int i = 0; i < 5; i++) {
System.out.println("主线程启动"+i);
}
}
}
class MyRunnable implements Runnable{
@Override
public void run() {
for (int j = 0; j < 5; j++) {
System.out.println("子线程启动:"+j);
}
}
}

扩展性好,多实现借口,空出继承

2.3 方式二升级版(内部类)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
public class Test04 {
public static void main(String[] args) {
//主线程
Runnable my = new Runnable() {
@Override
public void run() {
for (int j = 0; j < 5; j++) {
System.out.println("子线程启动:"+j);
}
}
};
Thread th = new Thread(my);
th.start();
for (int i = 0; i < 5; i++) {
System.out.println("主线程启动"+i);
}
}
}

2.4 方式二超级升级版

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
public class Test04 {
public static void main(String[] args) {
//主线程
Thread th = new Thread(new Runnable() {
@Override
public void run() {
for (int j = 0; j < 5; j++) {
System.out.println("子线程启动:"+j);
}
}
});
th.start();
for (int i = 0; i < 5; i++) {
System.out.println("主线程启动"+i);
}
}
}

2.5 方式三实现多线程

前两种只能跑功能,无法返回值

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
public class Test05 {
public static void main(String[] args) throws ExecutionException, InterruptedException {
Callable<String> my = new Mycallable(10);
FutureTask<String> sft = new FutureTask<String>(my);
//Future是Runnable对象,交给Thread(过渡)
Thread th = new Thread(sft);
th.start();
String s = sft.get();
//如果sft 未执行完毕,这里会等待
System.out.println(s);
}
}
class Mycallable implements Callable<String>{
private int n;
public Mycallable(int n) {
this.n = n;
}
@Override
public String call() throws Exception {
int sum=0;
for (int i = 0; i <=n; i++) {
sum+=i;
}
return "结果是" +sum;
}
}

3. 线程安全

屏幕截图 2022-01-06 110337

1
2
3
4
5
6
7
8
9
10
11
public class DrawThread extends Thread{
private Account ac;
public DrawThread(Account ac, String name) {
super(name);
this.ac=ac;
}
@Override
public void run() {
ac.Drawmoney(100000);
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
public class Account {
private String IDc;
private int money;
public Account(String iDc) {
IDc = iDc;
}
public Account(String iDc, int money) {
IDc = iDc;
this.money = money;
}
public void Drawmoney(int money) {
String name=Thread.currentThread().getName();
synchronized ("") {
//""代表一个常量,表示小明或小红
if (this.money>=money){
System.out.println(name+"取走"+money);
this.money-=money;
System.out.println(name+"取后剩余"+this.money);
}else {
System.out.println("余额不足");
}
}
}
public int getMoney() {
return money;
}
public void setMoney(int money) {
this.money = money;
}
public String getIDc() {
return IDc;
}
public void setIDc(String IDc) {
this.IDc = IDc;
}
}
1
2
3
4
5
6
7
public class Test01 {
public static void main(String[] args) {
Account ac = new Account(100000);
new DrawThread(ac,"小红").start();
new DrawThread(ac,"小明").start();
}
}
1
2
3
4
小红取走100000
小明取走100000
小红取后剩余0
小明取后剩余-100000

线程同步

3.1 法一(锁代码块)

实例方法:

ctrl +alt +T

1
2
3
4
5
6
7
8
9
10
synchronized ("") {
//""代表一个常量,表示小明或小红
if (this.money>=money){
System.out.println(name+"取走"+money);
this.money-=money;
System.out.println(name+"取后剩余"+this.money);
}else {
System.out.println("余额不足");
}
}

synchronized不好,会影响其他线程执行

小明小红一家人只有一个能取钱

但是其他人的账户不能同时取钱

如下:

1
2
3
4
5
6
7
8
9
10
public class Test01 {
public static void main(String[] args) {
Account ac = new Account("ID1", 100000);
new DrawThread(ac,"小红").start();
new DrawThread(ac,"小明").start();
Account acc = new Account("ID2", 100000);
new DrawThread(acc,"小黑").start();
new DrawThread(acc,"小白").start();
}
}
1
2
3
4
5
6
小红取走100000
小红取后剩余0
小明取走100000
小明取后剩余0
余额不足
余额不足
1
2
3
4
5
6
7
8
9
10
11
12
13
public void Drawmoney(int money) {
String name=Thread.currentThread().getName();
synchronized (this) {
//""代表一个常量,表示小明或小红
if (this.money>=money){
System.out.println(name+"取走"+money);
this.money-=money;
System.out.println(name+"取后剩余"+this.money);
}else {
System.out.println("余额不足");
}
}
}

==this=acc==,前提:面向对象设计

1
2
3
4
5
6
小白取走100000
小红取走100000
小白取后剩余0
小红取后剩余0
余额不足,还剩0
余额不足,还剩0

静态方法建议使用==类名.class==作为锁对象,因为类是唯一的,静态方法针对所有线程

3.2 法二(锁方法)

实例方法默认锁this

静态方法默认:类名.class

1
2
3
4
5
6
7
8
9
10
11
public synchronized void Drawmoney(int money) {
String name=Thread.currentThread().getName();
//""代表一个常量,表示小明或小红
if (this.money>=money){
System.out.println(name+"取走"+money);
this.money-=money;
System.out.println(name+"取后剩余"+this.money);
}else {
System.out.println("余额不足,还剩"+this.money);
}
}

3.3 法一二对比

同步方法使用更多,更方便,但同步代码块性能更高(提前进入方法)

3.4 法三Lock锁

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
public class Account {
private String IDc;
private int money;
private final Lock lock=new ReentrantLock();
//用final修饰跟专业安全
public Account(String iDc) {
IDc = iDc;
}
public Account(String iDc, int money) {
IDc = iDc;
this.money = money;
}
public void Drawmoney(int money) {
String name=Thread.currentThread().getName();
//""代表一个常量,表示小明或小红
lock.lock();
try {
if (this.money>=money){
System.out.println(name+"取走"+money);
this.money-=money;
System.out.println(name+"取后剩余"+this.money);
}else {
System.out.println("余额不足,还剩"+this.money);
}
} catch (Exception e) {
e.printStackTrace();
} finally {
lock.unlock();
//中间出先异常也能解锁
}
}
}

3.5 线程安全的类

屏幕截图 2022-09-19 161847

4. 定时器

4.1 TIMER及其缺陷

定时器本身就是一个单线程

1
2
3
4
5
6
7
8
9
10
11
public class D1 {
public static void main(String[] args) {
Timer ti = new Timer();
ti.schedule(new TimerTask() {
@Override
public void run() {
System.out.println("调动一次");
}
},3000,2000);//延迟3秒运行,之后每隔2秒运行一次
}
}

问题:

屏幕截图 2022-01-06 182803

1B要等待A

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
public class D1 {
public static void main(String[] args) {
Timer ti = new Timer();
ti.schedule(new TimerTask() {
@Override
public void run() {
System.out.println("调动A次"+new Date());
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
},0,2000);
ti.schedule(new TimerTask() {
@Override
public void run() {
System.out.println("调动B次"+new Date());
}
},0,5000);

}
}
1
2
3
4
5
6
调动A次Thu Jan 06 18:31:28 CST 2022
调动B次Thu Jan 06 18:31:33 CST 2022
调动A次Thu Jan 06 18:31:33 CST 2022
调动A次Thu Jan 06 18:31:38 CST 2022
调动B次Thu Jan 06 18:31:43 CST 2022
调动A次Thu Jan 06 18:31:43 CST 2022

2 死机

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
public class D1 {
public static void main(String[] args) {
Timer ti = new Timer();
ti.schedule(new TimerTask() {
@Override
public void run() {
System.out.println("调动A次");
}
},0,2000);
ti.schedule(new TimerTask() {
@Override
public void run() {
System.out.println("调动B次");
System.out.println(10/0);
}
},0,5000);

}
}
调动A次
调动B次
Exception in thread "Timer-0" java.lang.ArithmeticException: / by zero
at heimaSe.Review.R5.D1$2.run(D1.java:19)
at java.base/java.util.TimerThread.mainLoop(Timer.java:556)
at java.base/java.util.TimerThread.run(Timer.java:506)

Process finished with exit code 0

4.2 Timer升级解决方法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
public class D2 {
public static void main(String[] args) {
ScheduledExecutorService scs = Executors.newScheduledThreadPool(3);
scs.scheduleAtFixedRate(new TimerTask() {
@Override
public void run() {
System.out.println(Thread.currentThread().getName()+"AAA"+new Date());
try {
Thread.sleep(10000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
},0,2,TimeUnit.SECONDS);
scs.scheduleAtFixedRate(new TimerTask() {
@Override
public void run() {
System.out.println(Thread.currentThread().getName()+"BBB"+new Date());
System.out.println(100/0);
}
},0,2,TimeUnit.SECONDS);
scs.scheduleAtFixedRate(new TimerTask() {
@Override
public void run() {
System.out.println(Thread.currentThread().getName()+"CCC"+new Date());
}
},0,2,TimeUnit.SECONDS);
}
}
pool-1-thread-2BBBThu Jan 06 20:39:05 CST 2022
pool-1-thread-3CCCThu Jan 06 20:39:05 CST 2022
pool-1-thread-1AAAThu Jan 06 20:39:05 CST 2022
pool-1-thread-3CCCThu Jan 06 20:39:07 CST 2022
pool-1-thread-3CCCThu Jan 06 20:39:09 CST 2022
pool-1-thread-3CCCThu Jan 06 20:39:11 CST 2022
pool-1-thread-3CCCThu Jan 06 20:39:13 CST 2022
pool-1-thread-3CCCThu Jan 06 20:39:15 CST 2022
pool-1-thread-1AAAThu Jan 06 20:39:15 CST 2022
pool-1-thread-3CCCThu Jan 06 20:39:17 CST 2022

5. 线程池

原理:

不需要突然创建很多线程处理问题

轮流处理

屏幕截图 2022-01-06 152549

5.1 创建线程池方式一

1:正式工3 2:临时工+正式工10 3:临时工干几天 5:忙时客户排队5个等待 6:招人的 7:10个忙,5个等 又来了 怎么处理

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
public class Pool {
public static void main(String[] args) {
ThreadPoolExecutor tpe = new ThreadPoolExecutor(3, 5, 6, TimeUnit.SECONDS
, new ArrayBlockingQueue<>(5),
new ThreadPoolExecutor.AbortPolicy());
Runnable my = new Myrunnable();
//丢给线程池处理
tpe.execute(my);
tpe.execute(my);
tpe.execute(my);
//不懂用队列此时
tpe.execute(my);
tpe.execute(my);
tpe.execute(my);
tpe.execute(my);
tpe.execute(my);

tpe.execute(my);//此时动用临时队列

tpe.execute(my);//还有一个人排队(下面无代码)
tpe.shutdownNow();
//暴力关闭线程池,会造成数据损失
tpe.shutdown();
//等线程池里的任务运行完再关闭
// tpe.execute(my);
// tpe.execute(my);
// tpe.execute(my);
// tpe.execute(my);//报错,太忙被拒绝
}
}

屏幕截图 2022-01-06 164530

4:老板上阵

屏幕截图 2022-01-06 164719

处理线程池

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
public class Test01 {
public static void main(String[] args) throws ExecutionException, InterruptedException {
ThreadPoolExecutor tpe = new ThreadPoolExecutor(3, 5, 6, TimeUnit.SECONDS
, new ArrayBlockingQueue<>(5),
new ThreadPoolExecutor.AbortPolicy());
Future<String> sb = tpe.submit(new Mycall(10));
Future<String> sb1 = tpe.submit(new Mycall(11));
Future<String> sb2 = tpe.submit(new Mycall(12));
String s = sb.get();
String s1 = sb1.get();
String s2 = sb2.get();
System.out.println(s);
System.out.println(s1);
System.out.println(s2);
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
public class Mycall implements Callable {
private int n;
public Mycall(int n) {
this.n = n;
}
@Override
public String call() throws Exception {
int sum=0;
for (int i = 0; i <=n; i++) {
sum+=i;
}
return Thread.currentThread().getName()+"结果是" +sum;
}
}
1
2
3
pool-1-thread-1结果是55
pool-1-thread-2结果是66
pool-1-thread-3结果是78

5.2 线程池创建方式二

屏幕截图 2022-01-06 174222

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
public class Test02 {
public static void main(String[] args) {
ExecutorService es = Executors.newFixedThreadPool(3);
//3个线程
es.execute(new Myrunnable());
es.execute(new Myrunnable());
es.execute(new Myrunnable());
es.execute(new Myrunnable());//没有多余线程了,不进行
}
}
public class Myrunnable implements Runnable{
@Override
public void run() {
for (int i = 0; i < 5; i++) {
System.out.println(Thread.currentThread().getName()+" helloworld "+i);
}
try {
System.out.println(Thread.currentThread().getName()+"进入休眠");
Thread.sleep(10000000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}

屏幕截图 2022-01-06 175339

屏幕截图 2022-01-06 180925

6. 线程通信

6.1 案例1送牛奶

屏幕截图 2022-01-06 141200

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
public class Box {
private int milk;
private boolean flag=false;
//表示牛奶状态,true有牛奶
public synchronized void getMilk() {
if (!flag){
//如果没奶,等待生产
try {
wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
flag=false;
System.out.println("取出第"+this.milk+"瓶奶取出");
notifyAll();
//唤醒其他等待线程
}

public synchronized void putMilk(int milk) {
if (flag){
//如果有牛奶就等待,没有就生产牛奶
try {
wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
this.milk = milk;
System.out.println("送奶工将第"+this.milk+"瓶奶送入奶箱");
flag=true;
//生产完毕,修改奶箱状态
notifyAll();
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
public class Producer implements Runnable{
private Box box;
public Producer(Box box) {
this.box=box;
}

@Override
public void run() {
for (int i = 1; i <=5; i++) {
box.putMilk(i);
}
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
public class Costumer implements Runnable{
private Box box;

public Costumer(Box box) {
this.box=box;
}

@Override
public void run() {
while (true){
box.getMilk();
}
}
}
1
2
3
4
5
6
7
8
9
10
11
public class Test {
public static void main(String[] args) {
Box box = new Box();
Producer pro = new Producer(box);
Costumer cos = new Costumer(box);
Thread t1 = new Thread(pro);
Thread t2 = new Thread(cos);
t1.start();
t2.start();
}
}
1
2
3
4
5
6
7
8
9
10
送奶工将第1瓶奶送入奶箱
取出第1瓶奶取出
送奶工将第2瓶奶送入奶箱
取出第2瓶奶取出
送奶工将第3瓶奶送入奶箱
取出第3瓶奶取出
送奶工将第4瓶奶送入奶箱
取出第4瓶奶取出
送奶工将第5瓶奶送入奶箱
取出第5瓶奶取出

6.2 案例2打电话

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
public class Phone {
private boolean flag=false;
//表示当前手机状态,处于等待状态
public void run(){
new Thread(new Runnable() {
@Override
public void run() {
try {
while (true){
synchronized (Phone.this) {
//如果用this指向runnable匿名内部类
//实例同步必须指向实例对象
if (!flag) {
//来电提醒
System.out.println("新电话呼入");
flag=true;
Phone.this.notify();
Phone.this.wait(50000);
}
}
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}).start();//提醒来电
new Thread(new Runnable() {
@Override
public void run() {
try {
while (true){
//不断接电话,每一次接电话都要用锁
synchronized (Phone.this){
if (flag){
System.out.println("接电话,通话5分钟");
Thread.sleep(5000);
flag=false;//改变状态等待
Phone.this.notify();
//要把别人唤醒
Phone.this.wait();
//wait等方法对当前同步锁对象使用
}else{
Phone.this.notify();
Phone.this.wait(500000);
}
}
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}).start();//正式接电话
}//开机
// 可以将phone类提出去,变成两个类一个测试类,一个手机开机类(功能类)
public static void main(String[] args) {
Phone ph = new Phone();
ph.run();
}
}

七、Lambda表达式

==省略规则==

  1. 一个参数省略括号
  2. 可省略类型
  3. 当语句只有一条可以省略括号和分号
  4. 有return时满足3时可省略return;

范例

1
2
3
4
5
6
7
8
9
10
11
12
13
public class D3 {
public static void main(String[] args) {
new Thread(new Runnable() {
@Override
public void run() {
System.out.println("luhao666");
}
}).start();
new Thread(() -> {
System.out.println("多线程程序启动");
}).start();
}
}

==前提==

有一个接口,有且只有一个抽象方法

1. 无参无返回值

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
public class D4 {
public static void main(String[] args) {
//1.多态形式
Eatable ee = new Eattrue();
ee.eat();
//2.内部类形式
useEat(new Eatable() {
@Override
public void eat() {
System.out.println("吃饭");
}
});
//3.Lambda表达式
useEat(()->{
System.out.println("吃饭");
});
}
public static void useEat(Eatable e){
e.eat();
}
}
1
2
3
public interface Eatable {
void eat();
}
1
2
3
4
5
6
public class Eattrue implements Eatable{
@Override
public void eat() {
System.out.println("吃饭");
}
}

2. 带参无返回值

方法引用

==这里的s类型是由接口中方法的String推导出来的==

他把传入的==老虎飞==丢给了 println() 相当于是println(“老虎飞”)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
public class D5 {
public static void main(String[] args) {
//1.匿名内部类
useFly(new Flyable() {
@Override
public void fly(String s) {
System.out.println(s);
}
});
useFly(s -> {
System.out.println(s);
});
useFly(System.out::println);
}
public static void useFly(Flyable f){
f.fly("老虎飞");
}
}
1
2
3
public interface Flyable {
void fly(String s);
}

3. 带参带返回值

1
2
3
4
5
6
7
8
9
10
11
12
public class D6 {
public static void main(String[] args) {
useadd((x,y)->{
return x+y;
});
useadd((x,y)-> x+y);
}
public static int useadd(Addable a){
int sum = a.add(10, 20);
return sum;
}
}
1
2
3
public interface Addable {
int add(int x,int y);
}

4. Lambda和匿名内部类的区别

屏幕截图 2022-01-06 221808

5. 引用类方法

==soutc==

屏幕截图 2022-01-07 101441

1
2
3
4
5
6
7
8
9
10
11
12
13
public class Test02 {
public static void main(String[] args) {
useConve(s -> {
return Integer.parseInt(s);
});
useConve(s -> Integer.parseInt(s));
useConve(Integer::parseInt);
}
private static void useConve(Convertable c){
int num=c.conver("666");
System.out.println(num);
}
}

Lambda被类方法替代时,它的形式参数全部传递给静态方法作参数

6. 引用对象的实例方法

屏幕截图 2022-01-07 104002

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
public class Test03 {
public static void main(String[] args) {
coUp co = new coUp();
useto(s -> co.printUpp(s));
useto(co::printUpp);
}
private static void useto(printUpper p){
p.toUpp("aaa");
}
}
public interface printUpper {
void toUpp(String s);
}
public class coUp {
public void printUpp(String s){
String s1 = s.toUpperCase();
System.out.println(s1);
}
}

7. 引用类的实例方法

屏幕截图 2022-01-07 110838

1
2
3
4
5
6
7
8
9
10
11
12
13
public class Test04 {
public static void main(String[] args) {
useMy((s,x,y)->{
return s.substring(x,y);
});
useMy((s,x,y)->s.substring(x,y));
useMy(String::substring);
}
public static void useMy(MtsubString m){
String hw = m.sb("helloWorld", 2, 5);
System.out.println(hw);
}
}
1
2
3
public interface MtsubString {
String sb(String s,int x,int y);
}

引用构造器

1
2
3
4
5
6
7
8
9
10
11
12
13
public class Test05 {
public static void main(String[] args) {
usestb((name,age)->{
return new Student(name,age);
});
usestb((name,age)->new Student(name,age));
usestb(Student::new);
}
public static void usestb(useSt u){
Student lh = u.stbuild("luhao", 19);
System.out.println(lh.getName()+lh.getAge());
}
}
1
2
3
public interface useSt {
Student stbuild(String name,int age);
}

8. 函数式接口

首先是接口,==只有一个抽象表达式==

是lambda表达式的使用前提

用@FunctionalInterface确认是否是函数式接口(建议加上,不加也是函数式接口)

1
2
3
4
5
6
7
8
9
10
@FunctionalInterface
public interface MyInterfacce {
void show();
}
public class T1 {
public static void main(String[] args) {
MyInterfacce m=()->System.out.println("函数式接口");
m.show();
}
}

8.1 函数式接口作形参

屏幕截图 2022-01-07 113344

8.2 函数式接口作返回值

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
public class T2 {
public static void main(String[] args) {
ArrayList<String> arr = new ArrayList<>();
arr.add("cccc");
arr.add("aaaaa");
arr.add("bb");
System.out.println(arr);
Collections.sort(arr);
System.out.println(arr);
Collections.sort(arr,useCom());
System.out.println(arr);
}
public static Comparator<String> useCom(){
// return new Comparator<String>() {
// @Override
// public int compare(String o1, String o2) {
// return o1.length()-o2.length();
// }
// };
return ((o1, o2) -> o1.length()-o2.length());
}
}
1
2
3
[cccc, aaaaa, bb]
[aaaaa, bb, cccc]
[bb, cccc, aaaaa]

8.3 常用函数式接口Supplier

get()得到值

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
public class T3 {
public static void main(String[] args) {
int[] arr={1,33,42,11,65};
Integer Max = getMax(() -> {
int max = arr[0];
for (int i = 0; i < arr.length; i++) {
if (arr[i] > arr[max]) {
max = i;
}
}
return arr[max];
});
System.out.println(Max);
}
public static Integer getMax(Supplier<Integer> s){
return s.get();
}
}

8.4 常用函数式接口Comsumer

accept消费andThen同时满足

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
public class T4 {
public static void main(String[] args) {
String[] arr={"林青霞,31","张曼玉,32","柳岩,29"};
// printNA(arr,(s)->{
// String s1 = s.split(",")[0];
// System.out.print("姓名: "+s1);
// },s -> {
// String s1 = s.split(",")[1];
// System.out.println(",年龄 "+s1);
// });
printNA(arr,(s)-> System.out.print("姓名: "+s.split(",")[0]),s -> System.out.println(",年龄 "+s.split(",")[1]));}
private static void printNA(String[] arr, Consumer<String> c1,Consumer<String> c2){
for (String s : arr) {
c1.andThen(c2).accept(s);
//s消费c1,c2
}
}
}

8.5 常用函数式接口Predicate

逻辑非:pre.negate().test(s);

与:and 或:or pre.and(pre2).test(s)

返回类型可更改

复杂案例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
public class T5 {
public static void main(String[] args) {
String[] arr={"林青霞,30","柳岩,34","张曼玉,35","貂蝉,31","王祖贤,33"};
ArrayList<String> L1 = panduan(arr, s -> s.split(",")[0].length() > 2, s -> Integer.parseInt(s.split(",")[1]) > 32);
System.out.println(L1);
}
private static ArrayList<String> panduan(String [] arr, Predicate<String> p1, Predicate<String> p2){
ArrayList<String> arrs = new ArrayList<>();
for (String s : arr) {
if (p1.and(p2).test(s)){
arrs.add(s);
}
}
return arrs;
}
}

8.6 常用函数式接口Function

andThen:两个都满足

屏幕截图 2022-01-07 124817

1
2
3
4
5
6
7
8
9
10
public class T6 {
public static void main(String[] args) {
String s="林青霞,30";
Convert(s,s1 -> s.split(",")[1],s1 -> Integer.parseInt(s1),s1->s1+70);
}
public static void Convert(String s, Function<String,String>f1,Function<String,Integer>f2,Function<Integer,Integer>f3){
Integer a = f1.andThen(f2).andThen(f3).apply(s);
System.out.println(a);
}
}

屏幕截图 2022-01-05 121934

屏幕截图 2022-01-05 132046

屏幕截图 2022-01-05 132314

屏幕截图 2022-01-05 132631

实现平衡二叉树

左左,左右,右左,右右P130

屏幕截图 2022-01-05 133959

屏幕截图 2022-01-05 143625

默认黑色调整两次

红色一次

屏幕截图 2022-01-05 144045

屏幕截图 2022-01-05 144259

屏幕截图 2022-01-05 144843

八、网络通信

1. 简述

屏幕截图 2022-01-12 220206

IP地址:IPV4(32字节),IPV6(16字节)

屏幕截图 2022-01-12 220621

屏幕截图 2022-01-12 220555

特殊IP一般用来测试

屏幕截图 2022-01-12 221256

屏幕截图 2022-01-12 221631

屏幕截图 2022-01-12 221744

屏幕截图 2022-01-12 221853

屏幕截图 2022-01-12 221935

屏幕截图 2022-01-12 222047

屏幕截图 2022-01-12 222141

2. UDP

==先启动服务端(接收端),再启动客户端==

屏幕截图 2022-01-12 224118

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
public class C3 {
public static void main(String[] args) throws Exception {
//发送
//1.创建一个发送端对象,自带默认端口号(人)客户端
DatagramSocket ds = new DatagramSocket();
//2.创建一个数据包封装数据(韭菜盘子)
/*
public DatagramPacket(byte buf[], int offset, int length,
InetAddress address, int port) {
}
参数一:封装要发送的数据
参数二:发送数据的大小长度
参数三:服务器主机IP地址(企业)
参数四:服务器端口
*/
byte[] buffer = "卢浩最帅".getBytes();
DatagramPacket dp = new DatagramPacket(buffer, buffer.length, InetAddress.getLocalHost(), 8888);
// DatagramPacket dp = new DatagramPacket(buffer, buffer.length, InetAddress.getByAddress("IP"), 8888);
ds.send(dp);
ds.close();//一送一关,如果要持续发送,这句可取消
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
public class C4 {
public static void main(String[] args) throws Exception {
//1.接收端对象(人)
DatagramSocket ds = new DatagramSocket(8888);
//2.盘子
byte[] buffer = new byte[1024 * 64];
DatagramPacket dp = new DatagramPacket(buffer, buffer.length);
//3.等待接收数据还未接收
ds.receive(dp);
//4.接收数据
int len=dp.getLength();
String s = new String(buffer,0,len);
System.out.println(s);
//获得发送端的IP和端口
String r = dp.getSocketAddress().toString();
int port = dp.getPort();
System.out.println(r+port);
ds.close();
}
}

2.1 UDP多发多收

==多线程==

屏幕截图 2022-01-13 113121

屏幕截图 2022-01-13 113105

屏幕截图 2022-01-13 113050

2.2 广播

屏幕截图 2022-01-13 113246

屏幕截图 2022-01-13 113812

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
public class C5 {
public static void main(String[] args) throws Exception{
DatagramSocket ds = new DatagramSocket();
Scanner sc = new Scanner(System.in);
while (true){
String s = sc.nextLine();
if (s.equals("exit")){
System.out.println("退出");
ds.close();
break;
}
byte[] buffer = s.getBytes();
DatagramPacket dp = new DatagramPacket(buffer, buffer.length, InetAddress.getByName("255.255.255.255"), 9999);
ds.send(dp);
}
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
public class C6 {
public static void main(String[] args) throws Exception{
DatagramSocket ds = new DatagramSocket(9999);
byte[] buffer = new byte[1024 * 64];
DatagramPacket dp = new DatagramPacket(buffer, buffer.length);
while (true){
ds.receive(dp);
int len=dp.getLength();
String s = new String(buffer, 0, len);
System.out.println("收到了来自"+dp.getAddress()+"的消息"+s);
}
}
}

2.3 组播

屏幕截图 2022-01-13 114259

屏幕截图 2022-01-13 114609

屏幕截图 2022-01-13 114642

3. TCP

3.1 一发一收

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
public class C8 {
public static void main(String[] args) throws Exception{
ServerSocket ss = new ServerSocket(666);
while (true){
Socket ac = ss.accept();
// InputStream is = ac.getInputStream();
// new BufferedReader(new InputStreamReader(is));
// 采用转换流因为bufferedreader不能直接读字节流
BufferedReader br = new BufferedReader(new InputStreamReader(ac.getInputStream()));
String line;
while ((line=br.readLine())!=null){
System.out.println(ac.getRemoteSocketAddress()+" "+line);
}
}
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
public class C7 {
public static void main(String[] args) throws Exception{
Socket so = new Socket("127.0.0.1",666);
// OutputStream os = so.getOutputStream();
// PrintStream ps = new PrintStream(os);
PrintStream ps = new PrintStream(so.getOutputStream());
Scanner sc = new Scanner(System.in);
while (true){
String s = sc.nextLine();
if (s.equals("exit")){
System.out.println("关闭发送");
so.close();
break;
}
ps.println(s);
ps.flush();
}
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
public class C9 {
public static void main(String[] args) throws Exception {
Socket socket = new Socket("127.0.0.1", 10086);
PrintStream ps = new PrintStream(socket.getOutputStream());
Scanner SC = new Scanner(System.in);
while (true) {
String s = SC.nextLine();
ps.println(s);
//一定要用println!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
//!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
//因为用print是没有下一行的,接收端的nextLine接收不到数据
ps.flush();
}
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
public class C10 {
public static void main(String[] args) {
try {
ServerSocket SS = new ServerSocket(10086);
Socket ac = SS.accept();
InputStream is = ac.getInputStream();
BufferedReader br = new BufferedReader(new InputStreamReader(is));
String line;
while ((line=br.readLine())!=null){
System.out.println(line);
}
} catch (Exception e) {
e.printStackTrace();
}
}
}

3.2 多发多收

线程里的run方法不能抛异常

1
2
3
4
5
6
7
8
9
10
11
12
public class C9 {
public static void main(String[] args) throws Exception {
Socket socket = new Socket("127.0.0.1", 10086);
PrintStream ps = new PrintStream(socket.getOutputStream());
Scanner SC = new Scanner(System.in);
while (true) {
String s = SC.nextLine();
ps.println(s);
ps.flush();
}
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
public class C10 {
public static void main(String[] args) {
try {
ServerSocket SS = new ServerSocket(10086);
while (true) {
Socket ac = SS.accept();
new ServiceThread(ac).start();
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
public class ServiceThread extends Thread{
private Socket socket;
public ServiceThread(Socket socket) {
this.socket = socket;
}
@Override
public void run() {
// InputStream is = ac.getInputStream();
// new BufferedReader(new InputStreamReader(is));
// 采用转换流因为bufferedreader不能直接读字节流
/*
每接收到一个客户端管道就创建一个子线程
*/
try {
BufferedReader br = new BufferedReader(new InputStreamReader(socket.getInputStream()));
String line;
while ((line=br.readLine())!=null){
System.out.println(socket.getRemoteSocketAddress()+" "+line);
}
} catch (Exception e) {
e.printStackTrace();
}
}
}

3.3 ==线程池优化==

上述多发多收会创建更多子线程,应用线程池优化

1
2
3
4
5
6
7
8
9
10
11
12
public class C9 {
public static void main(String[] args) throws Exception {
Socket socket = new Socket("127.0.0.1", 10086);
PrintStream ps = new PrintStream(socket.getOutputStream());
Scanner SC = new Scanner(System.in);
while (true) {
String s = SC.nextLine();
ps.println(s);
ps.flush();
}
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
public class C10 {
private static ThreadPoolExecutor tpe=new ThreadPoolExecutor(3, 5, 3,
TimeUnit.SECONDS, new ArrayBlockingQueue<>(2), Executors.defaultThreadFactory(),
new ThreadPoolExecutor.AbortPolicy());
public static void main(String[] args) {
try {
ServerSocket SS = new ServerSocket(10086);
while (true) {
Socket ac = SS.accept();
SrerviceRunnable sr = new SrerviceRunnable(ac);
tpe.execute(sr);
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
public class SrerviceRunnable implements Runnable{
private Socket socket;
public SrerviceRunnable(Socket socket) {
this.socket = socket;
}
@Override
public void run() {
try {
BufferedReader br = new BufferedReader(new InputStreamReader(socket.getInputStream()));
String line;
while ((line=br.readLine())!=null){
System.out.println(socket.getRemoteSocketAddress()+" "+line);
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
/127.0.0.1:58954  第一个线程
/127.0.0.1:58964 第二个线程
/127.0.0.1:58973 第三个线程
/127.0.0.1:59003 那第6个呢
/127.0.0.1:59003 有人管了
/127.0.0.1:59013 试一试第7
/127.0.0.1:59013
java.util.concurrent.RejectedExecutionException: Task heimaSe.Review.R10.SrerviceRunnable@6bf256fa rejected from java.util.concurrent.ThreadPoolExecutor@6cd8737[Running, pool size = 5, active threads = 5, queued tasks = 2, completed tasks = 0]
at java.base/java.util.concurrent.ThreadPoolExecutor$AbortPolicy.rejectedExecution(ThreadPoolExecutor.java:2055)
at java.base/java.util.concurrent.ThreadPoolExecutor.reject(ThreadPoolExecutor.java:825)
at java.base/java.util.concurrent.ThreadPoolExecutor.execute(ThreadPoolExecutor.java:1355)
at heimaSe.Review.R10.C10.main(C10.java:19)
java.net.SocketException: Connection reset
at java.base/java.net.SocketInputStream.read(SocketInputStream.java:186)
at java.base/java.net.SocketInputStream.read(SocketInputStream.java:140)
at java.base/sun.nio.cs.StreamDecoder.readBytes(StreamDecoder.java:284)
at java.base/sun.nio.cs.StreamDecoder.implRead(StreamDecoder.java:326)
at java.base/sun.nio.cs.StreamDecoder.read(StreamDecoder.java:178)
at java.base/java.io.InputStreamReader.read(InputStreamReader.java:185)
at java.base/java.io.BufferedReader.fill(BufferedReader.java:161)
at java.base/java.io.BufferedReader.readLine(BufferedReader.java:326)
at java.base/java.io.BufferedReader.readLine(BufferedReader.java:392)
at heimaSe.Review.R10.SrerviceRunnable.run(SrerviceRunnable.java:17)
at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1128)
at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:628)
at java.base/java.lang.Thread.run(Thread.java:834)
/127.0.0.1:58980 第四个线程
/127.0.0.1:58980 没人管第四个线程
/127.0.0.1:58980 关掉一个线程

3.4 即时通信

屏幕截图 2022-01-13 122717

上面的程序只能称为弹幕。是服务端与客户端

即时通信:客户端对客户端

3.4.1 群发
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
public class Client01 {
public static void main(String[] args) throws Exception {
Socket socket = new Socket("127.0.0.1", 10086);
PrintStream ps = new PrintStream(socket.getOutputStream());
new ClinetReaderThread(socket).start();
Scanner sc = new Scanner(System.in);
while (true) {
String s = sc.nextLine();
ps.println(s);
ps.flush();
}
}
}
class ClinetReaderThread extends Thread{
private Socket socket;
public ClinetReaderThread(Socket socket) {
this.socket = socket;
}
@Override
public void run() {
try {
BufferedReader br = new BufferedReader(new InputStreamReader(socket.getInputStream()));
String line;
while ((line=br.readLine())!=null){
System.out.println("收到"+socket.getRemoteSocketAddress()+"消息: "+" "+line);
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
public class Service {
public static ArrayList<Socket> all_onlineClients= new ArrayList<Socket>();
public static void main(String[] args) throws Exception{
ServerSocket ss = new ServerSocket(10086);
while (true){
Socket socket = ss.accept();
System.out.println(socket.getRemoteSocketAddress()+"上线了");
all_onlineClients.add(socket);
new ServiceThread(socket).start();
}
}
}
class ServiceThread extends Thread{
private Socket socket;
public ServiceThread(Socket socket) {
this.socket = socket;
}
@Override
public void run() {
try {
BufferedReader br = new BufferedReader(new InputStreamReader(socket.getInputStream()));
String line;
while ((line=br.readLine())!=null){
System.out.println(socket.getRemoteSocketAddress()+" "+line);
sendMessageToall(line);
}
} catch (Exception e) {
//关掉一个客户到这里会有异常,在这里实现删减
System.out.println(socket.getRemoteSocketAddress()+"下线了");
Service.all_onlineClients.remove(socket);
}
}

private void sendMessageToall(String message) throws Exception {
for (Socket socket : Service.all_onlineClients) {
PrintStream ps = new PrintStream(socket.getOutputStream());
ps.println(message);
ps.flush();
}
}
}
3.4.2 线程池优化
1
2
3
4
5
6
7
8
9
10
11
12
public class BSsevrice {
private static ThreadPoolExecutor tpe=new ThreadPoolExecutor(3, 5, 3,
TimeUnit.SECONDS, new ArrayBlockingQueue<>(2), Executors.defaultThreadFactory(),
new ThreadPoolExecutor.AbortPolicy());
public static void main(String[] args) throws Exception{
ServerSocket ss = new ServerSocket(3060);
while (true){
Socket socket = ss.accept();
tpe.execute(new ServiceRunnable(socket));
}
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
public class ServiceRunnable implements Runnable{
private Socket socket;
public ServiceRunnable(Socket socket) {
this.socket = socket;
}
@Override
public void run() {
try {
PrintStream ps = new PrintStream(socket.getOutputStream());
ps.println("HTTP/1.1 200 OK");
ps.println("Content-Type:text/html;charset=UTF-8");
ps.println();
ps.println("<span style='color:red;font-size:90px'>《卢浩最牛了》 </span>");
ps.close();
}catch (Exception e){
e.printStackTrace();
}
}
}

屏幕截图 2022-01-14 123235

九、IO

1. File系列

屏幕截图 2022-01-08 204159

屏幕截图 2022-01-09 104609

屏幕截图 2022-01-09 105036

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
public class Q4 {
public static void main(String[] args) {
//1.相对路径
File f1 = new File("fangyuan.jpeg");
long l1 = f1.length();
System.out.println(f1.exists());
System.out.println(l1);
System.out.println(f1.getAbsolutePath());
System.out.println("----------------");
/*2.绝对路径
写法:
(1)C:\\Users\\soul\\Desktop\\Markdown\\fangyuan.jpeg
(2)C:/Users/soul/Desktop/Markdown/fangyuan.jpeg
(3)File.separator
*/
File f2 = new File("C:\\Users\\soul\\Desktop\\Markdown\\fangyuan.jpeg");
File F4 = new File("C:\\Users\\soul\\");
System.out.println(f2.length());
File f3 = new File("C:\\Users\\soul\\", "Desktop\\Markdown\\fangyuan.jpeg");
File f5 = new File(F4,"Desktop\\Markdown\\fangyuan.jpeg");
//只能前面是file后面是路径
System.out.println(f5.exists());
}
}
1
2
3
4
5
6
true
136026
D:\inJava\fangyuan.jpeg
----------------
136026
true
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
public class Q5 {
public static void main(String[] args) throws Exception {
File f1 = new File("Date.txt");
System.out.println(f1.createNewFile());
//因为已经存在所以false
File f2 = new File("Date01.txt");
System.out.println(f2.createNewFile());
//几乎不用,因为以后文件是自动创建
System.out.println("---------------");
//单多集创建
File f3 = new File("D:\\Hao's bag\\ee");
f3.mkdir();
File f4 = new File("D:\\Hao's bag\\dd\\ee");
f4.mkdirs();
f4.delete();
//在用一样可以删除,不能删除非空文件夹
}
}

1.1 File遍历

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
public class Q6 {
public static void main(String[] args) {
File f1 = new File("C:\\Users\\soul\\Desktop\\Markdown");
String[] li = f1.list();
Arrays.stream(li).forEach(System.out::println);
System.out.println("------------------------");
Arrays.stream(f1.listFiles()).forEach(new Consumer<File>() {
@Override
public void accept(File file) {
File ab = file.getAbsoluteFile();
System.out.println(ab);
}
});
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
20190812223017908.png
fangyuan.jpeg
JavaSE
JavaSE图片
logback-classic-1.2.3-javadoc.jar
logback-core-1.2.3-javadoc.jar
markdown基础.md
slf4j-api-1.7.26-javadoc.jar
------------------------
C:\Users\soul\Desktop\Markdown\20190812223017908.png
C:\Users\soul\Desktop\Markdown\fangyuan.jpeg
C:\Users\soul\Desktop\Markdown\JavaSE
C:\Users\soul\Desktop\Markdown\JavaSE图片
C:\Users\soul\Desktop\Markdown\logback-classic-1.2.3-javadoc.jar
C:\Users\soul\Desktop\Markdown\logback-core-1.2.3-javadoc.jar
C:\Users\soul\Desktop\Markdown\markdown基础.md
C:\Users\soul\Desktop\Markdown\slf4j-api-1.7.26-javadoc.jar

1.2 ==注意事项==

屏幕截图 2022-01-09 175648

1.3 方法递归

屏幕截图 2022-01-09 180617

屏幕截图 2022-01-09 180653

![屏幕截图 2022-01-09 181205](C:\Users\soul\Desktop\Markdown\JavaSE图片\屏幕截图 2022-01-09 181205.png)

屏幕截图 2022-01-09 181214

1.3.1 递归实现遍历
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
public class Q7 {
public static void main(String[] args) {
File f1 = new File("C:\\Users\\soul\\Desktop\\study\\src\\heiMa");
getPath(f1);
}
public static void getPath(File file){
File[] f1 = file.listFiles();
if (f1.length>0&&f1!=null){
for (File f2 : f1) {
if (f2.isDirectory()){
getPath(f2);
}else {
System.out.println(f2.getAbsolutePath());
}
}
}
}
}
1.3.2 递归实现查找文件
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
public class Q7 {
public static void main(String[] args) {
File f1 = new File("C:\\Users\\soul\\Desktop\\study\\src\\heiMa");
getPath(f1,"duoDuixiang.java");
}
public static void getPath(File file,String name){
File[] f1 = file.listFiles();
if (f1.length>0&&f1!=null){
for (File f2 : f1) {
if (f2.isFile()){
if (f2.getName().contains(name)){
System.out.println(f2.getAbsolutePath());
}
}else {
getPath(f2,name);
}
}
}
}
}

2. ==IO流==

屏幕截图 2022-01-11 220144

2.1 ==字节流和字符流的区别==

字节(byte):8位

字符(char):16位

每次读写的字节数不同;

字符流是块读写,字节流是字节读写;

字符流带有缓存,字节流没有。

java流在处理上分为字符流和字节流。字符流处理的单元为2个字节的Unicode字符,分别操作字符、字符数组或字符串,而字节流处理单元为1个字节,操作字节和字节数组。

字符流和字节流,一个属性范围小,一个属性范围大,字符流只能是字符这一种类型,但是字节流中可以是字符,可以是二进制文件,可以是音频,可以是各种各样的类型,只要符合字节形式存储的都可以接字节流,==而字符流只能接字符==。

==磁盘到内存称为读数据,input==

==内存到磁盘称为写数据,output==

字符集

ASCII

GBK:Windows系统默认的码表,兼容ASCII,是中国的码表,但不包括所有国家的文字。

Unicode(万国码,统一码,单一码):容纳世界上大多数国家所有常见文字和符号,会先通过UTF-8,UTF-16,UTF-32编码成2进制到计算机存储。一个中文以==3个字节==存储,UTF-8兼容ASCII,==技术人员都应使用UTF-8==

2.2 编码解码

解码:String(byte[] )

编码:getByte()

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
public class Q8 {
public static void main(String[] args) throws Exception {
String a="卢浩爱中国";
byte[] bytes = a.getBytes();
byte[] gbks = a.getBytes("GBK");
System.out.println(Arrays.toString(bytes));
System.out.println(Arrays.toString(gbks));
System.out.println("---------");
String s = new String(bytes);
String s1=new String(gbks);
System.out.println(s);
System.out.println(s1);
//编码解码不一致
}
}
1
2
3
4
5
[-27, -115, -94, -26, -75, -87, -25, -120, -79, -28, -72, -83, -27, -101, -67]
[-62, -84, -70, -58, -80, -82, -42, -48, -71, -6]
---------
卢浩爱中国
¬�ư��й�

屏幕截图 2022-01-09 193901

2.3 IO流简述

==字符流最大的好处是它可以进行中文的有效处理==。如果在日常开发中有中文处理,用字符流,如果没有,建议使用字节流。字节流也能处理中文,==但很可能出现乱码==

20200218091506629

20200218091526371

2.4 字节输入输出流

一个字节一个字节读存取数据

水流模型(一滴一滴读,读完就没了,返回-1)

2.4.1 字节输入流
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
public class Q9 {
public static void main(String[] args) throws Exception {
// FileInputStream fis = new FileInputStream(new File("Date.txt"));
//此处可以不new File 因为在源码中,若找不到,自己会new一个,因此可简化为:
FileInputStream fis = new FileInputStream("Date.txt");
int re = fis.read();//读一个字节
System.out.println(re);
System.out.println((char)re);

int r2 = fis.read();
int r3 = fis.read();
int r4 = fis.read();
System.out.println(r4);//-1
}
}
97
a
-1
1
2
3
4
5
6
7
8
9
public class Q9 {
public static void main(String[] args) throws Exception {
FileInputStream fis = new FileInputStream("Date.txt");
int b;
while ((b=fis.read())!=-1){
System.out.println((char) b);
}
}
}

上述只要出现中文就会出错,因为中文两到三字节,若上面还有读取的操作,则while开始时不是从第一个开始读取

2.4.1.1 批量读取
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
public class Q10 {
public static void main(String[] args) throws Exception {
FileInputStream fis = new FileInputStream("Date.txt");
byte[] buffer = new byte[3];//3B一桶水
int len =fis.read(buffer);
System.out.println("读取了"+len);
String s = new String(buffer);
System.out.println(s);
//桶里装着[ab3]
int len2 =fis.read(buffer);
System.out.println("读取了"+len2);
String s1 = new String(buffer);
System.out.println(s1);
//[abc]
int len3 =fis.read(buffer);
System.out.println("读取了"+len3);
String s2 = new String(buffer);
System.out.println(s2);
//因为最后只有两滴水[cd ]
//上一桶水还生了一滴[ c]因此补上
}
}
1
2
3
4
5
6
读取了3
ab3
读取了3
abc
读取了2
cdc

==解决方案==

读多少倒多少

1
2
3
String s2 = new String(buffer,0,len3);
读取了2
cd

==循环读取==

1
2
3
4
5
6
7
8
9
10
public class Q11 {
public static void main(String[] args) throws Exception {
FileInputStream fis = new FileInputStream("Date.txt");
byte[] buffer = new byte[1024];
int len;
while ((len=fis.read(buffer))!=-1){
System.out.println(new String(buffer,0,len));
}
}
}
2.4.1.2 ==增强版==
1
2
3
4
5
6
7
8
9
public class Q11 {
public static void main(String[] args) throws Exception {
File f = new File("Date.txt");
FileInputStream fis = new FileInputStream(f);
byte[] b1 = fis.readAllBytes();
//读取全部字节
System.out.println(new String(b1));
}
}
2.4.2 字节输出流

==输出中文数据可能出问题==

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
public class N1 {
public static void main(String[] args) throws Exception {
// FileOutputStream fops = new FileOutputStream("Date.txt");
FileOutputStream fops = new FileOutputStream("Date.txt",true);
//可以设置追加数据,如果不设置,则使用前会先清空文件中的数据
fops.write(97);
fops.write("我爱中国".getBytes());
byte [] buf={99,'a','L','P'};
fops.write(buf);//写入一个字节数组
fops.write("\r\n".getBytes());
fops.write(buf,0,2);//从字节数组第几个开始写几个进入
//换行
fops.flush();//必须刷新,否则缓冲的数据可能丢失,之后还可写入
fops.close();//关闭,包含刷新
}
}
2.4.2.1 JDK7升级操作

放到catch(中)只能放置资源对象,自动调用close关闭,即使出现异常

==资源==都是实现了closeable/Autocloseable的类对象

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
public class N2 {
public static void main(String[] args) {
try (
FileInputStream fis =new FileInputStream("fangyuan.jpeg");
FileOutputStream fos=new FileOutputStream("fangyuan01.jpeg");
){
byte[] buffer = new byte[1024];
int len;
while ((len=fis.read(buffer))!=-1){
fos.write(buffer,0,len);
}
System.out.println("完成");
} catch (Exception e) {
e.printStackTrace();
}
}
}
2.4.2.2 Autocloseable

自动释放资源

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
public class N4 {
public static void main(String[] args) {
try (
myconnection my = new myconnection();
//被放在catch()中被认定为是资源,如果删掉try-catch,则不会调用,说明try()会自动关闭资源
){

} catch (Exception e) {
e.printStackTrace();
}
}
}
class myconnection implements AutoCloseable{
@Override
public void close() throws Exception {
System.out.println("资源已经被释放");
}
}
资源已经被释放
2.4.2.3 JDK9(鸡肋升级版)

屏幕截图 2022-01-10 194806

2.4.3 字节流复制

屏幕截图 2022-01-10 214338

屏幕截图 2022-01-10 214402

2.5 字符输入输出流

==面向中文==

2.5.1 读数据
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
public class N5 {
public static void main(String[] args) throws Exception {
FileReader fr = new FileReader("Date01.txt");
/*
int r1 = fr.read();
System.out.println((char) r1);
//爱

int r2 = fr.read();//每次读一个字符
System.out.println((char) r2);
//2,即使是2,也会被认为是字符
*/


/*
int code;
while ((code=fr.read())!=-1){
System.out.println((char)code );
}
*/
//升级版
char[] buffer = new char[1024];//读取1K字符!!!!!!不是1KB
int len;
while ((len=fr.read(buffer))!=-1){
System.out.println(new String(buffer,0,len));
//假设1024+1024+8,一共读4次
}
fr.close();
}
}
2.5.2 写数据
1
2
3
4
5
6
7
8
9
10
11
12
13
public class N6 {
public static void main(String[] args) throws Exception {
FileWriter fw = new FileWriter("Date.txt", true);
fw.write(97);
fw.write('徐');//fw.write('徐州')则报错
fw.write("我是中国人");
fw.write("\r\n");
char[] chars = "abc我是中国人".toCharArray();
fw.write(chars);//没必要
fw.write(chars,0,3);//abc在字节流中是9个字节
fw.flush();
}
}

2.6 缓冲流

相当于粗水管与细水管

屏幕截图 2022-01-10 212329

2.6.1 字节缓冲流

可以对普通输出输入流扩容:new byte[1024*8]

屏幕截图 2022-01-10 212442

屏幕截图 2022-01-10 212519

屏幕截图 2022-01-10 213314

屏幕截图 2022-01-10 213926

2.6.2 字符缓冲流复制

屏幕截图 2022-01-10 214542

2.6.3 ==字符流特有功能==
1
2
3
4
5
6
7
8
9
10
11
12
13
14
public class N7 {
public static void main(String[] args) throws Exception {
BufferedReader br = new BufferedReader(new FileReader("Date.txt"));
BufferedWriter bw = new BufferedWriter(new FileWriter("Date01.txt"));
String line;
while ((line=br.readLine())!=null){
bw.write(line);
bw.newLine();//加一行
bw.flush();
}
bw.close();
br.close();
}
}
2.6.4 ==字符转换流==

文件与IDEA UTF-8不一致 出现乱码

IntputStreamReader 与 OutputStreamWriter

1相等于new FileWriter==new InputStreamReader(InputStream xx)

屏幕截图 2022-01-11 173851

屏幕截图 2022-01-11 183102

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
public class N8 {
public static void main(String[] args) throws Exception {
InputStreamReader isr = new InputStreamReader(new FileInputStream("Date.txt"),"GBK");//GBK
BufferedReader br = new BufferedReader(isr);
String line;
/*
char[] buffer = new char[1024];
int len;
while ((len=isr.read())!=-1){
System.out.print(len);
}
979851979899991002923320102972510529233200132226999977680131099979724464251052615920013222692015413109798992510526159200132226920154979899
*/
System.out.println("------------");
while ((line= br.readLine())!=null){
System.out.println(line);
}
isr.close();//正确读法
}
}

输出

1
2
3
4
5
6
7
8
9
10
11
12
13
public class N9 {
public static void main(String[] args) {
try (
BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(new FileOutputStream("Date03.txt"), "GBK"));
//默认UTF-8创建,不如直接new FileWriter 也可以使用getByte("GBK"),但有区别,上述是以GBK为基准创建文件,而getByte
){
bw.write(String.valueOf("A".getBytes("GBK")));
bw.write("我是中国人");
} catch (Exception e) {
e.printStackTrace();
}
}
}

2.7 序列化反序列化

以内存为基准,将内存中的==对象==存到磁盘文件当中去,称为对象序列化ObjectOutputStream

对象要实现序列化,==必须实现Serializable接口==(声明性接口)实现之后JVM虚拟机就知道你这个对象是要存储到磁盘中,一个标准,通知虚拟机以序列化方式进行存储。打开来看是一堆==乱码==,因为对象只是暂时存储在磁盘中,不是为了看的,而是为了再次导出。

==transient==:代表不参与序列化,例如:private transient int passcode ;

==serialVersionUID==:序列化版本号,一旦对象Student更新了数据如爱好等等,原序列化的文件全部作废,必须重新序列化,才能成功反序列化.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
public class Student implements Serializable {
private static final long serialVersionUID=1;
private String name;
private int age;
private transient String password;
public Student() {}
public Student(String name, int age, String password) {
this.name = name;
this.age = age;
this.password = password;
}
public String getName() {return name;}
public void setName(String name) {this.name = name;}
public int getAge() {return age;}
public void setAge(int age) {this.age = age;}
public String getPassword() {return password;}
public void setPassword(String password) {this.password = password;}
@Override
public String toString() {
return "name是:"+name+" age是:"+age+" 密码是:"+password;
}
}
1
2
3
4
5
6
7
8
9
public class ObjecctOutput {
public static void main(String[] args) throws Exception {
ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("Date02.txt"));
Student lh = new Student("luhao", 19, "1013886337");
System.out.println(lh.toString());
oos.writeObject(lh);
oos.close();
}
}
1
2
3
4
5
6
7
8
public class ObjectInput {
public static void main(String[] args) throws Exception {
ObjectInputStream ois = new ObjectInputStream(new FileInputStream("Date02.txt"));
Student student = (Student) ois.readObject();
System.out.println(student.toString());
ois.close();
}
}

2.8 打印流

在打印方面,PrintWriter和PrintStream没区别,啥都可以打

2.8.1 字节打印流

既可以通向低级管道,又可以直接通向文件,离谱。

1
2
//        PrintStream ps = new PrintStream(new FileOutputStream("Date04.txt"));
PrintStream ps = new PrintStream("Date04.txt");

原理源码:

1
2
3
public PrintStream(String fileName) throws FileNotFoundException {
this(false, new FileOutputStream(fileName));
}

可以追加:

1
PrintStream ps = new PrintStream(new FileOutputStream("Date04.txt"),true);

用==print==输出数据print(xx);

屏幕截图 2022-01-11 220356

2.8.2 字符打印流

==改变输出语句==

1
2
3
4
5
6
7
8
9
public class N10 {
public static void main(String[] args) throws Exception{
PrintStream ps = new PrintStream("Date04.txt");
System.setOut(ps);
System.out.println("luhao");
System.out.println(666);
ps.close();
}
}

2.9 IO流与Properties

屏幕截图 2022-01-12 202139

屏幕截图 2022-01-12 202517

屏幕截图 2022-01-12 202537

1
2
3
4
5
6
7
8
9
10
11
12
public class N11 {
public static void main(String[] args) throws Exception{
Properties pp = new Properties();
// pp.put("luhao",19);离家出走与Map无关了,与IO流挂钩
pp.setProperty("luhao","19");//功能与put同,但是只能是两个String,源码
pp.store(new FileWriter("Date05.properties"),"this is shuaige!!!");
/*
参数二:保存心得
在store内部new一个他会自动帮你关闭流
*/
}
}
1
2
3
4
5
6
7
8
9
10
public class N12 {
public static void main(String[] args) throws Exception{
Properties pp = new Properties();
pp.load(new FileReader("Date05.properties"));
// Object lh = pp.get("luhao");get是Map里的,
String lh = pp.getProperty("luhao");//因为setPropertise里只能放String,String,所以只能读String
System.out.println(lh);
}
}
19

2.10 ==Commons-io==

屏幕截图 2022-01-12 210844

屏幕截图 2022-01-12 211259

2.11 FileUtils

(黑马167)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
public class C1 {
public static void main(String[] args) throws Exception {
//1.完成文件复制
IOUtils.copy(new FileInputStream("Date.txt"),new FileOutputStream("Date06.txt"));
//2.完成文件复制到某个文件夹下
FileUtils.copyFileToDirectory(new File("Date.txt"),new File("C:\\Users\\soul\\Desktop\\study\\src\\heiMa\\basic"));
//3.文件夹复制到文件夹下
FileUtils.copyDirectoryToDirectory(new File("C:\\Users\\so" +
"ul\\Desktop\\study\\src\\heiMa\\basic\\demo1"),new File("C:\\U" +
"sers\\soul\\Desktop\\study\\src\\heiMa\\basic\\demo1\\DEMOMO"));
//删除文件文件夹
// FileUtils.delete(new File("XXX"))
}
}

2.12 JDK1.7升级IO

1
2
3
4
5
6
7
8
public class C2 {
public static void main(String[] args) throws Exception{
//复制
Files.copy(Path.of("Date.txt"),Path.of("Date01.txt"));
//删除
Files.deleteIfExists(Path.of("Date.txt"));
}
}

十、Stream流

1. Stream流API范例

分生成流,中间操作,终结操作

屏幕截图 2022-01-07 151537

1
2
3
4
5
6
7
public class T8 {
public static void main(String[] args) {
ArrayList<String> str = new ArrayList<>();
Collections.addAll(str,"张无忌","赵敏","张三丰","周芷若","张强");
str.stream().filter(s -> s.startsWith("张")).filter(s -> s.length()>=3).forEach(System.out::println);
}
}
1
2
3
4
5
6
7
8
9
10
11
12
public class T8 {
public static void main(String[] args) {
ArrayList<String> str = new ArrayList<>();
Collections.addAll(str,"张无忌","赵敏","张三丰","周芷若","张强");
//取前三个
str.stream().limit(3).forEach(System.out::println);
System.out.println("------------------------");
//跳前三个
str.stream().skip(3).forEach(System.out::println);
System.out.println("------------------------");
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
public class T8 {
public static void main(String[] args) {
ArrayList<String> str = new ArrayList<>();
Collections.addAll(str,"张无忌","赵敏","张三丰","周芷若","张强");
Stream<String> s1 = str.stream().limit(4);
Stream<String> s2 = str.stream().skip(1);
//拼接两个流
// Stream.concat(s1,s2).forEach(System.out::println);
//去重
System.out.println("---------------");
Stream.concat(s1,s2).distinct().forEach(System.out::println);
}
}

==流用过一遍就关闭了,无法继续使用==

2. API排序

1
2
3
4
5
6
7
8
9
10
11
public class T10 {
public static void main(String[] args) {
ArrayList<String> str = new ArrayList<>();
Collections.addAll(str,"linqingxia","zhangsanfeng","zhangwuji","zhaomin");
str.stream().sorted((s1,s2)->s1.length()-s2.length()).forEach(System.out::println);
str.stream().sorted((s1,s2)-> {
int num=s1.length()-s2.length();
return num==0?s1.compareTo(s2):num;
}).forEach(System.out::println);
}
}

3. MAP

1
2
3
4
5
6
7
8
9
10
11
12
13
14
public class T0 {
public static void main(String[] args) {
ArrayList<String> str = new ArrayList<>();
Collections.addAll(str,"10","20","30","40","50");
// str.stream().map(new Function<String, Integer>() {
// @Override
// public Integer apply(String s) {
// return Integer.parseInt(s);
// }
// });
str.stream().map(s -> Integer.parseInt(s)).forEach(System.out::println);
str.stream().map(Integer::parseInt).forEach(System.out::println);
}
}

4. MaptoInt

有更多功能,得到IntStream,可以求和

1
2
3
4
5
6
7
8
public class T0 {
public static void main(String[] args) {
ArrayList<String> str = new ArrayList<>();
Collections.addAll(str,"10","20","30","40","50");
int sum = str.stream().mapToInt(Integer::parseInt).sum();
System.out.println(sum);
}
}

5.终结操作

forEach,count,sum,此时流已经结束,得到基本类型

1
2
3
4
5
6
7
8
public class T0 {
public static void main(String[] args) {
ArrayList<String> str = new ArrayList<>();
Collections.addAll(str,"10","20","30","40","50");
long count = str.stream().count();
System.out.println(count);
}
}

6. Stream案例

屏幕截图 2022-01-07 163146

1
2
3
4
5
6
7
8
9
10
public class T11 {
public static void main(String[] args) {
ArrayList<String> man = new ArrayList<>();
Collections.addAll(man,"周润发","成龙","刘德华","吴京","周星驰","李连杰");

ArrayList<String> woman = new ArrayList<>();
Collections.addAll(woman,"林心如","张曼玉","林青霞","柳岩","林志玲","王祖贤");
Stream.concat(man.stream().filter(s -> s.length()>=3).limit(3),woman.stream().filter(s -> s.startsWith("林")).skip(1)).map(Actor::new).forEach(actor -> System.out.println(actor.getName()));
}
}

7. Stream流的获取

7.1 Collection集合

1
2
3
4
5
6
public class T9 {
public static void main(String[] args) {
ArrayList<String> list = new ArrayList<>();
Stream<String> stream = list.stream();
}
}

7.2 Map间接

1
2
3
4
5
6
7
8
public class T9 {
public static void main(String[] args) {
HashMap<String, Integer> map = new HashMap<>();
Stream<String> s1 = map.keySet().stream();
Stream<Integer> s2 = map.values().stream();
Stream<Map.Entry<String, Integer>> s3 = map.entrySet().stream();
}
}

7.3 数组通过Stream接口

1
2
3
4
5
6
7
public class T9 {
public static void main(String[] args) {
String[] arr={};
Stream<String> a1 = Stream.of(arr);
Stream<String> s2 = Arrays.stream(arr);
}
}

8. Stream流收集

接口collector

工具类:collectors

List and Set:

1
2
3
4
5
6
7
8
9
public class T12 {
public static void main(String[] args) {
ArrayList<String> str = new ArrayList<>();
Collections.addAll(str,"luhao","lianghe","zcy");
Stream<String> stream = str.stream();
List<String> List = stream.collect(Collectors.toList());
Set<String> Set = stream.collect(Collectors.toSet());
}
}

Map集合:

1
2
3
4
5
6
7
8
public class T13 {
public static void main(String[] args) {
String[] arr={"林青霞,30","张曼玉,35","王祖贤,33","柳岩,25"};
Stream<String> ss = Stream.of(arr).filter(s -> Integer.parseInt(s.split(",")[1]) > 28);
Map<String, Integer> map = ss.collect(Collectors.toMap(s -> s.split(",")[0], s -> Integer.parseInt(s.split(",")[1])));
System.out.println(map.get("林青霞"));
}
}

十一、集合

集合中所储存的都认为是对象,因此支持泛型(==包装类==)

可添加减少元素

1. 集合嵌套

1.1 HashMap中存ArrayList

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
public class Test03 {
public static void main(String[] args) {
HashMap<String, ArrayList<String>> sah = new HashMap<>();
ArrayList<String> str1 = new ArrayList<>();
str1.add("Luhao");
str1.add("Lianghe");
str1.add("Zhangcongyi");
ArrayList<String> str2 = new ArrayList<>();
str2.add("luhao");
str2.add("lianghe");
str2.add("zhangcongyi");
ArrayList<String> str3 = new ArrayList<>();
str3.add("LIANGHE");
str3.add("LUHAO");
str3.add("ZHANGCONGYI");
sah.put("s1",str1);
sah.put("s2",str2);
sah.put("s3",str3);
Set<Map.Entry<String, ArrayList<String>>> en = sah.entrySet();
for (Map.Entry<String, ArrayList<String>> sae : en) {
String key=sae.getKey();
ArrayList<String> value=sae.getValue();
for (String s : value) {
System.out.println(key+s);
}
}
}
}

1.2 ArrayList中存HashMap

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
public class Test03 {
public static void main(String[] args) {
ArrayList<HashMap<String,String>> arr= new ArrayList<>();
HashMap<String, String> SSH = new HashMap<>();
SSH.put("LUHAO","666");
SSH.put("LIANGHE","888");
SSH.put("ZCY","LLL");
arr.add(SSH);
HashMap<String, String> SSB = new HashMap<>();
SSH.put("luhao","666");
SSH.put("lianghe","888");
SSH.put("zcy","LLL");
HashMap<String, String> SSD = new HashMap<>();
SSH.put("Luhao","666");
SSH.put("Lianghe","888");
SSH.put("Zcy","LLL");
arr.add(SSB);
arr.add(SSD);
for (HashMap<String, String> SSHM : arr) {
Set<String> SET = SSHM.keySet();
for (String s : SET) {
System.out.println(s+SSHM.get(s));
}
}
}
}

2. Collections工具类

==shift+F6==同步改名字

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
public class Test03 {
public static void main(String[] args) {
List<Integer> IT = new ArrayList<>();
Collections.addAll(IT,232,444,555,2,992,12,33,21);
System.out.println(IT);
Collections.shuffle(IT);
//打乱顺序
System.out.println(IT);
Collections.sort(IT, new Comparator<Integer>() {
@Override
public int compare(Integer o1, Integer o2) {
return o1-o2;
}
});
System.out.println(IT);
}
}

简化版:

1
Collections.sort(IT, (Integer o1, Integer o2) -> o1-o2);

3. Map集合

HashMap:无序,不重复,无索引

LinkedHashMap:有序(根据添加的顺序),不重复,无索引

TreeMap:可排序,不重复,无索引

屏幕截图 2022-01-05 213943

得到value:int a=maps.get(key);

3.1 杂类操作

3.1.1 不可变集合
1
List<Double> num = List.of(100.0, 282.1, 67.23);
3.1.2 获取键值集合1
1
2
3
4
5
6
7
8
9
10
11
12
public class Test03 {
public static void main(String[] args) {
LinkedHashMap<String, Integer> si = new LinkedHashMap<>();
si.put("lh",100);
si.put("lh1",10);
si.put("aa",330);
Set<String> set = si.keySet();
for (String s : set) {
System.out.println(s+si.get(s));
}
}
}
3.1.3 获取键值集合2
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
public class Test03 {
public static void main(String[] args) {
LinkedHashMap<String, Integer> si = new LinkedHashMap<>();
si.put("lh",100);
si.put("lh1",10);
si.put("aa",330);
Set<Map.Entry<String, Integer>> en = si.entrySet();
for (Map.Entry<String, Integer> sie : en) {
int value = sie.getValue();
String key=sie.getKey();
System.out.println(key+value);
}

}
}
3.1.4 获取全部值的集合
1
2
3
4
5
6
7
8
9
10
11
12
public class Test03 {
public static void main(String[] args) {
LinkedHashMap<String, Integer> si = new LinkedHashMap<>();
si.put("lh",100);
si.put("lh1",10);
si.put("aa",330);
Collection<Integer> va = si.values();
for (Integer integer : va) {
System.out.println(integer);
}
}
}
3.1.5 合并集合
1
2
3
4
5
6
7
8
9
10
11
12
public class Test03 {
public static void main(String[] args) {
LinkedHashMap<String, Integer> si = new LinkedHashMap<>();
si.put("lh",100);
si.put("lh1",10);
si.put("aa",330);
HashMap<String, Integer> sih = new HashMap<>();
sih.put("Zcy",22);
si.putAll(sih);
System.out.println(si);
}
}

3.2 HashMap

1
2
3
4
5
6
7
8
9
10
11
public class Test03 {
public static void main(String[] args) {
Map<String, Integer> si = new HashMap<>();
si.put("lh",1);
si.put("lh1",1);
si.put(null,null);
si.put("aa",1);
System.out.println(si);
}
}
{null=null, aa=1, lh1=1, lh=1}

3.3 LinkedHashMap

这里的有序指的是根据添加的顺序

3.4 TreeMap

可设置排序同TreeMap同

依靠equals和hashcode

[跳转TreeSet](# TreeSet)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
public class Test03 {
public static void main(String[] args) {
TreeMap<Integer, String> ist = new TreeMap<>();
ist.put(3,"张三");
ist.put(1,"李四");
ist.put(5,"王五");
System.out.println(ist);
//默认按数值大小排序
Map<Student, String> sst = new TreeMap<>(new Comparator<Student>() {
@Override
public int compare(Student o1, Student o2) {
int num= o1.getAge()- o2.getAge();
return num==0?o1.getName().compareTo(o2.getName()):num;
}
});
sst.put(new Student("luhao",19),"杭州");
sst.put(new Student("lianghe",19),"济南");
sst.put(new Student("zcy",18),"广西");
System.out.println(sst);
}
}
1
2
3
{1=李四, 3=张三, 5=王五}
{Student{name='zcy', age=18}=广西, Student{name='lianghe', age=19}=济南, Student{name='luhao', age=19}=杭州}

还有实现接口方法(Comparable)

4. Collection接口

多态实现Collection

Collection接口==没索引==

Set:无序,不重复,无索引(TreeSet,LinkedHarshSet除外),因为不重复,所以无索引

1
2
3
4
5
6
7
        Collection list = new ArrayList();
list.add("JAVA");
list.add("JAVA");
list.add(false);
list.add(false);
System.out.println(list);
//[JAVA, JAVA, false, false]

List:有序,可重复,有索引

1
2
3
4
5
6
7
8
9
10
11
public class Test02 {
public static void main(String[] args) {
Collection list = new HashSet();
list.add("JAVA");
list.add("JAVA");
list.add(false);
list.add(false);
System.out.println(list);
}
}
//[JAVA, false]
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
public class Test02 {
public static void main(String[] args) {
Collection<String> Str = new ArrayList<>();
//1.添加,成功返回true
Str.add("a");
System.out.println(Str.add("N"));
//2.清空
Str.clear();
//3.判断是否为空
System.out.println(Str.isEmpty());
Str.add("CC");
Str.add("DD");
Str.add("EE");
//4.集合大小
System.out.println(Str.size());
//5.是否包含某元素
System.out.println(Str.contains("CC"));
//6.删除元素,若多个相同则删除第一个
Str.remove("CC");
//7.集合转数组
Object[] ob = Str.toArray();
System.out.println(Arrays.toString(ob));
}
}
//true
//true
//3
//true
//[DD, EE]
1
2
3
4
5
6
7
8
9
10
11
public class Test02 {
public static void main(String[] args) {
Collection<String> Str = new ArrayList<>();
Str.add("bb");
ArrayList<String> Str2 = new ArrayList<>();
Str2.add("A");
Str.addAll(Str2);
System.out.println(Str);
}
}
//[bb, A]

4.1 Collection遍历方式

4.1.1. Collection迭代器
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
public class Test02 {
public static void main(String[] args) {
Collection<String> Str = new ArrayList<>();
Str.add("a");
Str.add("b");
Str.add("c");
Str.add("d");
Iterator<String> IT = Str.iterator();
// System.out.println(IT.next());//a
// System.out.println(IT.next());//b
while (IT.hasNext()){
System.out.println(IT.next());
}
}
}
a
b
c
d
4.1.2. 增强for
4.1.3. Lambda(Consumer)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
public class Test02 {
public static void main(String[] args) {
Collection<String> Str = new ArrayList<>();
Str.add("a");
Str.add("b");
Str.add("c");
Str.add("d");
Str.forEach(new Consumer<String>() {
@Override
public void accept(String s) {
System.out.println(s);
}
});
System.out.println("--------------");
Str.forEach(s -> System.out.println(s));
System.out.println("------------");
Str.forEach(System.out::println);
}
}
a
b
c
d
--------------
a
b
c
d
------------
a
b
c
d

4.2 Collection储存对象

5.Set

无序,但只会无序一次,跟随第一次取的

不重复

无索引,不能用普通for

Set集合各实现类

==HarshSet==:无序,不重复,没索引

==LinkedHarshSet==:有序,不重复,没索引

==TreeSet==:可排序.不重复,没索引

5.1 LinkedhashSet

存的时候怎么样,取得时候就怎么样

额外多了一个双链表机制记录存储顺序(其余与hashSet同)

1
2
3
4
5
6
7
8
9
10
11
public class Test03 {
public static void main(String[] args) {
Set<String> str = new LinkedHashSet<>();
str.add("sD ADA");
str.add("ss");
str.add("ss");
str.add("ad ed adawzda");
System.out.println(str);
}
}
[sD ADA, ss, ad ed adawzda]

5.2TreeSet

方式一

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
public class Test03 {
public static void main(String[] args) {
TreeSet<Student> st = new TreeSet<>();
Student s1 = new Student("zcy", 17);
Student s2 = new Student("lianghe", 15);
Student s3 = new Student("jizhijian", 16);
Student s4 = new Student("wx", 18);
Student s5 = new Student("lh", 15);
st.add(s1);
st.add(s2);
st.add(s3);
st.add(s4);
st.add(s5);
System.out.println(st);
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
public class Student implements Comparable<Student>{
private String name;
private int age;

public Student() {
}

public Student(String name, int age) {
this.name = name;
this.age = age;
}

public String getName() {
return name;
}

public void setName(String name) {
this.name = name;
}
//内容一样就一样(不判地址值)
@Override
public boolean equals(Object o) {
//判断是不是一个对象
if (this == o) return true;
//判断是否为null
if (!(o instanceof Student)) return false;
Student student = (Student) o;
return getAge() == student.getAge() && Objects.equals(getName(), student.getName());
}
@Override
public int hashCode() {
return Objects.hash(getName(), getAge());
//name,及age传入,即name,age哈希值相同即是相同
}

public int getAge() {
return age;
}

public void setAge(int age) {
this.age = age;
}

@Override
public String toString() {
return "Student{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}

@Override
public int compareTo(Student o) {
return this.getAge()-o.age>=0?1:-1;
}
}

方式二

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
public class Test03 {
public static void main(String[] args) {
TreeSet<Student> st = new TreeSet<>(new Comparator<Student>() {
@Override
public int compare(Student o1, Student o2) {
int num= o1.getAge()- o2.getAge();
return num==0?o1.getName().compareTo(o2.getName()):num;
}
});
Student s1 = new Student("zcy", 17);
Student s2 = new Student("lianghe", 15);
Student s3 = new Student("jizhijian", 16);
Student s4 = new Student("wx", 18);
Student s5 = new Student("lh", 15);
st.add(s1);
st.add(s2);
st.add(s3);
st.add(s4);
st.add(s5);
System.out.println(st);
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
public class Student {
private String name;
private int age;
public Student() {
}
public Student(String name, int age) {
this.name = name;
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
//内容一样就一样(不判地址值)
@Override
public boolean equals(Object o) {
//判断是不是一个对象
if (this == o) return true;
//判断是否为null
if (!(o instanceof Student)) return false;
Student student = (Student) o;
return getAge() == student.getAge() && Objects.equals(getName(), student.getName());
}
@Override
public int hashCode() {
return Objects.hash(getName(), getAge());
//name,及age传入,即name,age哈希值相同即是相同
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
@Override
public String toString() {
return "Student{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
}

5.3 HarshSet

哈希值:是JDK根据对象的地址,按某种规则算出来的int值

void harshcode();

同一个对象多次调用哈希是相同的

==哈希值又可能会相同(重地和通话)==

==没有Get方法==

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
public class Test03 {
public static void main(String[] args) {
String d1="NAME";
String d2="NAME";
String d3="name";
System.out.println(d1.hashCode());
System.out.println(d2.hashCode());
System.out.println(d3.hashCode());
System.out.println("重地".hashCode());
System.out.println("通话".hashCode());
}
}
2388619
2388619
3373707
1179395
1179395
1
2
3
4
5
6
7
8
9
10
11
public class Test03 {
public static void main(String[] args) {
Set<String> str = new HashSet<>();
str.add("sD ADA");
str.add("ss");
str.add("ss");
str.add("ad ed adawzda");
System.out.println(str);
}
}
//[ss, ad ed adawzda, sD ADA]
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
public class Student {
private String name;
private int age;

public Student() {
}

public Student(String name, int age) {
this.name = name;
this.age = age;
}

public String getName() {
return name;
}

public void setName(String name) {
this.name = name;
}
//内容一样就一样(不判地址值)
@Override
public boolean equals(Object o) {
//判断是不是一个对象
if (this == o) return true;
//判断是否为null
if (!(o instanceof Student)) return false;
Student student = (Student) o;
return getAge() == student.getAge() && Objects.equals(getName(), student.getName());
}
@Override
public int hashCode() {
return Objects.hash(getName(), getAge());
//name,及age传入,即name,age哈希值相同即是相同
}

public int getAge() {
return age;
}

public void setAge(int age) {
this.age = age;
}

@Override
public String toString() {
return "Student{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
public class Test03 {
public static void main(String[] args) {
HashSet<Student> st = new HashSet<>();
Student l1 = new Student("luhao", 19);
Student l2 = new Student("luhao", 19);
Student l3 = new Student("lianghe", 19);
st.add(l1);
st.add(l2);
st.add(l3);

System.out.println(l1.hashCode());
//l1与l2哈希值相同
System.out.println(l2.hashCode());
System.out.println(l3.hashCode());
System.out.println(st);
}
}
-1091771129
-1091771129
825348634
[Student{name='luhao', age=19}, Student{name='lianghe', age=19}]

==Set集合去重原因==:先判断哈希值,再判断equals

6. LIst

List:与ArrayList差不多,ArrayList有LIst的方法

6.1 ==并发修改异常==

同时在前进,同时在删除

==不能用list.remove(“JAVA”);==

增强for和lambda出bug

普通for会漏删(修改:倒删,或正删完-1)

对迭代器删除进行修改如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
public class Test02 {
public static void main(String[] args) {
List<String> list = new ArrayList<>();
list.add("heima");
list.add("JAVA");
list.add("JAVA");
list.add("JAVA");
list.add("true");
list.add("FALSE");
Iterator<String> it = list.iterator();
while (it.hasNext()){
String next = it.next();
if (next.equals("JAVA")){
it.remove();
}
}
System.out.println(list);
}
}

6.2 ArrayList<>

原理:在第一次添加元素时,创建了一个默认长度为10的数组

==查询快,增删慢==

==Collection不可以用普通for遍历,ArrayList可以==

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
ArrayList<String> ste = new ArrayList<>();
ste.add("1");
ste.add("S");
ste.add("ss");
ste.add(2,"SSS")
ste.add("JAVA");//{1,s,ss,JAVA}
ste.remove(1);//{1,SS,JAVA}
ste.remove("1");//{SS,JAVA}//不会删掉1,因为没有
sout(ste.remove(1));
//返回被删除元素
sout(ste.get(1));
//得到元素
System.out.println(ste.remove("ss"));
ste.set(0,"java");//{JAVA}
System.out.println(ste);"java"

6.3 LinkedList

==查询慢,首尾操作快==,双链表

push=addFirst(压栈,入栈)

pop=removeFirst(弹栈,出栈)

offerLast=addLast(入列)

(出列)

6.4 Arrays

  • 对分查找
  • toString
  • sort排序
1
2
3
4
5
6
7
8
9
10
11
public static void main(String[] args) {
int arr[]={10,2,55,76,99,65};
System.out.println(arr);
System.out.println(Arrays.toString(arr));
Arrays.sort(arr);
System.out.println(Arrays.toString(arr));
//对分查找 未找到结果为-X-1;
int i = Arrays.binarySearch(arr, 2);
System.out.println(i);
System.out.println(Arrays.binarySearch(arr,33));
}

自定义比较器对象实现降序排序

==左边数大,返回正数==,升序

==右边数大,返回负数==,降序

==相等为0==

1
2
3
4
5
6
7
8
9
10
public static void main(String[] args) {
Integer[] arr={10,2,55,76,99,65};
Arrays.sort(arr, new Comparator<Integer>() {
@Override
public int compare(Integer o1, Integer o2) {
return o2-o1;
}
});
System.out.println(Arrays.toString(arr));
}
1
[99, 76, 65, 55, 10, 2]

换成对象:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
public class Test02 {
public static void main(String[] args) {
Student[] students = new Student[3];
students[0] = new Student("LUHAO", 19);
students[1] = new Student("lianghe", 18);
students[2] = new Student("ZCY", 17);
Arrays.sort(students, new Comparator<Student>() {
@Override
public int compare(Student o1, Student o2) {
int num= o1.getAge()- o2.getAge();
return num==0?o1.getName().compareTo(o2.getName()):num;
}
});
System.out.println(Arrays.toString(students));
}
}
//[Student{name='ZCY', age=17}, Student{name='lianghe', age=18}, Student{name='LUHAO', age=19}]

十二、Java高级

1.注解

屏幕截图 2022-01-14 223603

1.1 自定义注解

屏幕截图 2022-01-14 223702

屏幕截图 2022-01-14 223928

1
2
3
4
5
public @interface MyCX {
// public String name();public可省略
String name();
String value();
}
1
2
3
4
public @interface MyAnnot {
String value();
int price() default 10;
}
1
2
3
public @interface MyAnno {
String value();
}
1
2
3
4
5
6
7
8
@MyAnno("1")//此时可省略
@MyAnnot("1")
public class W1 {
@MyCX(name = "a",value = "2")//此时value不可省略
public static void main(String[] args) {

}
}

1.2 元注解

屏幕截图 2022-01-14 230541

屏幕截图 2022-01-14 230914

1
2
3
4
5
6
7
@Target({ElementType.METHOD,ElementType.FIELD})//表示只能注解方法和成员变量
@Retention(RetentionPolicy.RUNTIME)//一直活着,生命周期
public @interface MyCX {
// public String name();public可省略
String name();
String value();
}

1.3 注解的解析

屏幕截图 2022-01-15 103934

屏幕截图 2022-01-15 104127

屏幕截图 2022-01-15 104155

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
public class W2 {
@Test
public void Test01(){
Class<Book> BC = Book.class;
if (BC.isAnnotationPresent(Mybook.class)){
//如果存在此注解,直接获取
Mybook dc = BC.getDeclaredAnnotation(Mybook.class);
System.out.println(Arrays.toString(dc.authors()));
System.out.println(dc.book());
System.out.println(dc.value());
}
}
@Test
public void Test02() throws Exception{
Class<Book> BC = Book.class;
Method m = BC.getDeclaredMethod("books");
if (m.isAnnotationPresent(Mybook.class)){
//如果存在此注解,直接获取
Mybook dc = BC.getDeclaredAnnotation(Mybook.class);
System.out.println(Arrays.toString(dc.authors()));
System.out.println(dc.book());
System.out.println(dc.value());
}
}
}
@Mybook(book = "《龙族》",value = 25.0,authors = {"江南","卢浩"})
class Book{
@Mybook(book = "《三少爷的剑》",value = 20,authors = {"古龙","熊耀华"})
public void books(){}
}
1
2
3
4
5
6
[江南, 卢浩]
《龙族》
25.0
[江南, 卢浩]
《龙族》
25.0
1
2
3
4
5
6
7
@Target({ElementType.METHOD,ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
public @interface Mybook {
String book();
double value() default 100;
String[] authors();
}
1.3.1 案例

屏幕截图 2022-01-15 112348

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
public class W3 {
@Test
public void test1(){
System.out.println("test1");
}
public void test2(){
System.out.println("test2");
}
@Test
public void test3(){
System.out.println("test3");
}
//要求只运行有注解的程序
public static void main(String[] args) throws Exception {
W3 w3 = new W3();
Class<W3> wc = W3.class;
Method[] dm = wc.getDeclaredMethods();
for (Method method : dm) {
if (method.isAnnotationPresent(Test.class)){
method.invoke(w3);
}
}
}
}

1.4Junit注解测试

屏幕截图 2022-01-14 135709

屏幕截图 2022-01-14 135842

屏幕截图 2022-01-14 140147

![屏幕截图 2022-01-14 142224](C:\Users\soul\Desktop\Markdown\JavaSE图片\屏幕截图 2022-01-14 142224.png)

断言:要有返回值

屏幕截图 2022-01-14 142523

屏幕截图 2022-01-14 142603

2.==反射==

屏幕截图 2022-01-14 143234

class本身是个类,是个类 类型的,是类对象而不是类的对象.

类对象应该指类的Class对象,也就是==字节码对象==可以通过Class.forName()/getclass()/.class来获取,当jvm加载一个类时就会为这个类创建一个Class对象;calss.xx人类(人类不会灭绝,即使一个人对象死亡,new的一个消失,而字节码不会消失)

类的对象,通常就是指我们通过new这个类或者反射得到Class对象再调用newInstance()创建的对象,存在内存的堆中,也叫类的实例;new class 人

2.1 获取class类的对象

屏幕截图 2022-01-14 144420

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
public class P1 {
public static void main(String[] args) throws Exception {
//1.Class类中的一个静态方法
Class<?> cl = Class.forName("heimaSe.Demo04.A2.Student");
System.out.println(cl);
//2.类名.class
Class<Student> sc = Student.class;
System.out.println(sc);
//3.对象.getClass,获取对象的class类
Student st = new Student();
Class<? extends Student> cla = st.getClass();
System.out.println(cla);
}
}
class heimaSe.Demo04.A2.Student

2.2 获取构造器

屏幕截图 2022-01-14 145036

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
public class P2 {
@Test
public void getConstructors(){
Class<Student> stc1 = Student.class;
Constructor<?>[] cs = stc1.getConstructors();
for (Constructor<?> c : cs) {
System.out.println(c.getName()+" "+c.getParameterCount());
}
}
//getParameterCount得到参数个数
@Test
public void getDeclaredConstructors(){
Class<Student> stc1 = Student.class;
Constructor<?>[] cs = stc1.getDeclaredConstructors();
for (Constructor<?> c : cs) {
System.out.println(c.getName()+" "+c.getParameterCount());
}
}
@Test
public void getConstructor() throws Exception{
//得到无参构造器
Class<Student> stc1 = Student.class;
Constructor<Student> c = stc1.getConstructor();//这里将 无参构造器改为public
System.out.println(c.getName()+c.getParameterCount());
}
@Test
public void getDeclaredConstructor() throws Exception{
Class<Student> stc1 = Student.class;
Constructor<Student> c = stc1.getDeclaredConstructor(String.class,int.class);
System.out.println(c.getName()+c.getParameterCount());
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
public class Student {
private String name;
private int age;
private Student() {
System.out.println("私有无参构造器执行");
}
public Student(String name, int age) {
this.name = name;
this.age = age;
}
public String getName() {return name;}
public void setName(String name) {this.name = name;}
public int getAge() {return age;}
public void setAge(int age) {this.age = age;}
}

2.3 Class创建对象

屏幕截图 2022-01-14 171254

如果私有只能暴力反射(getDeclaredConstructor)

1
2
3
4
5
6
7
8
9
10
11
public class P3 {
public static void main(String[] args) throws Exception{
Class<Student> stc1 = Student.class;
Constructor<Student> c = stc1.getDeclaredConstructor();
c.setAccessible(true);
//打开权限,如果是getConstructor则不能暴力反射打开权限,因为他只能得到public
Student student = c.newInstance();
Student L1 = stc1.getDeclaredConstructor(String.class, int.class).newInstance("luhao", 19);
System.out.println(student);
}
}

2.4 获取Field(成员变量)

屏幕截图 2022-01-14 172952

set,get取值赋值

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
public class P4 {
public static void main(String[] args) throws Exception{
Class<Student> st = Student.class;
Field[] df = st.getDeclaredFields();
for (Field field : df) {
System.out.println(field.getName()+" "+field.getType());
}
System.out.println("------------");
Field name = st.getDeclaredField("name");
name.setAccessible(true);
Student stc = new Student();
name.set(stc,"luhao");
System.out.println(name.get(stc));
}
}

2.5 获取方法

屏幕截图 2022-01-14 174017

屏幕截图 2022-01-14 174241

1
2
3
4
5
6
7
8
9
10
11
public class P5 {
public static void main(String[] args) throws Exception{
Class<Student> st = Student.class;
Method[] methods = st.getMethods();
for (Method method : methods) {
System.out.println(method);
}
//包括了其父类Object类的方法

}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
public class P5 {
public static void main(String[] args) throws Exception{
Class<Student> st = Student.class;
Method eat = st.getDeclaredMethod("eat");
Method eat1 = st.getDeclaredMethod("eat",String.class);
eat.setAccessible(true);
eat1.setAccessible(true);
Student student = new Student();
Object invoke = eat.invoke(student);
System.out.println(invoke);
//没有返回值则 null
Object shi = eat1.invoke(student, "shi");
System.out.println(shi);
}
}

2.6 反射的作用

2.6.1.越过泛型添加数据

屏幕截图 2022-01-14 182408

编译成class文件泛型会自动擦除,因为在底层ArrayList没有泛型

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
public class P6 {
public static void main(String[] args) throws Exception{
ArrayList<String> list1 = new ArrayList<>();
ArrayList<Integer> list2 = new ArrayList<>();
Class<? extends ArrayList> AC1 = list1.getClass();
Class<? extends ArrayList> AC2 = list2.getClass();
System.out.println(AC1==AC2);
//表面底层都是ArrayList
System.out.println("---------------");
ArrayList<Integer> list = new ArrayList<>();
list.add(1);
list.add(3);
Class<? extends ArrayList> ac = list.getClass();
Method add = ac.getDeclaredMethod("add", Object.class);
add.invoke(list, "黑马");
System.out.println(list);
}
}
true
---------------
[1, 3, 黑马]

更简单方式:

1
2
3
4
5
6
7
public class P6 {
public static void main(String[] args) throws Exception{
ArrayList list = new ArrayList();
list.add(1);
list.add("2");
}
}
2.6.2 通过框架的底层原理

屏幕截图 2022-01-14 184527

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
public class Student {
private String name;
private int age;
private char sex;
private String className;
private String hobby;
public Student() {
}
public Student(String name, int age, char sex, String className, String hobby) {
this.name = name;
this.age = age;
this.sex = sex;
this.className = className;
this.hobby = hobby;
}
public String getName() {return name;}
public void setName(String name) {this.name = name;}
public int getAge() {return age;}
public void setAge(int age) {this.age = age;}
public char getSex() {return sex;}
public void setSex(char sex) {this.sex = sex;}
public String getClassName() {return className;}
public void setClassName(String className) {this.className = className;}
public String getHobby() {return hobby;}
public void setHobby(String hobby) {this.hobby = hobby;}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
public class Teacher {
private String name;
private char sex;
private int salary;
public Teacher() {}
public Teacher(String name, char sex, int salary) {
this.name = name;
this.sex = sex;
this.salary = salary;
}
public String getName() {return name;}
public void setName(String name) {this.name = name;}
public char getSex() {return sex;}
public void setSex(char sex) {this.sex = sex;}
public int getSalary() {return salary;}
public void setSalary(int salary) {this.salary = salary;}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
public class sendToTXT {
public static void sendmessage(Object objects){
try (
PrintStream ps= new PrintStream(new FileOutputStream("Date.txt",true));
){
Class ac = objects.getClass();
ps.println("======================="+ac.getSimpleName()+"=========================");
//getSimpleName获取当前类名,getName获取全限名包名+类名
Field[] df = ac.getDeclaredFields();
for (Field field : df) {
field.setAccessible(true);
String name = field.getName();
String value = field.get(objects)+" ";
ps.println(name+" "+value);
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
1
2
3
4
5
6
7
8
public class P7 {
public static void main(String[] args) {
Student st = new Student("luhao",19,'男',"电商5班","乒乓球");
sendToTXT.sendmessage(st);
Teacher teacher = new Teacher("xxx", '女', 5000);
sendToTXT.sendmessage(teacher);
}
}
1
2
3
4
5
6
7
8
9
10
=======================Student=========================
name luhao
age 19
sex 男
className 电商5班
hobby 乒乓球
=======================Teacher=========================
name xxx
sex 女
salary 5000

3.动态代理

可以理解为拦截下来先做一些业务

3.1 原

屏幕截图 2022-01-15 115310

![屏幕截图 2022-01-15 120100](C:\Users\soul\Desktop\Markdown\JavaSE图片\屏幕截图 2022-01-15 120100.png)

1
2
3
4
5
6
7
8
public class Mainn {
public static void main(String[] args) {
UserService usi = new UserServiceIMP();
usi.login("admin","123456");
System.out.println(usi.deleteUser());
usi.selectUser();
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
public class UserServiceIMP implements UserService{
@Override
public String login(String name, String password) {
long startTime=System.currentTimeMillis();
try {
Thread.sleep(2000);
if (name.equals("admin") && password.equals("123456")) {
return "登陆成功";
}
return "登陆失败";
}catch (Exception e){
e.printStackTrace();
return "Error";
} finally {
long endTime=System.currentTimeMillis();
System.out.println("登录耗时: "+(endTime-startTime)/1000.0+"s");
//注意除以1000.0
}
}
@Override
public void selectUser() {
long startTime=System.currentTimeMillis();
try {
Thread.sleep(1000);
} catch (Exception e) {
e.printStackTrace();
}
System.out.println("删除了100个用户");
long endTime=System.currentTimeMillis();
System.out.println("select共耗时"+(endTime-startTime)/1000.0+"s");
}
@Override
public boolean deleteUser() {
long startTime=System.currentTimeMillis();
try {
System.out.println("删除了100个用户");
Thread.sleep(1000);
return true;
} catch (Exception e) {
e.printStackTrace();
return false;
}finally {
long endTime=System.currentTimeMillis();
System.out.println("delete共耗时"+(endTime-startTime)/1000.0+"s");
}
}
}
1
2
3
4
5
public interface UserService {
String login(String name,String password);
void selectUser();
boolean deleteUser();
}

3.2 ==动态代理处理==

加新方法也可以触发代理自动

1
2
3
4
5
public interface UserService {
String login(String name,String password);
void selectUser();
boolean deleteUser();
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
public class UserServiceIMP implements UserService{
@Override
public String login(String name, String password) {
try {
Thread.sleep(2000);
} catch (Exception e) {
e.printStackTrace();
}
if (name.equals("admin") && password.equals("123456")) {
return "登陆成功";
}
return "登陆失败";
}
@Override
public void selectUser() {
try {
Thread.sleep(1000);
} catch (Exception e) {
e.printStackTrace();
}
System.out.println("删除了100个用户");
}
@Override
public boolean deleteUser() {
System.out.println("删除了100个用户");
try {
Thread.sleep(1000);
return true;
} catch (Exception e) {
e.printStackTrace();
return false;
}

}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
//public static Object newProxyInstance​(ClassLoader loader,
// Class<?>[] interfaces,
// InvocationHandler h)
//参数一:类加载器,负责加载代理类到内存中去(代理类)
//参数二:获取被代理对象实现的全部接口
//参数三:代理的核心处理逻辑(干活)
public class ProxyUtil {
public static UserService getProxy(UserService obj) {
//代理类型一定是跟业务类型相同的,因此下面返回的是UserService类型,默认返回的是object类型
return (UserService) Proxy.newProxyInstance(obj.getClass().getClassLoader(), obj.getClass().getInterfaces(),
new InvocationHandler() {
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
/**
* 参数一:代理对象本身
* 参数二:正在被代理的方法(真正要调用的方法)
* 参数三:被代理方法传入的传输,没有则null(如login里的"admin","123456")
*/
long startTime=System.currentTimeMillis();
//马上触发方法的真正执行
Object ob = method.invoke(obj, args);
//要收结果,因为有些方法有输出结果
long endTime=System.currentTimeMillis();
System.out.println(method.getName()+"耗时: "+(endTime-startTime)/1000.0+"s");
return ob;
}
});
}
}
1
2
3
4
5
6
7
8
9
10
public class Mainn {
public static void main(String[] args) {
//1.把业务类型直接做成一个代理类型返回,代理对象的类型也是UserService类型
UserService usi = ProxyUtil.getProxy( new UserServiceIMP());
//先走代理,再进行业务处理
usi.login("admin","123456");
System.out.println(usi.deleteUser());
usi.selectUser();
}
}

3.3泛型改进

任何代码都可以用该代理

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
public class ProxyUtil {
public static <T>T getProxy(T obj) {
//代理类型一定是跟业务类型相同的,因此下面返回的是UserService类型,默认返回的是object类型
return (T) Proxy.newProxyInstance(obj.getClass().getClassLoader(), obj.getClass().getInterfaces(),
new InvocationHandler() {
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
/**
* 参数一:代理对象本身
* 参数二:正在被代理的方法(真正要调用的方法)
* 参数三:被代理方法传入的传输,没有则null(如login里的"admin","123456")
*/
long startTime=System.currentTimeMillis();
//马上触发方法的真正执行
Object ob = method.invoke(obj, args);
//要收结果,因为有些方法有输出结果
long endTime=System.currentTimeMillis();
System.out.println(method.getName()+"耗时: "+(endTime-startTime)/1000.0+"s");
return ob;
}
});
}
}

屏幕截图 2022-01-15 140004

4.XML

屏幕截图 2022-01-15 155301

屏幕截图 2022-01-15 155404

屏幕截图 2022-01-15 155454

屏幕截图 2022-01-15 155626

屏幕截图 2022-01-15 155742

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
<?xml version="1.0" encoding="UTF-8" ?>
<!--注释:根标签有且只能有一个-->
<Student>
<name></name>
<location>
<room>
<Sex></Sex>
</room>
</location>
<sql>
select * from user where age &lt; 18
select * from user where age &lt; &amp;&amp; >18
<![CDATA[
select * from user where age < 18
]]><!-- 打CD-->
</sql>
</Student>

屏幕截图 2022-01-15 162708

屏幕截图 2022-01-15 163111

4.1 XML文档约束

屏幕截图 2022-01-15 163558

屏幕截图 2022-01-15 163736

1
2
3
4
5
<!ELEMENT 书架 (书+)>
<!ELEMENT 书 (书名,作者,售价)>
<!ELEMENT 书名 (#PCDATA)>
<!ELEMENT 作者 (#PCDATA)>
<!ELEMENT 售价 (#PCDATA)>

Book.xml

1
2
3
4
5
6
7
8
9
10
11
12
13
14
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE 书架 SYSTEM "Date.dtd">
<书架>
<书>
<书名>龙族</书名>
<作者>江南</作者>
<售价>1000</售价>
</书>
<书>
<书名></书名>
<作者></作者>
<售价></售价>
</书>
</书架>

4.2 schema

可以约束类型

屏幕截图 2022-01-15 174149

屏幕截图 2022-01-15 174413

屏幕截图 2022-01-15 174428

4.3 XML解析技术(DOM4J)

屏幕截图 2022-01-15 180221

屏幕截图 2022-01-15 180323

屏幕截图 2022-01-15 180637

屏幕截图 2022-01-15 180734

屏幕截图 2022-01-15 180919

屏幕截图 2022-01-15 181856

屏幕截图 2022-01-15 195619

屏幕截图 2022-01-15 200313

屏幕截图 2022-01-15 195933

屏幕截图 2022-01-15 200024

屏幕截图 2022-01-15 200156

4.5 数据检索技术(Xpath)

屏幕截图 2022-01-15 203719

屏幕截图 2022-01-15 203946

屏幕截图 2022-01-15 204011

屏幕截图 2022-01-15 204148

屏幕截图 2022-01-15 204259

屏幕截图 2022-01-15 204351

屏幕截图 2022-01-15 204415

5.设计模式

见尚硅谷视频,自学

5.1 工厂模式

Buffered不过是为了增强FileInput,FileInput才是最主要的功能

屏幕截图 2022-01-15 205533

比如我们要一台电脑,不是自己生产,而是去购买,电脑对象由工厂生产。

1
2
3
4
5
6
7
8
9
public class Customer {
public static void main(String[] args) {
Computer hw = Factory.produce("HuaWei");
System.out.println(hw.getName());
System.out.println("---------------");
Computer mac = Factory.produce("Mac");
System.out.println(mac.getPrice());
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
public abstract class Computer {
private String name;
private int price;
public abstract void start();
public Computer(String name, int price) {
this.name = name;
this.price = price;
}
public String getName() {return name;}
public void setName(String name) {this.name = name;}
public int getPrice() {return price;}
public void setPrice(int price) {this.price = price;}
}
1
2
3
4
5
6
7
8
9
public class Mac extends Computer{
public Mac(String name, int price) {
super(name, price);
}
@Override
public void start() {
System.out.println("Mac book 启动了");
}
}
1
2
3
4
5
6
7
8
9
10
public class HuaWei extends Computer{
public HuaWei(String name, int price) {
super(name, price);
}

@Override
public void start() {
System.out.println("华为开机了!!");
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
public class Factory {
public static Computer produce(String name){
switch (name){
case "Mac":
Computer mac = new Mac("苹果",9999);
return mac;
case "HuaWei":
Computer huawei=new HuaWei("华为",5555);
return huawei;
default:
return null;
}
}
}

5.2 装饰模式

屏幕截图 2022-01-15 213123

屏幕截图 2022-01-15 213137

屏幕截图 2022-01-15 213213

屏幕截图 2022-01-15 214714

屏幕截图 2022-01-15 214745

十三、JDK8新增日期

1. LocalDate

1
2
3
4
5
6
7
8
LocalDate now = LocalDate.now();
int year=now.getYear();
Month month=now.getMonth();
int monthValue = now.getMonthValue();
System.out.println(month);
System.out.println(monthValue);
System.out.println(now);
System.out.println("--------------");
1
2
3
JANUARY
1
2022-01-04

2. LocalTime

1
2
3
4
5
6
7
8
9
10
11
12
LocalTime now = LocalTime.now();
int hour = now.getHour();
int minute = now.getMinute();
System.out.println(hour);
System.out.println(minute);
System.out.println(now);
System.out.println(LocalTime.of(2,2));
LocalTime now = LocalTime.now();
System.out.println(now.minusMinutes(1));
//一分钟前
System.out.println(now.plusHours(1));
//1小时后
1
2
3
4
5
6
17
41
17:41:13.403692700
02:02
17:45:15.130765600
18:46:15.130765600

3. LocalDateTime

1
2
3
4
5
6
7
public static void main(String[] args) throws ParseException {
LocalDateTime now1 = LocalDateTime.now();
System.out.println(now1);
DayOfWeek dayOfWeek = now1.getDayOfWeek();
System.out.println(dayOfWeek);
System.out.println(LocalDateTime.of(1995,12,8,2,8));
}
1
2
3
2022-01-04T17:43:34.073014400
TUESDAY
1995-12-08T02:08

4.Instance

是JDK8以前的Date

1
2
3
4
5
6
7
public static void main(String[] args) throws ParseException {
Instant now = Instant.now();
System.out.println(now);
Date date =Date.from(now);
System.out.println(date);
//instant=date.toinstant();
}
1
2
2022-01-04T10:58:51.355808300Z
Tue Jan 04 18:58:51 CST 2022

5. DateTimeformatter

6. Period

1
2
3
4
5
6
7
8
9
10
public class Test02 {
public static void main(String[] args) throws ParseException {
LocalDate now = LocalDate.now();

LocalDate of = LocalDate.of(2002, 10, 25);
Period between = Period.between(now, of);
System.out.println(between.getYears());
System.out.println(between.getDays());
}
}
1
2
-19
-10