Files
2026-02-13 23:38:38 +08:00

811 lines
18 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Java
# 面向对象初级部分
### 为什么 非static可以调用static而非static不能调用static
因为在程序创立之初static就跟上面的class一起存在了而非static需要实例化以后才能存在。
## 构造器
```java
public class Person {
int age;
String name;
public Person() {
}
public Person(int age) {
this.age = age;
}
public Person(String name) {
this.name = name;
}
}
```
**1.与类名相同**
**2.没有返回值**
**3.new的本质就是在调用构造方法**
![image-20240903144853276](C:\Users\33882\AppData\Roaming\Typora\typora-user-images\image-20240903144853276.png)
注意:如果建立了有参构造器,像
```java
public Person(String name) {
this.name = name;
}
```
那么在new一个对象的时候就要使用有参的形式比如
```java
Person xm=new Person("xiaoming");
```
要不然就要在类里面,加一个无参构造器
```java
public Person() {}
```
无参构造器的作用:
1.初始化对象的值
## 重写:需要有继承关系,子类重写父类的方法:
1.方法名要相同
2.参数列表必须相同
3.修饰符:范围可以扩大但不能缩小
4.抛出的异常:范围可以缩小不能扩大
## 多态
1.多态是方法的多态,属性没有多态
2.父类和子类要有联系,类型转换异常
3.存在条件:继承关系,方法需要重写,父类引用指向子类对象
注意static属于类不属于实例//final变量//private方法不能多态
### 动态绑定机制***
##
## 关键字
### instanceof
作用就是检测是否具有父子关系
类名 instanceof 类名 结果就是True 和false
### This 与Super
这两个关键词的创建就是为了解决子类全局变量与子类内部变量,以及子类与父类的变量如果相同,该如何区分的问题
this 就是自己super就是父类
基本用法就是 this.XXX 或者Super.XXX
如果父类的父类。。。。也有相同的变量名字,则依照就近原则
Super 也可以直接访问爷类
### ==与equal()的区别
其实都是判断是否相等,一个是数值 equal的相等另一个是地址==的相等
注意object中的equal是重写了==所以有时候也是判断地址
### finlalize(释放资源——》亡语)
就是现在要开始考虑资源的占用率了,不用的资源就要关掉或者删除
这个方法是在object里面的如果不重写的话这B养的万一灭有一点用
woc 换了 被删除了 哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈 不学了 哈哈哈哈哈哈哈哈哈哈哈哈哈
## 可变参数
将参数相同代码实现功能基本相同的函数,用可变参数进行整合
```java
/*这里的参数可以是0-多.把sum看作是数组
可变参数可以是 数组
可变参数可以与其他参数在一起,但是可变参数一定要是在最后
*/
package EXE.Demon04;
public class VarParament {
public static void main(String[] args) {
T t1=new T();
t1.varparament("小明",11,15,15,15,510,5,15,1501,0,99);
}
}
class T {
void varparament(String name,int ... num)
{
int sum=0;
for(int i=0;i<num.length;i++)
{
sum+=num[i];
}
System.out.println("名字"+name+sum);
}
}
```
——————————————————————————————————
## 内部类
两种分类方式
1定义在局部位置上
局部内部类----》有类名
{
定义在外部类的局部位置
1.可以访问外部类的所有成员,包括私有的
2.作用域:仅仅在它的方法或者代码块中
3.访问内部类 直接访问
4.
}
匿名内部类-----》没有类名
2.定义在成员位置上
成员内部类
静态内部内static
## 匿名内部类
简化开发,如果一个类只想用一次 不想再用了, 于是使用这个,就可以只生成一个对象
类名 对象名=new 类名(){ 这里面直接重构 }
编译类型是就类
但是运行类型变成了类$01
## 成员内部类
## 代码块
在一个类里面例如
> ***类的五大成员====属性 方法 构造器 代码块 内部类***
一种构造器的应用
![image-20240909194920061](C:\Users\33882\AppData\Roaming\Typora\typora-user-images\image-20240909194920061.png)
```java
class Person{
//普通代码块
{
一般用来赋初始值
只有创建的时候才会调用
每次建造就会执行一次
}
//静态代码块
static{
只执行一次
第一执行只执行一次
}
//
Person(){
//构造器
}
}
```
在静态代码块/属性与普通代码块/属性的时候
调用的顺序是 父类的静态》子类静态》父类普通》父构造》子类普通》子构 。相同等级按照先后顺序
## 静态导入包
```java
import static java.lang.Math.random;
这样以后的代码就可以不用写Math.random();
就可以直接写random();
有趣的用法
```
## 静态变量(类变量)
静态变量就是类变量 可以让所有的变量共同使用。
所有对象一起使用
如果只有public 没有static 对象不可以使用
## 抽象类abstract
```java
public abstract class Person {
abstract void run();//正确写法
abstract void run(){}//错误写法,抽象类 不能有主体,它的实现是通过继承它的子类来实现的
/*1. 子类继承了Person也需要
2. 一个类只能继承一个抽象类,而一个类却可以实现多个接口
抽象类的存在的意义是什么????
-》就是
*/
}
```
## 重载与重写的区别
![1725531981115](F:\Wechat\WeChat Files\wxid_13iogzk6c5q612\FileStorage\Temp\1725531981115.png)
## 向上转型与向下转型
```java
package EXE.Demon01;
public class Main {
public static void main(String[] args) {
Animal cat = new Cat();
}
}
class Animal {
int age;
String name;
void eat() {
System.out.println("eat");
}
void sleep() {
System.out.println("sleep");
}
}
class Cat extends Animal {
Cat() {
}
void run() {
System.out.println("cats run");
}
}
```
就向这样的就是向上转型。
编译类型是Animal 但是数据类型还是Cat
注意
1. 向上转型后,子类单独定义的方法会丢失(父类并不知道子类定义的新属性与方法)
2. 父类引用可以指向子类对象,但是子类引用不能指向父类对象
3. 如果子类中重写了父类的方法,那么调用这个方法的时候,将会调用子类中的方法
4. 访问属性看编译类型,访问方法看运行类型
## 接口
作用:
1.约束
2.定义一些方法,让不同的人实现
3.是个抽象类
4.里面的变量都是public abstract final
5.implements可以实现多个接口
### 接口的多态数组(程序猿们太叼了)
比如一个A B C都是实现了English接口
定义一个English数组那么这个数组就可以放A B C
## 简易计算器
```java
package Calculator;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyAdapter;
public class Main {
public static void main(String[] args) {
new Calculator();
}
}
class Calculator extends Frame {
Calculator() {
TextField tf1 = new TextField(10);
TextField tf2 = new TextField(10);
TextField tf3 = new TextField(20);
Label label = new Label("+");
Button button = new Button("=");
button.addActionListener(new AddActionListener(tf1, tf2, tf3));
setLayout(new FlowLayout());
add(tf1);
add(label);
add(tf2);
add(button);
add(tf3);
setVisible(true);
pack();
}
}
class AddActionListener implements ActionListener {
TextField tf1, tf2, tf3;
AddActionListener(TextField tf1, TextField tf2, TextField tf3) {
this.tf1 = tf1;
this.tf2 = tf2;
this.tf3 = tf3;
}
public void actionPerformed(ActionEvent e) {
int num1 = Integer.parseInt(tf1.getText());
int num2 = Integer.parseInt(tf2.getText());
tf3.setText("" + (num1 + num2));
}
}
```
# 中级部分
## 集合
动态保存任意多个对象
![image-20240919194743834](C:\Users\33882\AppData\Roaming\Typora\typora-user-images\image-20240919194743834.png)
```java
List list =new Arrylist();
//增加
list.add(obj);
//删除
list.remove(0);
删除第0个元素
//查找
list.contains("XXX");
//元素个数
list.size()
//是否为空
list.isEmpty();
//清空
list.clear()
//
```
## List
arrylist
vector
## Set
特点:
1. 存放是无序的,但是取出是固定的
2. 不能存放重复的元素
3. 可以加NULL但是只能一个
4. 对象不能通过索引获取因为没有get方法。 只能用迭代器和for each
5.
### Hashset
1. 是set接口的实现类
2. 实际上是HashMap
3. 红黑树:数组加链表 每个数组里面存放的是头节点节点后面是链表。链表多了链表8个并且数组超过64就会变成树
## Map
1. 存放的是K-V类型 要存入两个 其中是以K来排序 有点像hash
Man的常用方法
1. put
2. remove 根据K删除映射关系
3. get 根据K获取值
4. size
5. isEmpty
6. clear
7. containsKey查找K是否存在
## 泛型
我不知道到底有什么 但是我知道一定有 并且有不止一个数据类型的东西
## 枚举和注解
## paint
```Java
//画圆
//g.drawOval(10, 10, 100, 100);
System.out.println("正在画画~~");
//画直线 drawLine(int x1, int y1, int x2, int y2)
//g.drawLine(10, 10, 100, 100);
//画矩形边框 drawRect(int x, int y, int width, int height)
//g.drawRect(10, 10, 100, 100);
//填充矩形 fillRect(int x, int y, int width, int height)
//g.setColor(Color.BLUE);//设置画笔颜色
//g.fillRect(10, 10, 100, 100);
//填充椭圆 fillOval(int x, int y, int width, int height)
//g.setColor(Color.RED);
//g.fillOval(10, 10, 100, 100);
//画图片 drawImage(Image img, int x, int y, ..)
//1.获取图片资源,/bg.png 表示在该项目的根目录去获取 bg.jpg 图片资源
//Image image = Toolkit.getDefaultToolkit().getImage(Panel.class.getResource("/bg.jpg"));
//g.drawImage(image, 0, 0, 1920, 1200, this);
//画字符串 drawString(String str, int x, int y)
//给画笔设置颜色和字体
//g.setColor(Color.red);
//g.setFont(new Font("隶书", Font.BOLD, 50));
//这里设置的100100是“北京你好”的左下角
//g.drawString("北京你好", 100, 100);
```
## 进程与线程
比如有一个进程 有两个线程 是main 与Cat
main 结束了以后并不会导致进程的结束 要等到 cat结束了以后才能结束进程
进程产生线程 线程依附于进程
如果直接使用run方法而不是start的话 那么其实就是用了一下run方法 只是将他作为一个函数使用 并不会产生线程
线程的入口是run函数 但是run函数其实是调用了start()函数 start函数最终其实是给到的是start0函数 这是最底层的了 而start0是用C/C++写的
![image-20240924214741433](C:\Users\33882\AppData\Roaming\Typora\typora-user-images\image-20240924214741433.png)
#### 关键字synchronized 可以让线程一个个来
```java
package EXE.Thread;
public class SellTick {
public static void main(String[] args) {
Sell sell = new Sell();
new Thread(sell).start();
new Thread(sell).start();
new Thread(sell).start();
}
}
class Sell implements Runnable {
public static int tick = 50;
synchronized void sell() {
if (tick > 0) {
System.out.println(Thread.currentThread().getName() + "当前窗口售票成功,剩余:" + tick);
tick--;
try {
Thread.sleep(500);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
}
}
@Override
public void run() {
while (true) {
sell();
}
}
}
```
```java
package EXE.Thread;
public class SellTick_Thread {
public static void main(String[] args) {
Sell02 sell03 = new Sell02();
Sell02 sell02 = new Sell02();
Sell02 sell01 = new Sell02();
sell03.start();
sell02.start();
sell01.start();
}
}
class Sell02 extends Thread {
public static int tick = 50;
synchronized static void sell() {
if (tick > 0) {
System.out.println(Thread.currentThread().getName() + "当前窗口售票成功,剩余:" + tick);
tick--;
try {
Thread.sleep(500);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
}
}
@Override
public void run() {
while (true) {
sell();
}
}
}
```
## 互斥锁
不知道,等一下查一下吧
## 死锁
## 异常体系图
## 鼠标监听
## 窗口监听
## 键盘监听
## 设计模式
### 单例设计模式
#### 饿汉式
```java
/*
将构造器私有化
在类里面直接调用对象 用static
写一个public static的函数来返回对象
*/
package EXE.Static;
public class Main {
public static void main(String[] args) {
A c=A.getA();
}
}
class A {
int n;
private static A a = new A(55);
private A(int n) {
this.n = n;
}
public static A getA() {
return a;
}
}
```
为什么要用这个,
1.为了让一个类只能产生一个对象。
比如如果有一个类,他是个重要的核心,占用资源很高,所以不能执行多次,只能执行一次
**是在类加载的时候 就创建了对象的实例**
**不存在线程安全问题**
**可能会浪费对象,因为已经创建了**
#### 懒汉式
```java
package EXE.Static;
public class Main {
public static void main(String[] args) {
}
static class A {
public static int n;
private static A a;//默认是null
private A(int n) {
this.n = n;
}
public static A getA() {
if (a == null) {
a= new A(5);
}
return a;
}
}
}
```
**是在类加载的时候就创建了对象的实例**
存在线程安全问题
## I/O流
![image-20241010214035229](C:\Users\33882\AppData\Roaming\Typora\typora-user-images\image-20241010214035229.png)
![image-20241010220227289](C:\Users\33882\AppData\Roaming\Typora\typora-user-images\image-20241010220227289.png)
### 序列化
你看啊 这个 数据可以存储在文件里 那么 对象可不可以呢??
就是序列化 需要对象 继承seriable
### 流
字符流 字节流 输入流 输出流 节点流
### 读入 文件转换乱码问题
![image-20241012181645248](C:\Users\33882\AppData\Roaming\Typora\typora-user-images\image-20241012181645248.png)
# 网络
## socket
就像一个口 所有的链接的数据传送 都是通过这个口来实现的
口来负责两个服务器的链接
如何确定是哪两台服务器——》通过 ip以及端口
注意流要关闭 不然会造成资源浪费
```java
package Int.PJ1;
import java.io.IOException;
import java.io.InputStream;
import java.net.ServerSocket;
import java.net.Socket;
import java.security.Provider;
public class Ser {
public static void main(String[] args) throws IOException {
//建立端口的
ServerSocket serverSocket = new ServerSocket(8888);
//如果又socket的请求 便会创建一个socket 来接受 返回一个socket
Socket socket = serverSocket.accept();
System.out.println("服务器" + socket.getClass());
InputStream inputStream = socket.getInputStream();
byte[] buffer = new byte[1024];
int len = 0;
while((len=inputStream.read())!=-1){
System.out.print((char)len);
}
serverSocket.close();
inputStream.close();
socket.close();
}
}
fu'wu
```
```java
package Int.PJ1;
import java.io.OutputStream;
import java.net.InetAddress;
import java.net.Socket;
public class Cil {
public static void main(String[] args) throws Exception {
//通过ip 以及端口来获取是哪一个
Socket socket = new Socket(InetAddress.getLocalHost(), 8888);
System.out.println("客户端链接:"+socket.getClass());
//用OutputStream流 来连接上socket的流
OutputStream out = socket.getOutputStream();
out.write("999".getBytes());
out.close();
socket.close();
}
}
用户端
```
```java
BufferedWriter bufferedWriter = new BufferedWriter(new OutputStreamWriter(outputStream));
解读 为了使用字符流输入 但是BufferedWriter只能接受Write类 于是就需要转换来把outputStream通过new OutputStreamWriter()来转换成
```
```java
BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(inputStream));
同理
```
小秘密:当客户端与服务端链接的时候 虽然看似是客户端找到了服务端的端口 客户端似乎是没有端口 其实客户端也是会产生临时端口
# 反射
反射机示意图
![image-20241020185741522](C:\Users\33882\AppData\Roaming\Typora\typora-user-images\image-20241020185741522.png)
吊的地方就是可用通过配置文件来在不修改源码的情况下 使用不同的东西
![image-20241021233817199](C:\Users\33882\AppData\Roaming\Typora\typora-user-images\image-20241021233817199.png)
![image-20241021234048064](C:\Users\33882\AppData\Roaming\Typora\typora-user-images\image-20241021234048064.png)