每日要点
File
directory / folder - 文件夹
Java 7以后I/O(nio.2)中添加了操作文件和路径的工具类
Files - 操作文件的工具类
Paths - 操作路径的工具类
例子1:
File f = new File("c:/hello/abc/efg");
// f.mkdir();
f.mkdirs();
// 获得绝对路径
System.out.println(f.getAbsolutePath());
if (f.isDirectory()) {
String[] strs = f.list();
for (String temp : strs) {
System.out.println(temp);
}
}
随机访问文件类
例子2:
// 随机访问文件
try (RandomAccessFile raf = new RandomAccessFile("c:/abc.txt", "rw")) {
raf.seek(6);
raf.writeUTF("good");
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
NIO
JDK 1.4版引入了一套新的I/O系统称之为NIO
Buffer 缓冲区
Channel 通道
CharSet 字符集
NIO - Non-blocking I/O - 非阻塞式的I/O
导出和使用jar文件
导出:
在项目上右键选择Export-java-JAR file
导入:
将jar包负责粘贴到项目中,然后右键jar包选择Build Path
导入jar包后就可以使用jar包中写好的类:
在当前项目中使用其他项目导出的jar文件中的类
jar - java archive - Java归档文件(压缩包)
从别处获得的jar文件必须放到Build Path(类路径)下才能使用
例子1:
class Test04 {
// 在当前项目中使用其他项目导出的jar文件中的类
// jar - java archive - Java归档文件(压缩包)
// 从别处获得的jar文件必须放到Build Path(类路径)下才能使用
public static void main(String[] args) {
for (int i = 0; i < 5; i++) {
System.out.println(MyUtil.generateVC(4));
}
new VCFrame().setVisible(true);
}
}
压缩
GZIPInputStream - 读取单个压缩文件 - 解压缩
GZIPOutputStream - 压缩单个文件 - 压缩
ZipOutputStream - 将多个文件压缩成一个文件
ZipInputStream - 读取压缩文件还原成多个文件
给压缩文件添加冗余校验码 - 用于验证压缩文件的正确性和完整性的附加数据
- Adler32 / CRC32
清空缓冲区(强行把缓冲区中的数据写到输出流中)
bos.flush();
例子1:
class Test05 {
// GZIPInputStream - 读取单个压缩文件 - 解压缩
// GZIPOutputStream - 压缩单个文件 - 压缩
// ZipOutputStream - 将多个文件压缩成一个文件
// ZipInputStream - 读取压缩文件还原成多个文件
public static void main(String[] args) {
try (OutputStream out = new FileOutputStream("C:/Users/Administrator/Desktop/test.zip")) {
// 给压缩文件添加冗余校验码 - 用于验证压缩文件的正确性和完整性的附加数据
// - Adler32 / CRC32
CheckedOutputStream cos = new CheckedOutputStream(out, new CRC32());
ZipOutputStream zos = new ZipOutputStream(cos);
BufferedOutputStream bos = new BufferedOutputStream(zos);
String[] filenames = {"java.chm", "git命令.txt", "chess.rar"};
for (String filename : filenames) {
zos.putNextEntry(new ZipEntry(filename));
try (InputStream in = new FileInputStream("C:/Users/Administrator/Desktop/" + filename)) {
BufferedInputStream bin = new BufferedInputStream(in);
byte[] buffer = new byte[4096];
int totalBytes;
while ((totalBytes = bin.read(buffer)) != -1) {
bos.write(buffer, 0, totalBytes);
}
// 清空缓冲区(强行把缓冲区中的数据写到输出流中)
bos.flush();
/* int b;
while ((b = bin.read()) != -1) {
bos.write(b);
}
bos.flush();*/
}
catch (IOException ioe) {
ioe.printStackTrace();
}
zos.closeEntry();
}
zos.finish();
System.out.println("压缩完成!!!");
} catch (IOException e) {
e.printStackTrace();
}
}
}
线程
进程 - process - 操作系统分配内存的基本单元
线程 - thread - 最小的执行单元(操作系统分配CPU资源的基本单位)
一个进程通常包含了一个(主线程)或多个线程
Java中创建线程有三种方式:
- 继承Thread类并重写run()方法
- 实现Runnable接口并重写run()方法 (推荐使用!!!)
- 由于Runnable接口是单方法接口(函数式接口)所以也可以使用Lambda表达式
- 实现Callable接口并重写call()方法 - 将来时(Java 5+)
创建并启动线程 在新的线程中执行耗时间的任务
需要执行很长的时间如果放在主线程中执行那么主线程中的其他任务,就会被这个耗时间的任务所阻塞 所以耗时间的任务一定要放到主线程之外的线程中
启动线程是调用start()方法不能直接调用run()方法
例子1.
// 进程 - process - 操作系统分配内存的基本单元
// 线程 - thread - 最小的执行单元(操作系统分配CPU资源的基本单位)
// 一个进程通常包含了一个(主线程)或多个线程
// Java中创建线程有三种方式:
// - 继承Thread类并重写run()方法
// - 实现Runnable接口并重写run()方法 (推荐使用!!!)
// ·由于Runnable接口是单方法接口(函数式接口)所以也可以使用Lambda表达式
// - 实现Callable接口并重写call()方法 - 将来时(Java 5+)
public class MyFrame extends JFrame implements ActionListener{
private static final long serialVersionUID = 6221501510348081778L;
private JButton downloadButton, aboutButton;
// private class DownloadHandler extends Thread {
@SuppressWarnings("unused")
private class DownloadHandler implements Runnable {
@Override
public void run() {
downloadData();
downloadButton.setText("下载");
downloadButton.setEnabled(true);
}
}
public MyFrame() {
this.setTitle("下载");
this.setSize(450, 200);
this.setResizable(false);
this.setLocationRelativeTo(null);
this.setDefaultCloseOperation(EXIT_ON_CLOSE);
this.setLayout(null);
downloadButton = new JButton("下载");
downloadButton.setBounds(120, 120, 80, 30);
downloadButton.addActionListener(this);
aboutButton = new JButton("关于");
aboutButton.setBounds(250, 120, 80, 30);
aboutButton.addActionListener(this);
this.add(downloadButton);
this.add(aboutButton);
}
public static void main(String[] args) {
new MyFrame().setVisible(true);
}
@Override
public void actionPerformed(ActionEvent e) {
Object source = e.getSource();
if (source == downloadButton) {
downloadButton.setEnabled(false);
downloadButton.setText("下载中");
// 创建并启动线程 在新的线程中执行耗时间的任务
// 启动线程是调用start()方法不能直接调用run()方法
// new DownloadHandler().start();
// new Thread(new DownloadHandler()).start();
// Lambda表达式写法
Thread thread = new Thread(() -> {
downloadData();
downloadButton.setText("下载");
downloadButton.setEnabled(true);
});
// 设置优先级
thread.setPriority(Thread.NORM_PRIORITY);
// 设置守护进程(不值得保留的线程 - 主线程一结束该线程不保留)
thread.setDaemon(true);
// 启动线程
thread.start();
}
else if (source == aboutButton) {
JOptionPane.showMessageDialog(null, "欢迎使用xXx软件1.0版!\n作者: Kygo");
}
}
// 下载任务需要执行很长的时间如果放在主线程中执行那么主线程中的其他任务
// 就会被这个耗时间的任务所阻塞 所以耗时间的任务一定要放到主线程之外的线程中
// 因此下面的方法应该在一个新的线程中去调用它而不是在主线程中直接调用
private void downloadData() {
try {
Thread.sleep(10000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
练习1.启动两个线程 一个负责输出hello 一个负责输出good
class PrintThread implements Runnable {
private String str;
private int counter;
public PrintThread(String str, int counter) {
this.str = str;
this.counter = counter;
}
@Override
public void run() {
for (int i = 0; i < counter; i++) {
System.out.print(str);
doNothing();
}
}
private void doNothing() {
try {
Thread.sleep(1);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
class Test01 {
public static void main(String[] args) {
new Thread(new PrintThread("hello", 100)).start();
new Thread(new PrintThread("good", 100)).start();
}
}
杂项
.getClass .Class 获得这个类的原数据对象
例子1:字符串题
class Test01 {
public static void main(String[] args) {
String s1 = "go";
String s2 = "od";
String s3 = "good";
String s4 = "go" + "od"; // 两个常量相加 引用放在常量池
// javap 反编译源文件 先new分配空间 再初始化StringBuilder append append .toString
String s5 = s1 + s2;
System.out.println(s4 == s3);
System.out.println(s5 == s3);
}
}
例子2:
非静态内部类的对象一定要依赖于外部类的对象才能创建出来
静态内部类对象的创建可以不依赖于外部类的象
class Test06 {
public class Foo {
}
public static void main(String[] args) {
Test06 t = new Test06();
// 非静态内部类的对象一定要依赖于外部类的对象才能创建出来
// 静态内部类对象的创建可以不依赖于外部类的象
Foo foo = t.new Foo();
}
}
昨日作业讲解
**作业:建一个文本文件 写很多话 做一个窗口 随机显示一句话 点一下换一句 **
public class MyFrame extends JFrame {
private static final long serialVersionUID = 5056783142767245993L;
private JLabel contentLable;
private List<String> contentsList = new ArrayList<>();
public MyFrame() {
loadData();
this.setTitle("每日一句");
this.setSize(350, 120);
this.setResizable(false);
this.setLocationRelativeTo(null);
this.setDefaultCloseOperation(EXIT_ON_CLOSE);
contentLable = new JLabel(randomContent(), JLabel.CENTER);
this.add(contentLable);
this.addMouseListener(new MouseAdapter() {
@Override
public void mousePressed(MouseEvent e) {
contentLable.setText(randomContent());
}
});
}
private void loadData() {
// .getClass .Class 获得这个类的原数据对象
ClassLoader loader = this.getClass().getClassLoader();
InputStream in = loader.getResourceAsStream("名言警句.txt");
Reader reader = new InputStreamReader(in);
try (BufferedReader br = new BufferedReader(reader)) {
String str;
while ((str = br.readLine()) != null) {
contentsList.add(str);
}
}
catch (IOException e) {
e.printStackTrace();
}
}
private String randomContent() {
int randomIndex = (int) (Math.random() * contentsList.size());
return contentsList.get(randomIndex);
}
public static void main(String[] args) {
new MyFrame().setVisible(true);
}
}
作业
1.做一个窗口,实现5辆车多线程跑
车类:
public class Car{
private int x;
private int y;
private int width;
private int height;
private Color color;
private boolean isEnd;
public Car(int x, int y) {
this.x = x;
this.y = y;
this.color = randomColor();
this.width = 60;
this.height = 30;
}
public void move() {
if (x < 530) {
x += Math.random() * 10 + 1;
}
}
public boolean isEnd() {
if (x > 530) {
isEnd = true;
}
return isEnd;
}
private Color randomColor() {
return new Color((int) (Math.random() * 256),
(int) (Math.random() * 256), (int) (Math.random() * 256));
}
public void draw(Graphics g) {
g.setColor(color);
g.fillRect(x, y, width, height);
}
}
窗口类:
public class MyFrame extends JFrame {
private static final long serialVersionUID = 1581122281838520043L;
private BufferedImage image = new BufferedImage(600, 400, 1);
private List<Car> carsList = new ArrayList<>();
private List<Thread> carsThread = new ArrayList<>();
public MyFrame() {
this.setTitle("赛车游戏");
this.setSize(600, 400);
this.setResizable(false);
this.setLocationRelativeTo(null);
this.setDefaultCloseOperation(EXIT_ON_CLOSE);
for (int i = 0; i < 5; i++) {
carsList.add(new Car(60, 80 + i * 50));
}
for (int i = 0; i < 5; i++) {
Car car = carsList.get(i);
carsThread.add(new Thread(() -> {
while (!car.isEnd()) {
car.move();
try {
Thread.sleep(500);
} catch (InterruptedException e) {
e.printStackTrace();
}
repaint();
}
}));
}
for (Thread thread : carsThread) {
thread.start();
}
}
@Override
public void paint(Graphics g) {
Graphics otherGraphics = image.getGraphics();
super.paint(otherGraphics);
for (Car car : carsList) {
car.draw(otherGraphics);
}
otherGraphics.setColor(Color.BLACK);
((Graphics2D) otherGraphics).setStroke(new BasicStroke(5));
otherGraphics.drawLine(530, 0, 530, 400);
g.drawImage(image, 0, 0, null);
}
public static void main(String[] args) {
new MyFrame().setVisible(true);
}
}