My Java
文章目录
注:swing组件之后的知识
一. 面向对象基础
-
override-重写-覆盖: 子类重新定义继承下来的方法
-
对象包含:实例变量 方法
-
对象引用 Dog myDog
- 这其实是定义的“引用变量”,和指针类似
- 若= new Dog(),这才是创建对象
-
垃圾回收
- 因为myDog是指针,所以如果myDog置为null,或者myDog指向其他对象
- 那么就没有人去指向刚new出来的空间,那么这个空间是无意义的,就会被回收
-
对象数组:
- Dog[] dog; 声明一个Dog数组变量
-
dog = new Dog[7]; 创建Dog数组,现在dog里是7个引用变量
- dog[0] = new Dog(); 但是需要Dog对象
-
== :
- 基类型是否相同
- 两个引用是否指向同一对象
二. swing编程
1. AWT组件和布局
1.1 Panel
所有的组件都依附于窗体Frame
Panel也是一个容器,但是它不能单独存在,只能存在其他容器(Window或其子类)中,一个Panel对象代表了一个长方形的区域,在这个区域中可以容纳其他组件。在程序中通常会使用Panel来实现一些特殊的布局。
import java.awt.*;
import java.util.ArrayList;
public class Test {
public static void main(String[] args) {
Frame f = new Frame("我的窗体!"); // 建立新窗体对象
f.setSize(400, 300); // 设置窗体的宽和高
// 设置窗体在屏幕中所处的位置(参数是左上角坐标)
f.setLocation(300, 200);
Panel panel = new Panel();
// 可以用这个方法直接加入到panel
panel.add(new Button("666"));
f.add(panel);
f.setVisible(true); // 设置窗体可见
}
}
1.2 布局管理器
java.awt包中提供了五种布局管理器,分别是FlowLayout(流式布局管理器)、BorderLayout(边界布局管理器)、GridLayout(网格布局管理器)、GridBagLayout(网格包布局管理器)和CardLayout(卡片布局管理器)。
1.2.1FlowLayout(流式布局管理器)
容器会将组件按照添加顺序从左向右放置。当到达容器的边界时,会自动将组件放到下一行的开始位置。这些组件可以左对齐、居中对齐(默认方式)或右对齐的方式排列。FlowLayout对象有三个构造方法
左对齐 | FlowLayout.LEFT |
---|---|
右对齐 | FlowLayout.RIGHT |
居中对齐 | FlowLayout.CENTER |
hgap和vgap | 设定组件之间的水平和垂直间隙,可以填入一个任意数值。 |
package Study;
import java.awt.*;
import java.util.ArrayList;
public class Test {
public static void main(String[] args) {
Frame f = new Frame("我的窗体!"); // 建立新窗体对象
// 设置窗体中的布局管理器为FlowLayout,所有组件左对齐,每个组件之间水平间距为20,垂直间距为30
f.setLayout(new FlowLayout(FlowLayout.LEFT,20,30));
f.setSize(400, 300);
f.setLocation(300, 200);
f.add(new Button("第1个按钮")); // 把"第1个按钮"添加到f窗口
f.add(new Button("第2个按钮"));
f.add(new Button("第3个按钮"));
f.add(new Button("第4个按钮"));
f.add(new Button("第5个按钮"));
f.add(new Button("第6个按钮"));
f.setVisible(true); // 设置窗体可见
}
}
1.2.2 BorderLayout(边界布局管理器)
将容器划分为五个区域,分别是东(EAST)、南(SOUTH)、西(WEST)、北(NORTH)、中(CENTER)。组件可以被放置在这五个区域中的任意一个。
可以再每个小区域加入Panel作为中间容易,再进行添加等操作。Panel里也能设置边界布局
调整方案 |
---|
NORTH和SOUTH区域高度不变长度调整 |
WEST和EAST区域宽度不变高度调整 |
CENTER会相应进行调整 |
package Study;
import java.awt.*;
public class Test {
public static void main(String[] args) {
final Frame f = new Frame("BorderLayout");// 创建一个名为BorderLayout的窗体
f.setLayout(new BorderLayout()); // 设置窗体中的布局管理器为BorderLayout
f.setSize(300, 300); // 设置窗体大小
f.setLocation(300, 200);// 设置窗体显示的位置
f.setVisible(true); // 设置窗体可见
// 下面的代码是创建5个按钮,分别用于填充BorderLayout的5个区域
Button but1 = new Button("东部"); // 创建新按钮
Button but2 = new Button("西部");
Button but3 = new Button("南部");
Button but4 = new Button("北部");
Button but5 = new Button("中部");
// 下面的代码是将创建好的按钮添加到窗体中,并设置按钮所在的区域
f.add(but1, BorderLayout.EAST); // 设置按钮所在区域
f.add(but2, BorderLayout.WEST);
f.add(but3, BorderLayout.SOUTH);
f.add(but4, BorderLayout.NORTH);
f.add(but5, BorderLayout.CENTER);
}
}
1.2.3 GridLayout(网格布局管理器)
使用纵横线将容器分成n行m列大小相等的网格,每个网格中放置一个组件。添加到容器中的组件首先放置在第1行第1列(左上角)的网格中,然后在第1行的网格中从左向右依次放置其他组件,行满后,继续在下一行中从左到右放置组件。与FlowLayout不同的是,放置在GridLayout布局管理器中的组件将自动占据网格的整个区域。
package Study;
import java.awt.*;
public class Test {
public static void main(String[] args) {
Frame f = new Frame("66");
// 设置该窗体为 2 * 4 的网格
f.setLayout(new GridLayout(2,4));
f.setSize(400,300);
f.setLocation(400, 300);
for(int i =0;i < 8;i++){
Button btn = new Button("btn" + (i + 1));
f.add(btn);
}
f.setVisible(true);
}
}
是最灵活、最复杂的布局管理器。
它允许网格中的组件大小各不相同,而且允许一个组件跨越一个或者多个网格。
步骤:
- 创建GridbagLayout布局管理器,并使容器采用该布局管理器
- 创建GridBagContraints对象(布局约束条件),并设置该对象的相关属性
- 调用GridBagLayout对象的setConstraints()方法建立GridBagConstraints对象和受控组件之间的关联
- 向容器中添加组件
ps: GridBagConstraints对象可以重复使用,只需要改变它的属性即可。
f.setLocationRelativeTo(null); // 参数为父容器组件,如果是null的话,为屏幕中心
// 就不需要设置窗体在屏幕的位置
2. 事件处理
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-3LJTS97Y-1607002193352)(https://s3.ax1x.com/2020/11/18/Dmtzi8.png)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-wF3drr6y-1607002193355)(https://s3.ax1x.com/2020/11/18/DmtjdP.png)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-mJzvnZXU-1607002193356)(https://s3.ax1x.com/2020/11/18/DmtvIf.png)]
2.1 窗口关闭:
-
System.exit(0) :直接关闭后台
-
((Window) e.getComponent()).dispose():隐藏至后台
-
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); // 使用JFrame的时候
f.addWindowListener(new WindowAdapter() {
public void windowClosing(WindowEvent e) {
System.out.println("外部关闭");
// System.exit(0);
// f.dispose();
((Window) e.getComponent()).dispose();
}
});
2.2 WindowEvent事件
窗口被激活,图标化,还原,关闭时发生
下面是WindowEvent事件处理所需要的接口和适配器
2.1 接口WindowListener
import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.awt.event.WindowListener;
public class A1 {
public static void main(String[] args) {
Frame f = new Frame("我的窗体!"); // 建立新窗体
f.setSize(400, 300); // 设置窗体的宽和高
f.setLocation(300, 200); // 设置窗体的出现的位置
f.setVisible(true); // 设置窗体可见
MyWindowListener mw = new MyWindowListener(); // 为窗口组件注册监听器
f.addWindowListener(mw); // 为窗口添加窗口监听器
}
}
// 下面可以直接用匿名内部类
// 创建MyWindowListener类实现WindowListener接口
class MyWindowListener implements WindowListener {
// 监听器监听事件对象作出处理
public void windowClosing(WindowEvent e) {
// 窗口正在关闭
System.out.println("正在关闭");
Window window = e.getWindow();
window.setVisible(false); // 先把窗口隐藏
window.dispose(); // 再释放窗口
}
public void windowActivated(WindowEvent e) {
System.out.println("激活窗体");
} // 激活窗口
public void windowClosed(WindowEvent e) {
System.out.println("关闭完成");
} // 窗口关闭完成
public void windowDeactivated(WindowEvent e) {
System.out.println("不是当前活动窗口");
} // 窗口不再是当前的活动窗口
public void windowDeiconified(WindowEvent e) {
System.out.println("窗口从最小化到正常窗口时");
} // 窗口从最小化到正常窗口时
public void windowIconified(WindowEvent e) {
System.out.println("窗口从正常到最小化时");
} // 窗口从正常到最小化时
public void windowOpened(WindowEvent e) {
System.out.println("窗口首次可见");
} // 窗口首次可见
}
2.2 适配器WindowListener
public class Exam09 {
public static void main(String[] args) {
// 建立新窗体
Frame f = new Frame("我的窗体!");
// 设置窗体的宽和高
f.setSize(400, 300);
// 设置窗体的出现的位置
f.setLocation(300, 200);
// 设置窗体可见
f.setVisible(true);
// 为窗口组件注册监听器
f.addWindowListener(new MyWindowListener1());
}
}
// 继承WindowAdapter类,重写windowClosing()方法
class MyWindowListener1 extends WindowAdapter{
public void windowClosing(WindowEvent e) {
Window window = e.getWindow();
window.dispose();
}
}
2.3 MouseEvent
2.3.1 接口MouseListener
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
import java.nio.ByteOrder;
public class A1 {
public static void main(String[] args) {
JFrame f = new JFrame("崇文");
f.setSize(400, 300);
f.setLocationRelativeTo(null);
f.setLayout(new BorderLayout());
JButton b_1 = new JButton("关闭");
JButton b_2 = new JButton("打开");
f.add(b_1, BorderLayout.EAST);
f.add(b_2, BorderLayout.WEST);
b_1.addMouseListener(new MouseListener() {
@Override
public void mouseClicked(MouseEvent e) {
System.out.println("点击");
System.exit(0);
}
@Override
public void mousePressed(MouseEvent e) {
System.out.println("按下");
}
@Override
public void mouseReleased(MouseEvent e) {
System.out.println("鼠标松开事件");
}
@Override
public void mouseEntered(MouseEvent e) {
System.out.println("进入窗口事件");
}
@Override
public void mouseExited(MouseEvent e) {
System.out.println("离开窗口事件");
}
});
f.setVisible(true);
// f.setDefaultCloseOperation();
}
}
2.3.2 适配器MouseAdapter
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
import java.nio.ByteOrder;
public class A1 {
public static void main(String[] args) {
JFrame f = new JFrame("崇文");
f.setSize(400, 300);
f.setLocationRelativeTo(null);
f.setLayout(new BorderLayout());
JButton b_1 = new JButton("关闭");
JButton b_2 = new JButton("打开");
f.add(b_1, BorderLayout.EAST);
f.add(b_2, BorderLayout.WEST);
b_1.addMouseListener(new MouseAdapter() {
@Override
public void mouseClicked(MouseEvent e) {
int cnt = e.getClickCount();
if(e.getButton() == MouseEvent.BUTTON1)
System.out.println("左键:" + cnt + "次");
else if(e.getButton() == MouseEvent.BUTTON2)
System.out.println("中键:" + cnt + "次");
else if(e.getButton() == MouseEvent.BUTTON3)
System.out.println("右键:" + cnt + "次");
System.out.println("基于窗体坐标:" + e.getX() + " " + e.getY());
System.out.println("基于屏幕坐标:" + e.getXOnScreen() + " " + " " + e.getYOnScreen());
}
});
f.setVisible(true);
// f.setDefaultCloseOperation();
}
}
2.4 KeyEvent
文本框组件:JTextField
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
import java.nio.ByteOrder;
public class A1 {
public static void main(String[] args) {
JFrame f = new JFrame("崇文");
f.setSize(400, 300);
f.setLocationRelativeTo(null);
f.setLayout(new FlowLayout(FlowLayout.CENTER));
JTextField jt = new JTextField(25);// 长度
f.add(jt);
// 为文本框添加键盘事件监听器
jt.addKeyListener(new KeyListener() {
@Override
public void keyTyped(KeyEvent e) {
char c = e.getKeyChar();
// System.out.println("正在输入: " + c);
}
@Override
public void keyPressed(KeyEvent e) {
char c = e.getKeyChar();
if (c == '\n')
System.exit(0);
System.out.println("输入的内容为:" + c + " " + "对应的整数值" + e.getKeyCode());
// System.out.println("按下");
}
@Override
public void keyReleased(KeyEvent e) {
// System.out.println("释放");
}
});
f.addWindowListener(new WindowAdapter() {
@Override
public void windowClosing(WindowEvent e) {
System.exit(0);
}
});
f.setVisible(true);
}
}
3. 其他组件
3.1 Dialog
Dialog也是一个窗口,用于弹出。
模式 | 非模式 |
---|---|
dialog.setModal(true); |
dialog.setModal(false); |
下面的程序:
- 把三个按钮加到f
- JLabel看情况加到Dialog里
- 为每个按钮设置事件
- 打开模态窗口
- 打开非模态窗口
- 关闭窗口
需要注意的是:一定要设置Flayout(布局管理器),不然组件会进行覆盖。
JLabel是一个标签,可以显示文本、图像或同时显示二者。
Dialog也可设置大小,位置,布局管理器等。
如果用Dialog,那么关闭也是要自己实现方法的。用JDialog就不用,效果和JFrame一样
import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
public class A1 extends JFrame {
public static void main(String[] args) {
// 建立两个按钮
JButton btn1 = new JButton("模态对话框");
JButton btn2 = new JButton("非模态对话框");
JFrame f = new JFrame("DialogDemo");
f.setSize(300, 250);
f.setLocation(300, 200);
f.setLayout(new FlowLayout()); // 为内容面板设置布局管理器
// 在Container对象上添加按钮
f.add(btn1);
f.add(btn2);
// 设置单击关闭按钮默认关闭窗口
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
f.setVisible(true);
final JLabel label = new JLabel();
final JDialog dialog = new JDialog(f, "Dialog"); // 定义一个JDialog对话框
dialog.setSize(220, 150); // 设置对话框大小
dialog.setLocation(350, 250); // 设置对话框位置
dialog.setLayout(new FlowLayout()); // 设置布局管理器
final JButton btn3 = new JButton("确定"); // 创建按钮对象
dialog.add(btn3); // 在对话框的内容面板添加按钮
// 为"模态对话框"按钮添加单击事件
btn1.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
// 设置对话框为模态
dialog.setModal(true);
// 如果JDialog窗口中没有添加了JLabel标签,就把JLabel标签加上
if (dialog.getComponents().length == 1) {
dialog.add(label);
}
// 否则修改标签的内容
label.setText("模式对话框,点击确定按钮关闭");
// 显示对话框
dialog.setVisible(true);
}
});
// 为"非模态对话框"按钮添加单击事件
btn2.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
// 设置对话框为非模态
dialog.setModal(false);
// 如果JDialog窗口中没有添加了JLabel标签,就把JLabel标签加上
if (dialog.getComponents().length == 1) {
dialog.add(label);
}
// 否则修改标签的内容
label.setText("非模式对话框,点击确定按钮关闭");
// 显示对话框
dialog.setVisible(true);
}
});
// 为对话框中的按钮添加单击事件
btn3.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
dialog.dispose();
}
});
}
}
3.2 JScrollPane
滚动方式:
垂直滚动条 | 水平滚动条 |
---|---|
ScrollPaneConstants.VERTICAL_SCROLLBAR_AS_NEEDED // 需要时显示(默认) | ScrollPaneConstants.HORIZONTAL_SCROLLBAR_AS_NEEDED // 需要时显示(默认) |
ScrollPaneConstants.VERTICAL_SCROLLBAR_NEVER // 从不显示 | ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER // 从不显示 |
ScrollPaneConstants.VERTICAL_SCROLLBAR_ALWAYS // 总是显示 | ScrollPaneConstants.HORIZONTAL_SCROLLBAR_ALWAYS // 总是显示 |
V的是垂直,H的是水平
设置方法:setHorizontalScrollBarPolicy
JScrollPane js = new JScrollPane();
js.setHorizontalScrollBarPolicy(ScrollPaneConstants.HORIZONTAL_SCROLLBAR_AS_NEEDED);
加入的时候:setViewportView
把东西都放在JPanel里,把jPnanel加到js
JPanel p = new JPanel();
p.add(new JButton("1"));
js.setViewportView(p);
import javax.swing.*;
import java.awt.*;
public class A1 extends JFrame {
private static final long serialVersionUID = 1L;
public A1() {
this.setTitle("PanelDemo");
// 创建滚动面板
JScrollPane scrollPane = new JScrollPane();
// 设置水平滚动条策略--滚动条需要时显示
scrollPane.setHorizontalScrollBarPolicy(ScrollPaneConstants.HORIZONTAL_SCROLLBAR_AS_NEEDED);
// 设置垂直滚动条策略--滚动条一直显示
scrollPane.setVerticalScrollBarPolicy(ScrollPaneConstants.VERTICAL_SCROLLBAR_ALWAYS);
// 定义一个JPanel面板
JPanel panel = new JPanel();
// 在JPanel面板中添加四个按钮
panel.add(new JButton("按钮1"));
panel.add(new JButton("按钮2"));
panel.add(new JButton("按钮3"));
panel.add(new JButton("按钮4"));
// 设置JPanel面板在滚动面板中显示
scrollPane.setViewportView(panel);
// 将滚动面板添加到内容面板的CENTER区域
this.add(scrollPane,BorderLayout.CENTER);
// 将一个按钮添加到内容面板的SOUTH区域
this.add(new JButton("11"),BorderLayout.SOUTH);
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
this.setSize(400,250);
this.setVisible(true);
}
public static void main(String[] args) {
new A1();
}
}
3.3 JTextArea
创建:
JTextArea t = new JTextArea(10, 30); // 文本域大小
t.setEditable(false); // 设置文本域不可编辑
- 设置一个panel放到下面,panel中存放
- label提示文字
- JTextField输入框
- JButton发送按钮
- 为按钮和文本框加事件,目的都是把文字发送到JTextArea
- 给JTextArea添加拖动条,(其实是把JTextArea加入到JScrollPane),再把JScrollPane加入到JFrame
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
public class A1 extends JFrame {
private static final long serialVersionUID = 1L;
JButton sendBt;
JTextField inputField;
JTextArea chatContent;
public A1() {
this.setLayout(new BorderLayout());
chatContent = new JTextArea(12, 34); // 创建一个文本域
// 创建一个滚动面板,将文本域作为其显示组件
JScrollPane showPanel = new JScrollPane(chatContent);
chatContent.setEditable(false); // 设置文本域不可编辑
JPanel inputPanel = new JPanel(); // 创建一个JPanel面板
inputField = new JTextField(20); // 创建一个文本框
inputField.addKeyListener(new KeyAdapter() {
@Override
public void keyPressed(KeyEvent e) {
// 如果敲击的是回车
if(e.getKeyCode()==KeyEvent.VK_ENTER) {
sendMsg();
}
}
});
sendBt = new JButton("发送"); // 创建一个发送按钮
// 为按钮添加事件
sendBt.addActionListener(new ActionListener() {
// 为按钮添加一个监听事件
public void actionPerformed(ActionEvent e) {
// 重写actionPerformed方法
sendMsg(); // 发送消息
}
});
JLabel label = new JLabel("聊天信息"); // 创建一个标签
inputPanel.add(label); // 将标签添加到JPanel面板
inputPanel.add(inputField); // 将文本框添加到JPanel面板
inputPanel.add(sendBt); // 将按钮添加到JPanel面板
// 将滚动面板和JPanel面板添加到JFrame窗口
this.add(showPanel, BorderLayout.CENTER);
this.add(inputPanel, BorderLayout.SOUTH);
this.setTitle("聊天窗口");
this.setSize(400, 300);
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
this.setVisible(true);
}
/**
* 发送消息
*/
private void sendMsg() {
String content = inputField.getText(); // 获取输入的文本信息
// 判断输入的信息是否为空
if (content != null && !content.trim().equals("")) {
// 如果不为空,将输入的文本追加到到聊天窗口
chatContent.append("本人:" + content + "\n");
} else {
// 如果为空,提示聊天信息不能为空
chatContent.append("聊天信息不能为空" + "\n");
}
inputField.setText(""); // 将输入的文本域内容置为空
}
public static void main(String[] args) {
new A1();
}
}
3.4 JTextField
3.5 JCheckBox
方法1:看是不是已经按下。
Box_1.isSelected
案例:
- 添加文本标签
- 两个JCheckBox复选框
- 一个事件:判断复选框是不是已经按下了:isSelected
- 按钮就改变文本标签的字体:setFont
3.6 ButtonGroup
ButtonGroup是单选按钮组,作用是把单选按钮联系起来,不需要加入到JFrame。
JRadioButton是单选按钮,靠前者联系起来
ButtonGroup group = new ButtonGroup();
JRadioButton radioButton1 = new JRadioButton("1");
JRadioButton radioButton2 = new JRadioButton("2");
group.add(radioButton1);
group.add(radioButton2);
案例 :
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
public class A1 extends JFrame {
private static final long serialVersionUID = 1L;
private ButtonGroup group; // 单选按钮组对象
private JPanel panel; // JPanel面板放置三个JRadioButton按钮
private JPanel pallet; // JPanel面板作为调色板
public A1() {
pallet = new JPanel();
this.add(pallet, BorderLayout.CENTER); // 将调色板面板放置了CENTER区域
panel = new JPanel();
group = new ButtonGroup();
// 调用addJRadioButton()方法
addJRadioButton("灰");
addJRadioButton("粉");
addJRadioButton("黄");
this.add(panel, BorderLayout.SOUTH);
this.setSize(300, 300);
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
this.setVisible(true);
}
/**
* JRadioButtion按钮的文本信息 用于创建一个带有文本信息的JRadioButton按钮
* 将按钮添加到panel面板和ButtonGroup按钮组中 并添加监听器
*/
private void addJRadioButton(final String text) {
JRadioButton radioButton = new JRadioButton(text);
group.add(radioButton);
panel.add(radioButton);
radioButton.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
Color color = null;
if ("灰".equals(text)) {
color = Color.GRAY;
} else if ("粉".equals(text)) {
color = Color.BLUE;
} else if ("黄".equals(text)) {
color = Color.YELLOW;
} else {
color = Color.WHITE;
}
pallet.setBackground(color);
}
});
}
public static void main(String[] args) {
new A1();
}
}
3.7 JComboBox<>
下拉框
添加方式:
JComboBox<String> comboBox; // 定义一个JComboBox组合框
String[] items = {
"请选择城市", "北京", "天津", "南京", "上海", "重庆"};
comboBox = new JComboBox<String>(items);
或
comboBox.addItem("请选择城市");
comboBox.addItem("北京");
comboBox.addItem("天津");
comboBox.addItem("南京");
comboBox.addItem("上海");
comboBox.addItem("重庆");
事件: 选择:
String item = (String) comboBox.getSelectedItem();
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
public class A1 extends JFrame {
private static final long serialVersionUID = 1L;
private JComboBox<String> comboBox; // 定义一个JComboBox组合框
private JTextField field; // 定义一个JTextField文本框
public A1() {
JPanel panel = new JPanel(); // 创建JPanel面板
String[] items = {
"请选择城市", "北京", "天津", "南京", "上海", "重庆"};
comboBox = new JComboBox<String>(items);
//comboBox = new JComboBox();
// 为组合框添加选项
// comboBox.addItem("请选择城市");
// comboBox.addItem("北京");
// comboBox.addItem("天津");
// comboBox.addItem("南京");
// comboBox.addItem("上海");
// comboBox.addItem("重庆");
// 为组合框添加事件监听器
comboBox.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
String item = (String) comboBox.getSelectedItem();
if ("请选择城市".equals(item)) {
field.setText("");
} else {
field.setText("您选择的城市是:" + item);
}
}
});
field = new JTextField(20);
panel.add(comboBox); // 在面板中添加组合框
panel.add(field); // 在面板中添加文本框
// 在内容面板中添加JPanel面板
this.add(panel, BorderLayout.NORTH);
this.setSize(350, 100);
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
this.setVisible(true);
}
public static void main(String[] args) {
new A1();
}
}
3.8 JMenuBar JMenu JToolBar
JMenuBar 菜单栏
JMenu 菜单
需要把菜单添加到菜单栏,给每一个菜单添加监听器。
JToolBar 工具栏
import javax.swing.JButton;
import javax.swing.JDialog;
import javax.swing.JFrame;
import javax.swing.JMenu;
import javax.swing.JMenuBar;
import javax.swing.JMenuItem;
import javax.swing.JToolBar;
public class A1 extends JFrame {
private static final long serialVersionUID = 1L;
public A1() {
JMenuBar menuBar = new JMenuBar(); // 创建菜单栏
this.setJMenuBar(menuBar); // 将菜单栏添加到JFrame窗口中
JMenu menu = new JMenu("操作"); // 创建菜单
menuBar.add(menu); // 将菜单添加到菜单栏上
// 创建两个菜单项
JMenuItem item1 = new JMenuItem("弹出窗口");
JMenuItem item2 = new JMenuItem("关闭");
// 为菜单项添加事件监听器
item1.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
// 创建一个JDialog窗口
JDialog dialog = new JDialog(A1.this, true);
dialog.setTitle("弹出窗口");
dialog.setSize(200, 200);
dialog.setLocation(50, 50);
dialog.setVisible(true);
}
});
item2.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
System.exit(0);
}
});
menu.add(item1); // 将菜单项添加到菜单中
menu.addSeparator(); // 添加一个分隔符
menu.add(item2);
JToolBar toolBar = new JToolBar();
JButton btn = new JButton("开始");
toolBar.add(btn);
toolBar.addSeparator(); // 分隔符,让中间空隙更大
JButton btn1 = new JButton("结束");
toolBar.add(btn1);
this.add(toolBar, BorderLayout.NORTH);
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
this.setLocationRelativeTo(null);
this.setSize(300, 300);
this.setVisible(true);
}
public static void main(String[] args) {
new A1();
}
}
3.9 JTable
行: Object[] columnTitle = { "姓名", "年龄", "性别" };
列: Object[][] tableDate = { new Object[] { "李清照", 29, "女" }}
添加:table = new JTable(tableDate, columnTitle);
列,行
import javax.swing.JFrame;
import javax.swing.JScrollPane;
import javax.swing.JTable;
/**
* @author Administrator
*
*/
public class Test {
// 创建JFrame窗口
JFrame jf = new JFrame("简单表格");
// 声明JTable类型的变量table
JTable table;
// 1.定义一维数组作为列标题
Object[] columnTitle = {
"姓名", "年龄", "性别" };
// 2.定义二维数组作为表格行对象数据
Object[][] tableDate = {
new Object[] {
"李清照", 29, "女" }, new Object[] {
"苏格拉底", 56, "男" },
new Object[] {
"李白", 35, "男" }, new Object[] {
"弄玉", 18, "女" }, new Object[] {
"虎头", 2, "男" } };
// 3.使用JTable对象创建表格
public void init() {
// 以二维数组和一维数组来创建一个JTable对象
table = new JTable(tableDate, columnTitle);
// 将JTable对象放在JScrollPane中,并将该JScrollPane放在窗口中显示出来
jf.add(new JScrollPane(table));
// 设置自适应JFrame窗体大小
jf.pack();
// 设置单击关闭按钮时默认为退出
jf.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
// 设置窗体可见
jf.setVisible(true);
}
public static void main(String[] args) {
new Test().init();
}
}
4. 杂
4.1 背景图片
ImageIcon imageIcon = new ImageIcon("D:\\临时下载文件夹\\java1.jpg");
JLabel backgread = new JLabel();
backgread.setIcon(imageIcon);
backgread.setBounds(0, 0, imageIcon.getIconWidth(), imageIcon.getIconHeight());
this.getContentPane().add(backgread);
4.2 Toolkit
在使用GUI中的组件进行窗体的设计时,当需要将窗体始终显示在屏幕的某一位置时,例如屏幕的中央。由于不同的电脑屏幕分辨率是不同的,所以在进行处理时会有一定的难度,要用到Tookit工具包。
class Test extends JFrame {
public Test(){
super("张问问");
this.setSize(300, 400);
//创建Toolkit对象
Toolkit t=Toolkit.getDefaultToolkit();
//获取当前屏幕的尺寸
Dimension d=t.getScreenSize();
double width=d.getWidth();//获取屏幕长
double height=d.getHeight();//获取屏幕宽
int x=(int)(width-300)/2;
int y = (int)(height-400)/2;
//设置窗体位置
this.setLocation(x, y);
this.setVisible(true);
}
public static void main(String[] args) {
new Test();
}
}
4.3 对话框组件-JOptionPane
1. 确认对话框
package Study;
import javax.swing.*;
import java.awt.*;
import java.io.*;
import java.net.URL;
class Test extends JFrame {
public Test() {
JOptionPane.showConfirmDialog(this, "问题", "title" ,JOptionPane.YES_NO_CANCEL_OPTION);
// JOptionPane.showConfirmDialog(this, "问题", "title"
// ,2 , 1,icon) ;
JOptionPane.showConfirmDialog(this,"确定要删除吗?","删除提示",0);
JOptionPane.showConfirmDialog(this,"确定要删除吗?","删除提示",1,2);
JOptionPane.showConfirmDialog(this,"确定要删除吗?","删除提示",2,2);
ImageIcon icon = new ImageIcon("a.jpg");
JOptionPane.showConfirmDialog(this,"确定要删除吗?","删除提示",1,1,icon);
}
public static void main(String[] args) {
new Test();
}
}
4.4 设置按钮大小
Dimension Size = new Dimension(150,50);
button.setPreferredSize(Size);
三. 异常处理
基本:
try{
危险动作
} catch(){
解决方法/故障处理
}
使用:
public class Test {
public static void main(String[] args) {
try {
f();
System.out.println("处理了吗");
// 异常代码下方的代码,不会被执行
// 跳过直接去catch
} catch (Exception ex) {
System.out.println("异常");
// ex.printStackTrace(); // 打印出异常信息
}finally {
turnOverOff();
}
// 无论如何, finally 总是会执行,即使try或catch里有return
}
static public int f() {
return 1 / 0;
}
static public void turnOverOff(){
System.out.println("感谢使用");
}
}
Exception的子类
抛出异常时,如果用Exception,他是所有异常的父类,可以捕获所有的异常,即所有的异常都可以被当作Exception处理。
但是最好不要都使用Exception,用他的子类会更加清楚。
异常 | 描述 |
---|---|
ArithmeticException | 当出现异常的运算条件时,抛出此异常。例如,一个整数"除以零"时,抛出此类的一个实例。 |
ArrayIndexOutOfBoundsException | 用非法索引访问数组时抛出的异常。如果索引为负或大于等于数组大小,则该索引为非法索引。 |
ArrayStoreException | 试图将错误类型的对象存储到一个对象数组时抛出的异常。 |
ClassCastException | 当试图将对象强制转换为不是实例的子类时,抛出该异常。 |
IllegalArgumentException | 抛出的异常表明向方法传递了一个不合法或不正确的参数。 |
IllegalMonitorStateException | 抛出的异常表明某一线程已经试图等待对象的监视器,或者试图通知其他正在等待对象的监视器而本身没有指定监视器的线程。 |
IllegalStateException | 在非法或不适当的时间调用方法时产生的信号。换句话说,即 Java 环境或 Java 应用程序没有处于请求操作所要求的适当状态下。 |
IllegalThreadStateException | 线程没有处于请求操作所要求的适当状态时抛出的异常。 |
IndexOutOfBoundsException | 指示某排序索引(例如对数组、字符串或向量的排序)超出范围时抛出。 |
NegativeArraySizeException | 如果应用程序试图创建大小为负的数组,则抛出该异常。 |
NullPointerException | 当应用程序试图在需要对象的地方使用 null 时,抛出该异常 |
NumberFormatException | 当应用程序试图将字符串转换成一种数值类型,但该字符串不能转换为适当格式时,抛出该异常。 |
SecurityException | 由安全管理器抛出的异常,指示存在安全侵犯。 |
StringIndexOutOfBoundsException | 此异常由 String 方法抛出,指示索引或者为负,或者超出字符串的大小。 |
UnsupportedOperationException | 当不支持请求的操作时,抛出该异常。 |
f()方法中有三个异常问题,但是try中只处理一个:f()中第一个发生异常的代码。
Exception的子类有各自处理的范围,如果确定异常的范围,那么就用子类来获取就行。
public class Test {
public static void main(String[] args) {
try {
f();
System.out.println("处理了吗");
}
// 如果在最前面加上这个就错了,Exception会捕获所有的异常
// catch (Exception ex) {
// System.out.println(ex.toString());
// System.out.println("11");
// }
catch (ArrayIndexOutOfBoundsException ex) {
// 处理越界
System.out.println("数组越界");
// ex.printStackTrace(); // 打印出异常信息
} catch (ArithmeticException ex1) {
System.out.println("除数为0");
// ex1.printStackTrace();
} catch (NumberFormatException ex2) {
System.out.println("字符串 " + ex2.toString());
// ex2.printStackTrace();
} finally {
turnOverOff();
}
}
// 里面有三个异常
static public int f() {
int x = Integer.parseInt("121/*/*");
int a[] = new int[10];
a[13] = 1;
return 1 / 0;
}
static public void turnOverOff() {
System.out.println("感谢使用");
}
}
抛出异常
throws: 放在方法名的后面,后面跟着抛出异常的类型
throw: 放在方法的里面,具体的:放在可能会抛出异常的地方,然后实例化即可抛出。
在调用方法的那里,使用try等。
public class Test {
public static void main(String[] args) {
try {
f();
System.out.println("处理了吗");
}catch(ArithmeticException ex){
System.out.println("抛出了异常 " + ex);
// ex.printStackTrace();
}
}
// 里面有三个异常
static public void f() throws ArithmeticException{
System.out.println("11");
throw new ArithmeticException();
}
static public void turnOverOff() {
System.out.println("感谢使用");
}
}
四. 文件
4.1 File类
File类创建的对象是一个文件,并不具备输入输出的功能。
利用File类来对整个文件进行一些操作,利用输入输出流对文件数据进行操作。
4.1.1 基本操作
public static void main(String[] args) {
// 不加地址,只有文件名,默认在当前目录下
File file1 = new File("a.txt"); // 一个文件
// 目录
File file2 = new File("d:" + File.separatorChar); //separatorChar 自动识别目录分隔符的系统格式
// 有目录的文件
// File file1 = new File("d:" + File.separatorChar + "a.txt");
if(!file1.exists()){
// 默认抛出了IOException异常,必须处理
try{
file1.createNewFile();
}catch(IOException e){
e.printStackTrace();
}
}
System.out.println(file1.canRead());
System.out.println(file1.length());
// 绝对路径
System.out.println(file1.getAbsolutePath());
// 文件名称
System.out.println(file1.getName());
// 是否为目录
System.out.println(file2.isDirectory());
// 返回目录下的文件 返回成String类
String[] stringList = file2.list();
System.out.println("string->指定目录下的文件为:");
for(String file: stringList){
System.out.println(file);
}
System.out.println();
// 返回的是文件
File[] fileList = file2.listFiles();
System.out.println("file->指定目录下的文件为:");
for(File file: fileList){
System.out.println(file);
}
}
4.1.2 寻找指定类型文件
package Study;
import java.io.File;
import java.io.FilenameFilter;
public class Test{
public static void main(String[] args) {
// 寻找指定类型文件:
System.out.println(" 寻找指定类型文件:");
File file = new File("D:\\ 临时下载文件夹" + File.separator);
// 设置一个过滤器
// 只接受符合条件的文件
File[] files = file.listFiles(new NameFilelter());
if(files != null){
for(File e : files){
System.out.println(e);
}
}
}
}
class NameFilelter implements FilenameFilter{
@Override
// 文件目录 文件名称
public boolean accept(File dir, String name) {
return name.endsWith(".doc") || name.endsWith(".docx");
}
}
4.2 字节流
4.2.1 inputStream
··
1. 输入
package Study;
import java.io.*;
public class Test{
public static void main(String[] args) {
//
FileInputStream in = null;
try {
in = new FileInputStream("d:" + File.separator + "a.txt");
} catch (FileNotFoundException e) {
e.printStackTrace();
}
int b =0;
while(true){
// 一个字节一个字节的读入,很慢
try {
b = in.read();
} catch (IOException e) {
e.printStackTrace();
}
if(b == -1){
break;
}
System.out.println(b);
}
try {
in.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
2. 解决输入过慢
public static void main(String[] args) {
FileInputStream in = null;
FileOutputStream out = null;
try {
out = new FileOutputStream("t.txt");
in = new FileInputStream("a.txt");
} catch (IOException e) {
}
// 一次读入1024个字节 1M
byte b[] = new byte[14];
int len;
try {
while ((len = in.read(b)) != -1) {
// 如果不这样,会有问题,可能会多输出一些内容
// 这样写是 实际需要读入缓冲区的字节数量
out.write(b, 0, len);
}
} catch (IOException e) {
}
}
3. 使用字节缓冲流
4.2.2 outputStream
import java.io.*;
public class Test {
public static void main(String[] args) {
// 若没有文件,则自动创建
FileOutputStream out = null;
try {
out = new FileOutputStream("a.txt");
} catch (FileNotFoundException e) {
e.printStackTrace();
}
byte[] b = "123萨达sd\n".getBytes();
// 从下标3开始的6个字符
// 注意:utf-8一个汉字是3个字符 GBK一个汉字是2个字符
try {
// 1.
out.write(b, 3, 6);
// 2. 全部读入
out.write(b);
// 3. 一个字节一个字节的 效率低
for (int i = 0; i < b.length; i++) {
out.write(b[i]);
}
} catch (IOException e) {
e.printStackTrace();
}
// 追加
FileOutputStream out_zui = null;
try {
out_zui = new FileOutputStream("a.txt", true);
} catch (FileNotFoundException e) {
e.printStackTrace();
}
try {
out_zui.write("你好\n".getBytes());
out_zui.write("你好\n".getBytes());
} catch (IOException e) {
e.printStackTrace();
}
try {
out.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
4.3 String和byte[] 互相转换
public static void main(String[] args) {
byte[] b = "张崇文666".getBytes();
String s = new String(b);
System.out.println(s);
}
4.4 字节缓冲流
承接4.2.2
import java.io.*;
public class Test {
public static void main(String[] args) {
BufferedInputStream bis = null;
BufferedOutputStream bos = null;
try {
// 使用BufferedInputStream来包装
bis = new BufferedInputStream(new FileInputStream("a.txt"));
bos = new BufferedOutputStream(new FileOutputStream("t.txt"));
} catch (FileNotFoundException e) {
e.printStackTrace();
}
int b;
try {
while ((b = bis.read()) != -1) {
bos.write(b);
}
} catch (IOException e) {
e.printStackTrace();
}
try {
bis.close();
bos.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
4.5 字符流
1. OutputStreamWriter 和 FileOutputStream
Java提供了FileWriter
和FileReader
简化字符流的读写,new FileWriter
等同于new OutputStreamWriter(new FileOutputStream(file, true))
class Test {
public static void main(String[] args) throws IOException {
File file = new File("t.txt");
write(file);
System.out.println(read(file));
}
public static void write(File file) throws IOException {
// OutputStreamWriter可以显示指定字符集,否则使用默认字符集
OutputStreamWriter osw = new OutputStreamWriter(new FileOutputStream(file, true), "UTF-8");
// 要写入的字符串
String string = "松下问童子,言师采药去。只在此山中,云深不知处。";
osw.write(string);
osw.close();
}
public static String read(File file) throws IOException {
InputStreamReader isr = new InputStreamReader(new FileInputStream(file), "UTF-8");
// 字符数组:一次读取多少个字符
char[] chars = new char[1024];
// 每次读取的字符数组先append到StringBuilder中
StringBuilder sb = new StringBuilder();
// 读取到的字符数组长度,为-1时表示没有数据
int length;
// 循环取数据
while ((length = isr.read(chars)) != -1) {
// 将读取的内容转换成字符串
sb.append(chars, 0, length);
}
// 关闭流
isr.close();
return sb.toString();
}
// 简化写法
public static void write_easy(File file) throws IOException {
FileWriter fw = new FileWriter(file, true);
// 要写入的字符串
String string = "松下问童子,言师采药去。只在此山中,云深不知处。";
fw.write(string);
fw.close();
}
public static String read_easy(File file) throws IOException {
FileReader fr = new FileReader(file);
// 一次性取多少个字节
char[] chars = new char[1024];
// 用来接收读取的字节数组
StringBuilder sb = new StringBuilder();
// 读取到的字节数组长度,为-1时表示没有数据
int length;
// 循环取数据
while ((length = fr.read(chars)) != -1) {
// 将读取的内容转换成字符串
sb.append(chars, 0, length);
}
// 关闭流
fr.close();
return sb.toString();
}
}
2. 字符缓存流
class Test {
public static void main(String[] args) throws IOException {
File file = new File("t.txt");
write(file);
System.out.println(read(file));
}
public static void write(File file) throws IOException {
// BufferedWriter fw = new BufferedWriter(new OutputStreamWriter(new
// FileOutputStream(file, true), "UTF-8"));
// FileWriter可以大幅度简化代码
BufferedWriter bw = new BufferedWriter(new FileWriter(file, true));
// 要写入的字符串
String string = "松下问童子,言师采药去。只在此山中,云深不知处。";
bw.write(string);
bw.close();
}
public static String read(File file) throws IOException {
BufferedReader br = new BufferedReader(new FileReader(file));
// 用来接收读取的字节数组
StringBuilder sb = new StringBuilder();
// 按行读数据
String line;
// 循环取数据
while ((line = br.readLine()) != null) {
// 将读取的内容转换成字符串
sb.append(line);
}
// 关闭流
br.close();
return sb.toString();
}
}
五. 集合
基本元素对应表
集合 中的元素实际上是对象,一些常见的基本类型可以使用它的包装类。
基本类型对应的包装类表如下:
基本类型 | 引用类型 |
---|---|
boolean | Boolean |
byte | Byte |
short | Short |
int | Integer |
long | Long |
float | Float |
double | Double |
char | Character |
5.1 ArraList
import java.util.ArrayList;
import java.util.LinkedList;
public class Main {
public static void main(String[] args) {
// LinkedList<Integer> l = new LinkedList<Integer>();
// l.add
ArrayList<Integer> a = new ArrayList<Integer>();
// 1. 增加元素
for(int i = 0;i < 5;i++){
a.add(i);
}
// 2. 获取元素
int index = 1;
System.out.println(a.get(index));
// 3. 判空
System.out.println(a.isEmpty());
// 4. contains 是否包含此元素
System.out.println("a包含4吗? " + a.contains(4));
// 5. indexOf 查找
// 5. lastIndexOf 反向查找
System.out.println("4在哪个位置? " + a.indexOf(4) + " " + a.lastIndexOf(4));
// 6. clone 输出所有元素 [0, 1, 2, 3, 4]
System.out.println(a.clone());
// 7. toArray 转化成数组
// 知道下面两种方式:
Integer[] cIntegers = (Integer[]) a.toArray(new Integer[0]);
// 7.2 开一个等大小的数组
Integer[] b =new Integer[a.size()];
// 转
a.toArray(b);
System.out.println("转成数组:");
for(int e :b){
System.out.print(e + " " );
}
System.out.println();
// 8. set 修改元素
a.set(0, -1);
// 9. add(int index, int x);
// 在index位置插入
System.out.println("插入:");
index = 2;
Print(a);
a.add(index, 9);
Print(a);
// 10. remove 删除
a.remove(1); // 移除index
a.remove((Integer)4); // 移除元素
Print(a);
// 11. addAll 复制
System.out.println("d复制了a");
ArrayList<Integer> d = new ArrayList<Integer>();
d.addAll(a);
Print(d);
}
static void Print(ArrayList<Integer> a){
for(int e : a){
System.out.print(e + " ");
}
System.out.println();
}
}
5.2 LinkedList
import java.util.ArrayList;
import java.util.LinkedList;
public class Main {
public static void main(String[] args) {
LinkedList<String> s = new LinkedList<String>();
s.addFirst("11");
s.addLast("56");
Print(s);
}
static void Print(LinkedList<String> s){
while(!s.isEmpty()){
System.out.println(s.getFirst() + " ");
s.removeFirst();
}
// for(String e : s){
// System.out.print(e + " ");
// }
System.out.println();
}
}
5.3 Iterator
当通过迭代器获取ArrayList集合中的元素时,都会将这些元素当做Object类型来看待,如果想得到特定类型的元素,则需要进行强制类型转换。
import java.util.Iterator;
import java.util.LinkedList;
public class Main {
public static void main(String[] args) {
LinkedList<String> s = new LinkedList<String>();
s.addFirst("11");
s.addLast("56");
Iterator<String> it = s.iterator();
while(it.hasNext()){
Object obj = it.next();
System.out.println(obj);
// 需要删除的时候, 如果想继续遍历,那么就这样删除
if(obj.equals("11"))
it.remove();
}
}
}
5.4 Set
5.4.1 HashSet
去重 无序
public static void main(String[] args) {
HashSet<Integer> ret = new HashSet<Integer>();
// 1. add
ret.add(1);
ret.add(3);
ret.add(2);
ret.add(1);
Print(ret);
// 2. contains
System.out.println(ret.contains(1));
// 3. remove
ret.remove(1);
Print(ret);
Iterator it = ret.iterator();
while(it.hasNext()){
Object obj = it.next();
System.out.println(obj);
}
System.out.println();
System.out.println(ret);
}
static void Print(HashSet<Integer> ret){
for(int e: ret){
System.out.print(e + " ");
}
System.out.println();
}
5.4.2 TreeSet
有序 + 去重
public static void main(String[] args) {
TreeSet<Integer> ret = new TreeSet<Integer>();
ret.add(3);
ret.add(1);
ret.add(2);
ret.add(2);
System.out.println(ret);
System.out.println(ret.first() + " " + ret.last());
}
5.5 Map
5.5.1 HashMap
去重 无序
public static void main(String[] args) {
HashMap<Integer, String> rap = new HashMap<Integer, String>();
// 1. put
rap.put(24, "xin");
rap.put(14, "xin");
rap.put(34, "xin");
rap.put(1, "liu");
rap.put(3, "wen");
rap.put(2, "qi");
rap.put(1, "xin");
rap.put(4, "xin");
rap.put(9, "xin");
System.out.println(rap);
// 2. 获取值 get
System.out.println(rap.get(1));
// 3. 删除 remove(key)
rap.remove(1);
System.out.println(rap);
// 4. for-each
for(int e : rap.keySet()){
System.out.println(e + " " + rap.get(e));
}
}
六. 多线程
6.1 继承Thread类 (不建议这样写)
重写run方法
每个进程的数据独立, 不会同时改变
public class Main {
public static void main(String[] args) {
/****************
*
* 创建多线程对象 并开启 第一个创建的就是第一个
*
****************/
// 1. 创建实例独享 创建线程对象 开启线程,执行线程中的run方法
Test ta = new Test();
Thread thread = new Thread(ta, "线程名字");
thread.start();
// 2.
new Test().start();
new Test().start();
// 3.
Test t = new Test();
new Thread(t, "线程名字").start();
}
}
class Test extends Thread {
int j = 0;
public void run() {
for (int i = 0; i < 10; i++) {
/***********
*
* 获取当前线程 获取当前线程的名字
*
***********/
Thread th = Thread.currentThread();
String name = th.getName();
System.out.println(name + " " + j++);
}
}
}
6.2 实现 java.lang.Runnable 接口
实现run方法
每个进程共享类中的数据, 即同时改变
public class Maina {
public static void main(String[] args) {
Test1 t1 = new Test1();
new Thread(t1, "窗口1").start();
new Thread(t1, "窗口2").start();
new Thread(t1, "窗口3").start();
}
}
class Test1 implements Runnable {
/***************
*
* 每个进程共享类中的数据, 即同时改变
*
***************/
int j = 0;
public void run() {
for (int i = 0; i < 10; i++) {
System.out.println(Thread.currentThread().getName() + " " + j++);
}
}
}
6.3 优先级
public class Mainn {
public static void main(String[] args) {
Thread min = new Thread(new Testa(), "低");
Thread mid = new Thread(new Testa(), "中");
Thread max = new Thread(new Testa(), "高");
/*********************
*
* 优先级可以定义为 1 - 10
* 可以用Thread中的常亮 他们分别是: 1 5 10
*
*
*********************/
min.setPriority(Thread.MIN_PRIORITY);
mid.setPriority(Thread.NORM_PRIORITY);
max.setPriority(Thread.MAX_PRIORITY);
min.start();
mid.start();
max.start();
}
}
class Testa implements Runnable{
public void run(){
for(int i =0 ;i < 5 ;i++){
String name = Thread.currentThread().getName();
System.out.println(name + " " + i);
}
}
}
6.4 休眠sleep
使用Thread中的sleep方法 单位是毫秒
public class Mainn {
public static void main(String[] args) throws Exception {
new Thread(new Testa(), "run-线程").start();
for (int i = 1; i <= 10; i++) {
if (i == 5) {
Thread.sleep(2000); // 当前main主线程 休眠2秒
} else {
Thread.sleep(500);
}
System.out.println("main-线程");
}
}
}
class Testa implements Runnable {
public void run() {
for (int i = 0; i <= 10; i++) {
if (i % 2 == 1) {
try {
Thread.sleep(1000); // 1秒
} catch (Exception e) {
}
}
String name = Thread.currentThread().getName();
System.out.println(name + " " + i);
}
}
}
6.5 让步yield
yield()方法不会阻塞该线程,它只是将线程转换成就绪状态,让系统的调度器重新调度一次。当某个线程调用yield()方法之后,只有与当前线程优先级相同或者更高的线程才能获得执行的机会。
package T;
public class Main {
public static void main(String[] args) throws Exception {
// 创建线程
Thread t = new Thread(new EmergencyThread(), "线程一");
t.start(); // 开启线程
for (int i = 1; i < 6; i++) {
System.out.println(Thread.currentThread().getName() + "输出:" + i);
if (i == 2) {
t.join(); // 调用join()方法
}
}
}
}
//线程的任务类
class EmergencyThread implements Runnable {
public void run() {
for (int i = 1; i < 6; i++) {
System.out.println(Thread.currentThread().getName() + "输出:" + i);
}
}
}
package T;
public class Main {
public static void main(String[] args) {
// 创建两个线程
Thread t1 = new YieldThread("线程A");
Thread t2 = new YieldThread("线程B");
Thread t3 = new YieldThread("线程C");
t1.setPriority(1);
t1.setPriority(2);
t2.setPriority(3);
// 开启两个线程
t1.start();
t2.start();
t3.start();
}
}
//定义YieldThread类继承Thread类
class YieldThread extends Thread {
// 定义一个有参的构造方法
public YieldThread(String name) {
super(name); // 调用父类的构造方法
}
public void run() {
for (int i = 0; i < 60; i++) {
System.out.println(Thread.currentThread().getName() + "---" + i);
if (i % 3 == 1) {
System.out.print("线程让步:");
Thread.yield(); // 线程运行到此,作出让步
}
}
}
}
6.6 插队join
需要抛出异常 Exception
当在某个线程中调用其他线程的join()方法时,调用的线程将被阻塞,直到被join()方法加入的线程执行完成后它才会继续运行。
package T;
public class Main {
public static void main(String[] args) throws Exception {
// 创建线程
Thread t = new Thread(new EmergencyThread(), "线程一");
t.start(); // 开启线程
for (int i = 1; i < 6; i++) {
System.out.println(Thread.currentThread().getName() + "输出:" + i);
if (i == 2) {
t.join(); // 调用join()方法
}
}
}
}
//线程的任务类
class EmergencyThread implements Runnable {
public void run() {
for (int i = 1; i < 6; i++) {
System.out.println(Thread.currentThread().getName() + "输出:" + i);
}
}
}
6.7 线程同步
package T;
import javax.sql.rowset.spi.SyncFactory;
public class Main {
public static void main(String[] args) {
TicketWindow task = new TicketWindow();// 创建线程的任务类对象
new Thread(task, "窗口1").start();// 创建线程并起名为窗口1, 开启线程
new Thread(task, "窗口2").start();// 创建线程并起名为窗口2, 开启线程
new Thread(task, "窗口3").start();// 创建线程并起名为窗口3, 开启线程
new Thread(task, "窗口4").start();// 创建线程并起名为窗口4, 开启线程
}
}
// 线程的任务类
class TicketWindow implements Runnable {
private int tickets = 10; // 10张票
Object lock = new Object();// 定义任意一个对象,用作同步代码块的锁
@Override
public void run() {
while (true) {
// synchronized (lock) { // 定义同步代码块
// synchronized(TicketWindow.class) {
synchronized(this) {
try {
Thread.sleep(10); // 线程休眠10毫秒
} catch (InterruptedException e) {
e.printStackTrace();
}
if (tickets > 0) {
System.out.println(Thread.currentThread().getName() + "---卖出的票" + tickets--);
} else {
break;
}
}
}
}
}
package T;
/**
* 死锁
*
* @author Administrator
*
*/
public class Main {
public static void main(String[] args) {
// 创建两个DeadLockThread对象
DeadLockThread d1 = new DeadLockThread(true);
DeadLockThread d2 = new DeadLockThread(false);
// 创建并开启两个线程
new Thread(d1, "Chinese").start(); // 创建开启线程Chinese
new Thread(d2, "American").start(); // 创建开启线程American
}
}
/** * 死锁 */
class DeadLockThread implements Runnable {
static Object chopsticks = new Object(); // 定义Object类型的chopsticks锁对象
static Object knifeAndFork = new Object(); // 定义Object类型的knifeAndFork锁对象
private boolean flag; // 定义boolean类型的变量flag
DeadLockThread(boolean flag) {
// 定义有参的构造方法
this.flag = flag;
}
public void run() {
if (flag) {
while (true) {
synchronized (chopsticks) {
// chopsticks锁对象上的同步代码块
System.out.println(Thread.currentThread().getName() + "---if---chopsticks");
synchronized (knifeAndFork) {
// knifeAndFork锁对象上的同步代码块
System.out.println(Thread.currentThread().getName() + "---if---knifeAndFork");
}
}
}
} else {
while (true) {
synchronized (knifeAndFork) {
// knifeAndFork锁对象上的同步代码块
System.out.println(Thread.currentThread().getName() + "---else---knifeAndFork");
synchronized (chopsticks) {
// chopsticks锁对象上的同步代码块
System.out.println(Thread.currentThread().getName() + "---else---chopsticks");
}
}
}
}
}
}
/**
* <p>Title: Exam13.java</p>
* <p>Description: </p>
* <p>Copyright: Copyright (c) 2020</p>
* <p>Company: ie.bzu.edu.cn</p>
* @author 宋锋
* @date 2020-10-29
* @version 1.0
*/
package exam13.copy;
import exam13.copy.DeadLockThread;
/**
* 死锁
*
* @author Administrator
*
*/
public class Exam13 {
public static void main(String[] args) {
// 创建两个DeadLockThread对象
DeadLockThread d1 = new DeadLockThread(true);
DeadLockThread d2 = new DeadLockThread(false);
// 创建并开启两个线程
new Thread(d1, "Chinese").start(); // 创建开启线程Chinese
new Thread(d2, "American").start(); // 创建开启线程American
}
}
/** * 死锁 */
class DeadLockThread implements Runnable {
static Object chopsticks = new Object(); // 定义Object类型的chopsticks锁对象
static Object knifeAndFork = new Object(); // 定义Object类型的knifeAndFork锁对象
private boolean flag; // 定义boolean类型的变量flag
DeadLockThread(boolean flag) {
// 定义有参的构造方法
this.flag = flag;
}
public void run() {
if (flag) {
while (true) {
synchronized (chopsticks) {
// chopsticks锁对象上的同步代码块
System.out.println(Thread.currentThread().getName() + "---if---chopsticks");
synchronized (knifeAndFork) {
// knifeAndFork锁对象上的同步代码块
System.out.println(Thread.currentThread().getName() + "---if---knifeAndFork");
}
}
}
} else {
while (true) {
synchronized (knifeAndFork) {
// knifeAndFork锁对象上的同步代码块
System.out.println(Thread.currentThread().getName() + "---else---knifeAndFork");
synchronized (chopsticks) {
// chopsticks锁对象上的同步代码块
System.out.println(Thread.currentThread().getName() + "---else---chopsticks");
}
}
}
}
}
}
七、网络编程
7.1 TCP
服务器端套路
- 创建ServerSocket对象,绑定监听端口。
- 通过accept()方法监听客户端请求。
- 连接建立后,通过输入流读取客户端发送的请求信息。
- 通过输出流向客户端发送响应信息。
- 关闭响应的资源。
客户端套路
- 创建Socket对象,指明需要连接的服务器的地址和端口号。
- 连接建立后,通过输出流向服务器发送请求信息。
- 通过输入流获取服务器响应的信息。
- 关闭相应资源。
多线程实现服务器与多客户端之间通信步骤
- 服务器端创建ServerSocket,循环调用accept()等待客户端连接。
- 客户端创建一个socket并请求和服务器端连接。
- 服务器端接受客户端请求,创建socket与该客户建立专线连接。
- 建立连接的两个socket在一个单独的线程上对话。
- 服务器端继续等待新的连接。
Socket
方法等 | 含义 |
---|---|
PrintWriter writer = new PrintWriter(socket.getOutputStream()); | 字符数据和字节间的转换桥梁 * 可以衔接String和Socket两端 使用这个来发送数据 |
writer.println(“你好”); | 对连接的目标发送消息 |
ServerSocket serverSocket = new ServerSocket(4242); | 设置服务器的端口 |
Socket socket = serverSocket.accept(); | 当有用户连接服务器时并发送数据时,自动返回一个Socket |
sock = new Socket(“127.0.0.1”, 4242); writer = new PrintWriter(sock.getOutputStream()); |
这个语句的含义是 建立连接 |
InputStreamReader streamReader = new InputStreamReader(socket.getInputStream()); BufferedReader reader = new BufferedReader(streamReader); String s = bufferedReader.readLine(); |
接收数据 |
public static void main(String args[]) throws Exception {
// 1. 对服务器建立Socket连接
Socket chatSocket = new Socket("169.254.151.206", 5000);
// 2. 建立链接到Socket的PrintWriter
/**************************
*
* PrintWriter
* 字符数据和字节间的转换桥梁
* 可以衔接String和Socket两端
*
* ps:在本机 由PrintWriter转成字节给Socket 然后Socket转给服务器
*
**************************/
PrintWriter writer = new PrintWriter(chatSocket.getOutputStream());
// 3. 写入数据
writer.println("你好");
writer.print("呵呵哒");
}
1。 简单用户与服务器
package Net.First;
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.net.Socket;
// 后启动客户机
public class Client_Study {
public void go() throws Exception{
// 对服务器的4242端口做连接
Socket s = new Socket("127.0.0.1", 4242);
// 用这个方式来读服务器传来的数据
// 一旦建立连接 客户端就可以从Socket取得底层串流
// 由这个读入
InputStreamReader streamReader = new InputStreamReader(s.getInputStream());
BufferedReader reader = new BufferedReader(streamReader);
String advice = reader.readLine();
System.out.println("客户端 : " + advice );
reader.close();
s.close();
}
public static void main(String[] args) {
Client_Study client_study = new Client_Study();
try {
client_study.go();
} catch (Exception e) {
e.printStackTrace();
}
}
}
// 服务器
package Net.First;
import java.io.PrintWriter;
import java.net.ServerSocket;
import java.net.Socket;
// 先启动服务器
public class Server_Study {
public void go() throws Exception {
// 服务器的端口就是4242 自己定义 由客户机确定ip和端口来连接服务器
ServerSocket serverSocket = new ServerSocket(4242);
/*****************
*
* 服务器创建出与客户端通信的新Socket
* 等待用户的Socket连接时闲置。
* 当用户连上来之后 会返回一个Socket
*
****************/
Socket socket = serverSocket.accept(); // 只能服务一个用户 必须在当前用户使用完成之后 才能接入下一个用户
PrintWriter writer = new PrintWriter(socket.getOutputStream());
String advice = "张崇文呢";
writer.print(advice);
writer.close();
System.out.println("服务器 : " + advice);
socket.close();
}
public static void main(String[] args) {
Server_Study server_study = new Server_Study();
try {
server_study.go();
} catch (Exception e) {
e.printStackTrace();
}
}
}
2。 用户机对服务器发消息
// 用户机:
package Net.Second;
import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.Socket;
public class Client_Only_Study {
JTextField outgoing;
PrintWriter writer;
Socket sock;
public void go() {
JFrame frame = new JFrame("聊天客户端");
frame.setLocationRelativeTo(null);
JPanel mainPanel = new JPanel();
outgoing = new JTextField(20);
JButton sendButton = new JButton("发送");
sendButton.addActionListener(new SendButtonListener());
mainPanel.add(outgoing);
mainPanel.add(sendButton);
frame.getContentPane().add(BorderLayout.CENTER, mainPanel);
// frame.getContentPane().add(mainPanel, BorderLayout.CENTER);
setUpNetworking();
frame.setSize(400, 500);
frame.setVisible(true);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}
private void setUpNetworking() {
try {
sock = new Socket("127.0.0.1", 4242);
writer = new PrintWriter(sock.getOutputStream());
System.out.println("以建立连接");
} catch (IOException e) {
e.printStackTrace();
}
}
class SendButtonListener implements ActionListener {
@Override
public void actionPerformed(ActionEvent e) {
try {
writer.println(outgoing.getText());
writer.flush();
outgoing.setText("");
} catch (Exception ex) {
ex.printStackTrace();
}
// outgoing.requestFocus();
}
}
public static void main(String[] args) {
Client_Only_Study client_only_study = new Client_Only_Study();
client_only_study.go();
}
}
// 服务器:
package Net.Second;
import java.io.BufferedReader;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.ServerSocket;
import java.net.Socket;
public class Server_Only_Study {
void go() throws Exception {
ServerSocket serverSocket = new ServerSocket(4242);
Socket socket = serverSocket.accept();
InputStreamReader inputStreamReader = new InputStreamReader(socket.getInputStream());
BufferedReader bufferedReader = new BufferedReader(inputStreamReader);
String s = bufferedReader.readLine();
System.out.println(s);
}
public static void main(String[] args) {
try {
new Server_Only_Study().go();
} catch (Exception e) {
e.printStackTrace();
}
}
}
3。 多个用户同时发送消息
3.1 客户机A与B
// A::
package Net.third;
import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.*;
import java.net.Socket;
public class Clinet_A {
JTextArea incoming;
JTextField outgoing;
BufferedReader reader ;
PrintWriter writer;
Socket sock;
public static void main(String[] args) {
Clinet_A clinet_A_ = new Clinet_A();
clinet_A_.go();
}
public void go(){
JFrame frame = new JFrame("崇文的客户端A");
JPanel mainPanel = new JPanel();
incoming = new JTextArea(15, 50);
incoming.setLineWrap(true);// 是否自动换行
incoming.setEditable(false);
JScrollPane qScroller = new JScrollPane(incoming);
qScroller.setVerticalScrollBarPolicy(ScrollPaneConstants.VERTICAL_SCROLLBAR_ALWAYS);
qScroller.setHorizontalScrollBarPolicy(ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER);
outgoing = new JTextField(20);
JButton sendButton = new JButton("Send");
sendButton.addActionListener(new SendButtonListener());
mainPanel.add(qScroller);
mainPanel.add(outgoing);
mainPanel.add(sendButton);
setUpNetworking();
// 送服务器端 接收的数据 输出到文本域中
Thread readThread = new Thread(new IncomingReader());
readThread.start();
frame.getContentPane().add(BorderLayout.CENTER, mainPanel);
frame.setSize(400,500);
frame.setVisible(true);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}
// 建立连接
private void setUpNetworking(){
try{
sock = new Socket("127.0.0.1", 5000);
// 接受服务器的数据
InputStreamReader streamReader = new InputStreamReader(sock.getInputStream());
reader = new BufferedReader(streamReader);
// 向服务器发送数据
writer = new PrintWriter(sock.getOutputStream());
System.out.println("成功建立连接");
}catch(Exception ex){
ex.printStackTrace();
}
}
// 发送数据事件
public class SendButtonListener implements ActionListener{
@Override
public void actionPerformed(ActionEvent e) {
try{
writer.println(outgoing.getText());
writer.flush();
}catch(Exception ex){
ex.printStackTrace();
}
outgoing.setText("");
outgoing.requestFocus();
}
}
public class IncomingReader implements Runnable{
public void run(){
String message;
try{
while((message = reader.readLine()) != null){
System.out.println("接收到:" + message);
incoming.append(message + "\n");
}
}catch(Exception ex){
ex.printStackTrace();
}
}
}
}
// B::
package Net.third;
import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.*;
import java.net.Socket;
public class Clinet_B {
JTextArea incoming;
JTextField outgoing;
BufferedReader reader;
PrintWriter writer;
Socket sock;
public static void main(String[] args) {
Clinet_B clinetB = new Clinet_B();
clinetB.go();
}
public void go() {
JFrame frame = new JFrame("崇文的客户端B");
JPanel mainPanel = new JPanel();
incoming = new JTextArea(15, 50);
incoming.setLineWrap(true);// ?
incoming.setWrapStyleWord(true); // ?
incoming.setEditable(false);// ?
JScrollPane qScroller = new JScrollPane(incoming);
qScroller.setVerticalScrollBarPolicy(ScrollPaneConstants.VERTICAL_SCROLLBAR_ALWAYS);
qScroller.setHorizontalScrollBarPolicy(ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER);
outgoing = new JTextField(20);
JButton sendButton = new JButton("Send");
sendButton.addActionListener(new SendButtonListener());
mainPanel.add(qScroller);
mainPanel.add(outgoing);
mainPanel.add(sendButton);
setUpNetworking();
Thread readThread = new Thread(new IncomingReader());
readThread.start();
frame.getContentPane().add(BorderLayout.CENTER, mainPanel);
frame.setSize(400, 500);
frame.setVisible(true);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}
// 建立连接
private void setUpNetworking() {
try {
sock = new Socket("127.0.0.1", 5000);
// 接受服务器的数据
InputStreamReader streamReader = new InputStreamReader(sock.getInputStream());
reader = new BufferedReader(streamReader);
// 向服务器发送数据
writer = new PrintWriter(sock.getOutputStream());
System.out.println("成功建立连接");
} catch (Exception ex) {
ex.printStackTrace();
}
}
// 发送数据事件
public class SendButtonListener implements ActionListener {
@Override
public void actionPerformed(ActionEvent e) {
try {
writer.println(outgoing.getText());
writer.flush();
} catch (Exception ex) {
ex.printStackTrace();
}
outgoing.setText("");
outgoing.requestFocus();
}
}
public class IncomingReader implements Runnable {
public void run() {
String message;
try {
while ((message = reader.readLine()) != null) {
System.out.println("接收到:" + message);
incoming.append(message + "\n");
}
} catch (Exception ex) {
ex.printStackTrace();
}
}
}
}
3.2 服务器
package Net.third;
import java.io.*;
import java.net.*;
import java.util.*;
public class Sever_ {
// 存放 接受的数据 然后在发送给客户端
ArrayList<PrintWriter> clientOutStreams;
// 多线程 运行信息接收代码
public class ClientHandler implements Runnable {
Socket sock;
BufferedReader reader;
// 建立连接
public ClientHandler(Socket clientSocket) {
try {
sock = clientSocket;
InputStreamReader isReader = null;
try {
isReader = new InputStreamReader(sock.getInputStream());
} catch (IOException e) {
e.printStackTrace();
}
// 接收信息
reader = new BufferedReader(isReader);
} catch (Exception ex) {
ex.printStackTrace();
}
}
// 把接收的信息 读出来
public void run() {
String message;
try {
while ((message = reader.readLine()) != null) {
System.out.println("接收到 :" +sock.getInetAddress() +" " + message);
// 发给所有人
tellEveryone(message);
}
} catch (Exception ex) {
ex.printStackTrace();
}
}
}
public static void main(String args[]) {
new Sever_().go();
}
public void go() {
clientOutStreams = new ArrayList<PrintWriter>();
try {
ServerSocket serverSocket = new ServerSocket(5000);
/**
*
* 服务器端创建ServerSocket
* 循环调用accept等待用户端的连接
* 可以同时连接多个设备
*
*/
while (true) {
// main线程一直等待连接
Socket clientSock = serverSocket.accept();
PrintWriter writer = new PrintWriter(clientSock.getOutputStream());
clientOutStreams.add(writer); // 对某一个客户机的连接
// 再等待新客户端接入的同时对其他客户端进行 信息转发
Thread t = new Thread(new ClientHandler(clientSock));
t.start();
System.out.println("得到一个连接");
}
} catch (Exception ex) {
ex.printStackTrace();
}
}
// 把接收的信息全部 再发到客户端
// 服务器就是一个信息中转站 客户机把信息先发送到服务器
// 然后服务器再转发出去
public void tellEveryone(String message) {
for (PrintWriter e : clientOutStreams) {
try {
PrintWriter writer = e;
writer.println("服务器发送: "+message);
writer.flush();
} catch (Exception ex) {
ex.printStackTrace();
}
}
}
}
7.1 InetAddress类
在JDK中,提供了一个与IP地址相关的InetAddress类,该类用于封装一个IP地址,并提供了一系列与IP地址相关的方法,下表中列举了InetAddress类的一些常用方法。
public class Main {
public static void main(String[] args) throws Exception{
// 获取本机的 InetAddress 对象
InetAddress own = InetAddress.getLocalHost();
// 获取主机IP
System.out.println(own.getHostAddress());
// 获取主机
System.out.println(own.getHostName());
// 获取指定主机的 InetAddress 对象
InetAddress bzu = InetAddress.getByName("www.bzu.edu.cn");
System.out.println(bzu.getHostAddress());
// 3秒是否可达
System.out.println(bzu.isReachable(1000));
// bzu的主机名:
System.out.println(bzu.getHostName());
}
}
7.2 集装箱 和 码头
7.2.1 DatagramPacket类——集装箱
该类的实例对象就相当于一个集装箱,用于封装UDP通信中发送或者接收的数据。
在创建发送端和接收端的DatagramPacket对象时,使用的构造方法有所不同,接收端的构造方法只需要接收一个字节数组来存放接收到的数据,而发送端的构造方法不但要接收存放了发送数据的字节数组,还需要指定发送端IP地址和端口号
构造方法:
•DatagramPacket(byte[] buf,int length) | 用于接收端: 指定了封装数据的字节数组和数据的大小,没有指定IP地址和端口号 |
---|---|
•DatagramPacket(byte[] buf,int length,InetAddress addr,int port) | 用于发送端: 目标IP地址(addr)和端口号(port) |
•DatagramPacket(byte[] buf,int offset,int length) | 接收端:增加了一个offset参数,该参数用于指定接收到的数据在放入buf缓冲数组时是从offset处开始的。 |
•DatagramPacket(byte[] buf,int offset,int length,InetAddress addr,int port) | 发送端:增加了一个offset参数,该参数用于指定一个数组中发送数据的偏移量为offset,即从offset位置开始发送数据。 |
方法:
7.2.3 DatagramSocket——码头
构造方法 | 含义 |
---|---|
•DatagramSocket() | 发送端:并没有指定端口号,系统自动分配一个没有被其他程序使用的端口号 |
•DatagramSocket(int port) | 接收端和发送端: 创建接收端的DatagramSocket对象时,必须要指定一个端口号,这样就可以监听指定的端口。 |
•DatagramSocket(int port,InetAddress addr) | 不仅指定了端口号,还指定了相关的IP地址。该对象的使用适用于计算机上有多块网卡的情况 |
方法:
7.3 UDP
特点:
在数据传输时,数据的发送端和接收端不建立逻辑连接。简单来说,当一台计算机向另外一台计算机发送数据时,发送端不会确认接收端是否存在,就会发出数据,同样接收端在收到数据时,也不会向发送端反馈是否收到数据。
DatagramPacket类,该类的实例对象就相当于一个集装箱,用于封装UDP通信中发送或者接收的数据。
7.4 TCP
特点:
面向连接的通信协议,即在传输数据前先在发送端和接收端建立逻辑连接,然后再传输数据,它提供了两台计算机之间可靠无差错的数据传输。
在TCP连接中必须要明确客户端与服务器端,由客户端向服务器端发出连接请求。
九十九. 杂
1. 获取时间
public static void main(String[] args) {
long begin_Time = System.currentTimeMillis();
for(int i =0 ;i < 2000000000;i++);
long end_Time = System.currentTimeMillis();
System.out.println(end_Time - begin_Time + " ms");
}
2. split方法
split() 方法根据匹配给定的正则表达式来拆分字符串。
注意:.
、$
**、 |
和 \*
(星号) 等转义字符,必须得加 \\
。
**注意:**多个分隔符,可以用 |
作为连字符。
public static void main(String[] args) {
String s = "123.456.789,1.2,3.83.9";
String[] t;
t = s.split("\\.|,");
for(String e: t)
System.out.println(e);
System.out.println(t.length);
}