1、ArrayList的学习
ArrayList构造方法和添加方法
- public ArrayList() 创建一个空的集合对象
- public Boolean add(E e) 将指定的元素追加到此集合的末尾
- public void add(int index,E element) 在此集合的指定位置插入指定元素
1、
import java.util.ArrayList;
public class ArrayListDemo01 {
public static void main(String[] args) {
ArrayList<String> array = new ArrayList<>();
System.out.println(array.add("hello"));
array.add(1,"java");
System.out.println("array:" +array);
}
}
2、
-public Boolean remove(Object o):删除指定的元素,返回删除是否成功
- public E remove(int index):删除指定索引处的元素,返回被删除的元素
- public E set(int index,E element ):删除指定索引处的元素,返回被修改的元素
- public E get(int index):返回索引处的元素
- public int size():返回集合中的元素的个数
import java.util.ArrayList;
public class ArrayListDemo01 {
public static void main(String[] args) {
ArrayList<String> array = new ArrayList<>();
array.add("hello");
array.add("world");
array.add("java");
// array.add(1,"java");
System.out.println(array.set(2,"javaee"));
System.out.println(array.remove("world"));
System.out.println(array.get(1));
System.out.println(array.size());
System.out.println("array"+array);
}
}
输出结果:
java
true
javaee
2
array[hello, javaee]
3、遍历
import java.util.ArrayList;
public class ArrayListDemo02 {
public static void main(String[] args) {
ArrayList<String> array = new ArrayList<>();
array.add("hello");
array.add("world");
array.add("java");
/* System.out.println(array.get(0));
System.out.println(array.get(1));
System.out.println(array.get(2));*/
for (int i=0;i<array.size();i++){
// System.out.println(array.get(i));
String s = array.get(i);
System.out.println(s);
}
}
}
输出
hello
world
java
4、ArrayList 存储学生对象并遍历
import java.util.ArrayList;
public class ArrayListDemo3 {
public static void main(String[] args) {
//创建集合对象
ArrayList<Student> array = new ArrayList<>();
//创建学生对象
Student stu1 = new Student("weblv",30);
Student stu2 = new Student("ljx",23);
//添加学生对象到集合中
array.add(stu1);
array.add(stu2);
//遍历集合,采用通用遍历格式实现
for(int i=0;i<array.size();i++){
Student s = array.get(i);
System.out.println(s.getName() + ','+s.getAge());
}
}
}
输出
weblv,30
ljx,23
5、ArrayList 存储学生对象并遍历(升级)
import java.util.ArrayList;
import java.util.Scanner;
public class ArrayListDemo04 {
public static void main(String[] args) {
ArrayList<Student> array =new ArrayList<Student>();
//调用方法
AddStu(array);
AddStu(array);
AddStu(array);
//输出对象
for (int i=0;i<array.size();i++){
Student s = array.get(i);
System.out.println(s.getName() +',' +s.getAge());
}
}
public static void AddStu(ArrayList<Student> array){
//键盘录入学生对象所需的数据
Scanner sc = new Scanner(System.in);
System.out.println("请输入学生姓名:");
String name = sc.nextLine();
System.out.println("请输入学生年龄");
String age = sc.nextLine();
//创建学生对象,把键盘录入的数据赋值给学生对象的成员变量
Student s = new Student();
s.setName(name);
s.setAge(age);
//集合中添加学生对象
array.add(s);
}
}
请输入学生姓名:
hah
请输入学生年龄
13
请输入学生姓名:
xkx
请输入学生年龄
14
请输入学生姓名:
adq
请输入学生年龄
12
hah,13
xkx,14
adq,12
6、
Alt+Ins 根据自己需要构造方法
2、继承
1、格式:public class 子类名 extends 父类名{}
2、继承的好处和弊端:
好处
- 提高代码复用性(多个类相同的成员可以放到同一个类中)
- 提高了代码的维护性(方法的代码需要修改,修改一处即可)
弊端
- 继承让类之间产生了关系,削弱了子类的独立性
3、继承中变量的访问特点
在子类方法中访问一个变量
- 子类局部范围找——>子类成员范围找—>父类成员范围找(如果都没有,则报错)
4、super关键字
public class Zi extends Fu {
public int age = 20;
public void show(){
int age = 30;
System.out.println(age);
//访问本类的成员变量age
System.out.println(this.age);
//访问父类的成员变量age
System.out.println(super.age);
}
}
5、继承中构造方法的访问特点
子类中所有的构造方法默认都会访问父类中无参的构造方法
- 子类会继承父类中的数据,可能还会使用父类的数据,所以子类初始化之前,一定先完成父类数据的初始化
- 每一个子类构造方法的第一条语句默认都是super
如果父类中没有无参构造方法,只有带参构造方法,怎么办?
- 通过使用super关键字显示的调用父类的带参构造方法
- 在父类中自己提供一个无参的构造方法(推荐)
6、继承中访问成员方法的访问特点
通过子类对象访问一个方法、
- 子类成员范围找
- 父类成员范围找
- 如果都没有则报错
7、方法重写
概述:
- 子类中出现和父类一模一样二点方法声明
方法重写的应用:
- 当子类需要父类的功能,而功能主体子类又有自己的内容十,可以重写父类中的方法,这样,既沿袭了父类的功能,有定义了子类特有的功能
@Override :帮助我们检查方法重写声明的正确性
- 方法重写注意事项:
1、私有方法不能被重写(父类的私有成员子类是不能继承的)
==子类访问权限不能更低(public > 默认(就是直接void ,没有修饰符) > 私有) ==
8、Java中继承的注意事项
- Java类只支持单继承,不支持多继承
- Java类中支持多层继承
9、继承实例
public class Person {
public String name;
public String age;
//无参构造
public Person() {
}
//带参构造
public Person(String name,String age){
this.name = name;
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getAge() {
return age;
}
public void setAge(String age) {
this.age = age;
}
}
public class Students extends Person{
public Students(){
}
public Students(String name,String age){
super(name,age); // 继承父类中的带参方法
}
public void Study(){
System.out.println("我是学生,我爱学习!");
}
}
3、修饰符
1、包
1、概述:就是文件夹,对类进行分类管理
2、定义格式 : package 包名.(多级包用.分开)
2、导包
使用不同包下的类时,简化带包的操作,使用import将其他包导入,并使用其他包下的类
- 格式:import 包名
3、状态修饰符
-
final(最终态):可修饰成员方法,成员变量,类
-
特点:
1、修饰方法:表明该方法是最终方法,不能被重写
2、修饰变量:表明该变量是常量,不能被再次赋值
3、修饰类:表明该类是最终类,不能被继承
final修饰局部变量:
-
变量是基本类型:final修饰指的是基本类型数据值不能发生改变
-
变量是引用类型:final修饰指的是引用类型的地址值不能发生改变,但是地址值里面的内容是可以发生改变的
-
static(静态):可修饰成员方法,成员变量
-
特点:
1、被类的所有对象共享(这也是我们判断是否使用静态变量关键字的条件)
2、可用通过类名调用,也能使用对象名进行调用(推荐使用类名调用)
public class Student01 {
public String name;
public int age ;
public static String university; //
public void show(){
System.out.println(name + "," + age + "," + university);
}
}
public class staticDemo {
public static void main(String[] args) {
Student01.university = "厦门大学";//直接用类中的参数进行赋值,直接通过类名访问,使得默认值为厦门大学
Student01 s1 = new Student01();
s1.name="lwb";
s1.age=10;
//s1.university="厦门大学";
s1.show();
Student01 s2 =new Student01();
s2.name = "ljx";
s2.age = 11;
s2.show();
}
}
输出
lwb,10,厦门大学
ljx,11,厦门大学
static 访问特点
非静态的成员方法:
- 能访问静态的成员变量
- 能访问非静态的成员变量
- 能访问静态的成员方法
- 能访问静态的成员方法
静态的成员方法:
- 能访问静态的成员变量
- 能访问静态的成员方法
静态成员只能访问静态成员
4、多态
1、同一个对象,在不同时刻表现出来的不同形态
猫 cat = new 猫();
也可以 动物 Animal = new 猫();
多态的前提和体现:
- 有继承/实现关系
- 有方法重写
- 有父类引用指向子类对象
2、多态中成员的访问特点
package Test01;
public class Animal {
public int age = 40;
public void eat(){
System.out.println("动物吃东西");
}
}
package Test01;
public class Cat extends Animal {
public int age = 20;
public int weight = 10;
@Override
public void eat() {
System.out.println("猫吃鱼");
}
public void playgame(){
System.out.println("猫捉迷藏");
}
}
package Test01;
public class AnimalDemo {
public static void main(String[] args) {
Animal a = new Cat();
System.out.println(a.age);
a.eat();
//a.playgame(); 会报错,因为Animal中没有该方法
}
}
输出
40
猫吃鱼
- 成员方法:编译看左边,执行看右边
- 成员变量:编译看左边,执行看左边
因为成员方法有重写,而成员变量没有
3、多态的好处和弊端
- 好处:提高了程序的拓展性
具体体现:定义方法时,使用父类作为参数,将来在使用的时候,使用具体子类参与操作(多态只能访问共有的功能)
- 弊端: 泵使用子类的特有功能
4、多态的转型
- 向上转型
从子到父
父类引用指向子类对象 - 向下转型
从父到子
父类引用转为子类对象
package Test01;
public class AnimalDemo {
public static void main(String[] args) {
//多态
Animal a = new Cat(); //向上转型
a.eat();
((Cat) a).playgame();//向下转型
}
}
输出
猫吃鱼
猫捉迷藏
5、抽象类
1、概述
一个没有方法体的方法应该定义为抽象方法,而类中如果有抽象方法,该类必须定义为抽象类
package Test_Abstract;
public abstract class Animal {//定义抽象类
public abstract void eat();//定义抽象方法
}
2、抽象类的特点
- 抽象类和抽象方法必须使用abstract关键字修饰
public **abstract** clss 类名{}
public **abstract** void 方法名();
-
抽象类中不一定有抽象方法,有抽象方法的类一定是抽象类
-
抽象类不能直接实例化
++可以参照多态的方式,通过子类对象实例化,这叫抽象类多态++
-
抽象类的子类
要么重写抽象类中的所有抽象方法
要么是抽象类
3、抽象类的成员特点
- 成员变量(可以是变量,也可以是常量)
- 构造方法(有构造方法,但是不能实例化,构造方法用于子类访问父类数据的初始化)
- 成员方法(可以有抽象方法:限定子类必须完成某些动作;也可以有非抽象方法:提高代码的复用性)
6、接口
1、概述:接口就是一种公用的规范,Java中的接口更多体现在对行为的抽象
2、特点
- 接口用关键字interface修饰
public interface 接口名{}
- 类实现接口用implements表示
public class 类名 implements 接口名{}
- 接口不能实例化
- 接口参照多态的方式,通过实现类对象实例化,这叫接口多态
- 多态的形式:抽象类多态,接口多态
- 多态的前提:有几成或者实现关系;有方法重写;有父类(类/接口)引用指向(子/实现)类对象
- 接口的实现类
要么重写接口中的所有抽象方法
要么是抽象类
3、接口的成员特点
- 成员变量
- 只能是常量
- 默认修饰符**:public static final**
- 构造方法
- 接口没有构造方法,因为接口主要是对行为进行抽象的,是没有具体存在的
- 一个类如果没有父类,默认继承Object类
- 成员方法
- 只能是抽象方法
- 默认修饰符:public abstract
4、类和接口的关系
- 类和类的关系
继承关系,只能单继承,但是可以多层继承
- 类和接口的关系
实现关系,可以单实现,也可以多实现,还可以继承一个类的同时实现多个接口
- 接口和接口的关系
继承关系,可以单继承,也可以多继承
5、抽象类和接口的区别
- 成员区别
- 抽象类---->常量、变量;有构造方法,有抽象方法。也有非抽象方法
- 接口------>常量;抽象方法
- 关系区别
- 类与类--------->继承、单继承
- 类与接口------->实现、可以单实现,也可以多实现
- 接口与接口----->继承,单继承,多继承
- 设计理念的区别
- 抽象类---->对类抽象,包括属性、行为
- 接口------>对行为抽象,主要是行为
/*
门与报警器
*/
public abstract interface Jumpping {
public abstract void Jump();
}
public interface Alram{
void alarm;
}
public abstract class Door(){
public abstract void open();
public abstract void close();
}
public class AkarnDoor extends Door implements Alarm{
public void open(){//重写方法
//...
}
public void close(){//重写方法
//...
}
public void alram(){//重写方法
//...
}
}
6、类名作为形参和返回值
- 方法的形参是类名,其实需要的是该类的对象
- 方法的返回值是类名,其实返回的是该类的对象(需要进行声明对象)
7、接口名作为形参和返回值
- 方法的形参是类名,其实需要的是该接口的对象
- 方法的返回值是类名,其实返回的是该接口的对象(需要进行声明对象)
7、内部类
1、格式
public class 类名{
修饰符 class 类名{
}
}
2、访问特点
- 内部类可以直接访问外部类的成员,包括私有
- 外部类要访问内部类的成员,必须创建对象
3、成员内部类
按照内部类在类中定义的位置不同,可以分为一下两种形式
- 在类的成员位置:成员内部类
- 在类的局部位置:局部内部类
成员内部类,外界如何创建对象使用呢? - 格式:外部类名.内部类名 对象名 = 外部类对象.内部类对象
- 范例:Outer.Inner oi = new Outer().new Inner(;
package InnerOutter;
public class Outer {
private int num = 10;
public class Inner{
private void show(){
System.out.println(num);
}
}
public void method(){//通过外部类调用内部类方法来实现
Inner i = new Inner();
i.show();
}
}
-----------------------------
package InnerOutter;
public class OuterTest {
public static void main(String[] args) {
/* Outer.Inner oi = new Outer().new Inner();
oi.show();*/
Outer o = new Outer();
o.method();
}
}
输出
10
4、局部内部类
局部内部类是在方法中定义的类,所以外界是无法直接访问的,需要在方法内部创建对象并使用该类可以直接访问外部类的成员,也可以访问方法内的局部变量
package InnerOutter;
public class Outer {
private int num = 10;
public void method(){//通过外部类调用内部类方法来实现
int num2 = 20;
class Inner{
public void show(){
System.out.println(num);
System.out.println(num2);
}
}
Inner i = new Inner();
i.show();
}
}
------------------------------------
package InnerOutter;
public class OuterTest {
public static void main(String[] args) {
/* Outer.Inner oi = new Outer().new Inner();
oi.show();*/
Outer o = new Outer();
o.method();
}
}
输出
10
20
5、匿名内部类(局部内部类特殊形式)
- 格式
new 类名或接口名(){
重写方法;
}
本质:是一个继承该类或者实现该接口的子类匿名对象
public interface Inter {
void show();
}
-------------------------------
public class Outer {
public void method(){//
Inter i= new Inter(){
@Override
public void show() {
System.out.println("匿名内部类");
}
};
i.show(); // 调用show方法
}
}
-------------------- ---------
package InnerOutter;
public class OuterTest {
public static void main(String[] args) {
/* Outer.Inner oi = new Outer().new Inner();
oi.show();*/
Outer o = new Outer();
o.method();
}
}
输出
匿名内部类
6、匿名内部类在开发中的使用
package Inner;
public class Cat implements Jumpping {
@Override
public void junp() {
System.out.println("我会跳高");
}
}
----------------------------------
package Inner;
public interface Jumpping {
void junp();
}
====================================
package Inner;
public class JumppingOperator {
public void method(Jumpping j){
j.junp();
}
}
--------------------------------
package Inner;
public class TestDemo {
public static void main(String[] args) {
Jumpping j = new Cat();
j.junp();
JumppingOperator jo = new JumppingOperator();
jo.method(j);
jo.method(new Jumpping() {//直接通过接口实例化对象调用匿名对象类,不用每次都新建一个类
@Override
public void junp() {
System.out.println("我也会跳高了");
}
});
}
}
输出
我会跳高
我会跳高
我也会跳高了
8、API
1、Math
查看文档
2、System
package Math;
public class Math {
public static void main(String[] args) {
System.out.println("开始");
System.exit(0);//中止当前Java虚拟机,非零表示异常
System.out.println("结束");
System.out.println(System.currentTimeMillis());//返回当前时间
}
}
3、Object类中的toString()方法
看方法,选中方法,按下crtl+B
- 建议子类重写object中的toString()方法
通过Alt+Ins中的toString()重写自动生成
4、Object类中的equals()方法
- 建议子类重写object中的equals()方法
通过Alt+Ins中的equals()重写自动生成,把hashmap()方法删除即可
5、Integer 类的概述和使用
- public static Integer valueOf(int i) 返回表示指定的int值的Integer实例
- public static Integer valueOf(String s) 返回一个保存指定值的Integer对象String
package Inter;
public class InterDeno {
public static void main(String[] args) {
Integer i = Integer.valueOf(100);
System.out.println(i);
Integer i1 = Integer.valueOf("100");
System.out.println(i1);
}
}
输出
100
100
5、int和String 的相互转化
- Int----->String
public static String valueOf(int i) 静态方法(String中的方法)
- String------->Int
public static int parseInt(String s)静态方法(Integer类中的方法)
package Inter;
/*
int和String的转换
*/
public class InterDeno {
public static void main(String[] args) {
//Int----->String
//方式1
int number = 100;
String s1 = ""+number;
System.out.println(s1);
//方式2 public static String valueOf(int i) 静态方法
String s2 = String.valueOf(number);
System.out.println(s2);
System.out.println("-----------------");
//String------->Int
String s3 ="100";
//方式一 String----->Integer----->int
Integer i = Integer.valueOf(s3);
//public int intValue()
int x = i.intValue();
System.out.println(x);
//方式2
//public static int parseInt(String s)静态方法
int y = Integer.parseInt(s3);
}
}
6、int和String 的相互转化(字符串转换案例)
package Inter;
import java.util.Arrays;
public class IntegerTest {
public static void main(String[] args) {
//定义一个字符串
String s = "91 27 46 38 50";
//用空格获取每一个元素放在数组中
String[] strArray = s.split(" ");
/* for (int i= 0;i<strArray.length;i++){
System.out.println(strArray[i]);
}*/
//定义一个int数组,把String[]数组中的每一个元素存储到int数组中
int[] arr = new int[strArray.length];
for (int i = 0;i<arr.length;i++){
arr[i] = Integer.parseInt(strArray[i]);
}
//对数组进行排序
Arrays.sort(arr);
//把排序后的int数组中的元素进行拼接得到一个字符串,用StringBuilder实现
StringBuilder sb = new StringBuilder();
for (int i = 0;i<arr.length;i++){
if(i == arr.length-1){
sb.append(arr[i]);
}else {
sb.append(arr[i]).append(" ");
}
}
String result = sb.toString();
System.out.println(result);
}
}
输出
27 38 46 50 91
6、自动拆箱和装箱
- 装箱:把基本数据类型转换为对应的包装类类型
Integer i= Integer.valueOf(100);//手动装箱
Integer ii = 100;//自动装箱
- 拆箱:把包装类类型转化为对应的基本数据类型
ii = ii.valueOf()+200;//手动装箱
ii += 200;//自动装箱 和上面语句一样结果
//i = i+200;i+200自动拆箱;i = i+200;自动装箱
在使用包装类类型的时候,如果做操作,最好先判断是否为null,只要是对象,在使用前就必须进行不为null的判断
4、Date
1、SimpleDateFormat
- y 年
- M 月
- d 日
- H 时
- m 分
- s 秒
2、SimpleDateFormat格式化和解析日期
- 格式化(从Date到String)
public final String format(Date date):将日期格式化成日期/时间字符串
- 解析(从String到Date)
public Date parse(String source):从给定字符串的开始解析文本以生成日期
package Date;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
public class DateDemo {
public static void main(String[] args) throws ParseException {
Date d1 = new Date();
SimpleDateFormat sdf = new SimpleDateFormat("yyyy年MM月dd日 HH时mm分ss秒");
String s = sdf.format(d1);
System.out.println(s);
String s1 = "2020-03-16 11:11:11";
SimpleDateFormat sdf1 = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
Date p = sdf1.parse(s1);
System.out.println(p);
}
}
输出
2020年03月16日 16时16分33秒
Mon Mar 16 11:11:11 CST 2020
3、日期工具类案例
- 需求:定义一个工具类DateUtils,包含两个方法,把日期转换为指定格式的字符串;把字符串解析为指定格式的日期,在测试类中调用实现
package Date;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
public class DateUtils {
public DateUtils() {
}
public static String dateToString(Date date, String format){
SimpleDateFormat sdf = new SimpleDateFormat(format);//按照传入格式创建对象
String s = sdf.format(date); // 把传入的日期转化成指定格式的字符串
return s;
}
public static Date stringToDater(String s, String format) throws ParseException {
SimpleDateFormat sdf = new SimpleDateFormat(format);
Date p = sdf.parse(s); //Artl+Enter创建抛出异常
return p;
}
}
//测试类
package Date;
import java.text.ParseException;
import java.util.Date;
public class DateDemo {
public static void main(String[] args) throws ParseException {
Date d1 = new Date();
String s1 =DateUtils.dateToString(d1,"yyyy年MM月dd日 HH:mm:ss");
System.out.println(s1);
String s2= DateUtils.dateToString(d1, "yyyy年MM月dd日");
System.out.println(s2);
System.out.println("--------------");
String s = "2012-01-01 12:12:12";
Date date = DateUtils.stringToDater(s, "yyyy-MM-dd HH:mm:ss");
System.out.println(date);
}
}
输出
2020年03月16日 16:40:00
2020年03月16日
--------------
Sun Jan 01 12:12:12 CST 2012
4、Calendar类
==Calendar rightNow = Calendar.getlnstance();==getlnstance()获取Calendar对象,其日历字段已使用当前日期和时间初始化
package Calendar;
import java.util.Calendar;
public class CalendarDemo {
public static void main(String[] args) {
Calendar c = Calendar.getInstance();
int i = c.get(Calendar.YEAR);
int i1 = c.get(Calendar.MONTH) + 1;
int i2 = c.get(Calendar.DATE);
System.out.println(i+"年"+i1+"月");
}
}
输出
2020年3月16日
5、Calendar类中的add,set方法
package Calendar;
import java.util.Calendar;
public class CalendarDemo {
public static void main(String[] args) {
Calendar c = Calendar.getInstance();
int i = c.get(Calendar.YEAR);
int i1 = c.get(Calendar.MONTH) + 1;
int i2 = c.get(Calendar.DATE);
System.out.println(i+"年"+i1+"月"+i2+"日");
System.out.println("-------------");
c.add(Calendar.YEAR,-3);// .add(int field,int amount)将指定的时间量加上或减去给定的日历字段
int k = c.get(Calendar.YEAR);
int k1 = c.get(Calendar.MONTH) + 1;
int k2 = c.get(Calendar.DATE);
System.out.println(k+"年"+k1+"月"+k2+"日");
System.out.println("-------------");
c.set(2058,11,11);// .set(int year,int month,int day)设置当前的年日月
int l = c.get(Calendar.YEAR);
int l1 = c.get(Calendar.MONTH) + 1; //月是从0开始算起的
int l2 = c.get(Calendar.DATE);
System.out.println(l+"年"+l1+"月"+l2+"日");
}
}
输出
2020年3月16日
-------------
2017年3月16日
-------------
2058年12月11日
5、Calendar类案例分析(计算二月天数)
package Calendar;
import java.util.Calendar;
import java.util.Scanner;
public class Cal {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
System.out.println("请输入你要查询的年份:");
int year = sc.nextInt();
Calendar c = Calendar.getInstance();
c.set(year,2,1);
c.add(Calendar.DATE,-1);
int date = c.get(Calendar.DATE);
System.out.println(year+"年的二月份有"+date+"天");
}
}
输出
请输入你要查询的年份:
2048
2048年的二月份有29天
9、异常
1、异常处理
-try…catch…
//格式
try {
可能出现异常的代码;
}catch (异常类名 变量名){
异常的处理代码;
}
执行流程:
程序从try里面的代码开始执行,出现异常,会自动生成一个异常类对象,该异常对象将被提交给Java运行时系统,当Java运行时系统接收到异常对象时,会到catch中找匹配的异常类,找到后进行异常处理,执行完毕后,程序还可以继续往下执行。
package Exception;
public class Exception {
public static void main(String[] args) {
System.out.println("开始");
method();
System.out.println("结束");
}
public static void method(){
try {
int[] arr = {1,2,3};
System.out.println(arr[3]); //new了一个异常
}catch (ArrayIndexOutOfBoundsException e){//匹配异常输出
//System.out.println("访问索引越界了");
e.printStackTrace();//返回异常信息
}
}
}
- Throwable
方法名 | 说明 |
---|---|
public String getMessage() | 返回此throwable的详细信息字符串 |
public String toString() | 返回此可抛出的简短描述 |
public void printStackTrace() | 把异常信息输出到控制台 |
- throws(处理一些没有权限的异常处理)
throws 异常类名;//这个格式是跟在方法的括号后面的
package Exception;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
public class Exception {
public static void main(String[] args) {
System.out.println("开始");
try { //用Artl+Enter添加异常方法
method2();
} catch (ParseException e) {
e.printStackTrace();
}
System.out.println("结束");
}
/* //运行时异常
public static void method() throws ArrayIndexOutOfBoundsException{
int[] arr = {1,2,3};
System.out.println(arr[3]); //new了一个异常
}*/
//编译异常
public static void method2() throws ParseException { //依然需要try....catch进行异常处理,仅仅是将异常抛出
String s = "2020=03-18";
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
Date d = sdf.parse(s);
System.out.println(d);
}
}
输出
开始
结束
java.text.ParseException: Unparseable date: "2020=03-18"
at java.text.DateFormat.parse(DateFormat.java:366)
at Exception.Exception.method2(Exception.java:28)
at Exception.Exception.main(Exception.java:11)
- 编译时异常必须要进行处理,两种处理方法:try…catch或者throws,如果采用throws,则谁调用谁处理
- 运行时异常可以不处理,出现问题后,需要我们回来修改代码
3、自定义异常
public class 异常类名 extends Exception{
无参构造
带参构造
}
package Exception;
public class ScoreException extends Exception {
public ScoreException() {
}
public ScoreException(String message) {
super(message);
}
}
package Exception;
import java.lang.*;
public class Teacher {
public void checkScore(int score) throws ScoreException{
if (score < 0 || score >100){
throw new ScoreException("你输入的分数应该在0~100之间"); //自定义抛出异常
}else {
System.out.println("分数正常");
}
}
}
package Exception;
import java.util.Scanner;
public class TeacherTest {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
System.out.println("请输入分数:");
int score = sc.nextInt();
Teacher t = new Teacher();
try {
t.checkScore(score);
} catch (ScoreException e) {
e.printStackTrace();
}
}
}
输出
请输入分数:
199
Exception.ScoreException: 宁输入的分数应该在0~100之间
at Exception.Teacher.checkScore(Teacher.java:7)
at Exception.TeacherTest.main(TeacherTest.java:13)
throw和throws的区别
throw | throws |
---|---|
在方法声明后面,跟的时异常类名 | 用在方法体内,跟的是异常对象名 |
表示出现异常的一种可能性,并不一定会发生这种异常 | 执行throw一定抛出某种移异常 |
表示抛出异常,由该方法的调用者来处理 | 表示抛出异常,由方法体内的语句处理 |
10、集合
1、Collection
概述
- 是单例集合的顶层接口,他表示一组对象,这些对象也称为Collection的元素
- JDK不提供此接口的任何直接实现,它提供更具体的子接口(如Set和List)实现
创建Collection集合的对象
- 多态的方式
- 具体的实现类ArrayList
package Collection;
import java.util.ArrayList;
import java.util.Collection;
public class Collection01 {
public static void main(String[] args) {
Collection<String> c = new ArrayList<>();
c.add("hello");
c.add("world");
System.out.println(c);
}
}
输出
[hello, world]
- void clear() 从此集合中删除所有元素(可选操作)。
- boolean add(E e) 确保此集合包含指定的元素(可选操作)。
- boolean remove(Object o) 从该集合中删除指定元素的单个实例(如果存在)(可选操作)。
- int size() 返回此集合中的元素数。
- boolean isEmpty() 如果此集合不包含元素,则返回 true 。
- boolean contains(Object o) 如果此集合包含指定的元素,则返回 true 。
Alt+7可以打开看类的窗口
2、Collection集合的遍历
Iterator:迭代器,集合的专用遍历方式
- Iterator iterator():返回此集合中元素的迭代器,通过集合的iterator()方法的到
- 迭代器是通过iterator()方法得到的,所以我们说它是依赖于集合而存在的
常用方法
- E next() 返回迭代中的下一个元素。
- boolean hasNext() 如果迭代具有更多元素,则返回 true 。
import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;
public class Collection01 {
public static void main(String[] args) {
Collection<String> c = new ArrayList<>();
c.add("hello");
c.add("world");
c.add("java");
Iterator<String> it = c.iterator();
while (it.hasNext()){
String s = it.next();
System.out.println(s);
}
}
}
输出
hello
world
java
3、Collection集合的遍历案例
package Collection;
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;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
}
package Collection;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;
public class CollectionStudent {
public static void main(String[] args) {
Collection<Student> sc = new ArrayList<Student>();
Student s1 = new Student("张三",19);
Student s2 = new Student("李四",20);
Student s3 = new Student("陈伍",22);
sc.add(s1);
sc.add(s2);
sc.add(s3);
Iterator<Student> it = sc.iterator();
while (it.hasNext()){
Student s = it.next();
System.out.println(s.getName() +","+ s.getAge());
}
}
}
输出
张三,19
李四,20
陈伍,22
4、List集合
概述
- 有序集合(也称序列),用户可以精确控制列表中每个元素的插入位置。用户可以通过整数索引访问元素,并搜索列表中的元素
- 与Set集合不同,列表通常允许重复的元素
集合特点
- 有序:存储和取出的元素顺序一致
- 可重复:存储的元素可以重复
5、并发修改异常
并发修改异常
- ConcurrentModificationException
产生原因
- 迭代器遍历的过程中,通过集合对象修改了集合中的元素,造成了迭代器获取元素中判断预期修改值和实际修改值不一致
解决方案
- 用for循环遍历,然后用集合对象做对应的操作即可
6、ListIterator列表迭代器
- 通过List集合的listlterator()方法得到,所以说它是List集合特有的迭代器
- public interface ListIterator
extends Iterator用于允许程序员沿任一方向遍历列表的列表的迭代器,在迭代期间修改列表,并获取列表中迭代器的当前位置
boolean hasNext() | 如果此列表迭代器在向前方向遍历列表时具有更多元素,则返回 true 。 |
---|---|
boolean hasPrevious() | 如果此列表迭代器在相反方向遍历列表时具有更多元素,则返回 true 。 |
E next() | 返回列表中的下一个元素,并且前进光标位置。 |
int nextIndex() | 返回由后续调用返回的元素的索引 next() 。 |
E previous() | 返回列表中的上一个元素,并向后移动光标位置。 |
7、增强for循环(简化数组和Collection集合的遍历)
- 实现Iterable接口的类允许其对象成为增强for语句的目标
- 它是JDK5之后出现的,其内部原理是一个内部Iterator迭代器
//格式
for(元素数据类型 变量名:数组或者Collection集合){
//在此处使用变量即可,该变量就是元素
}
范例:
int[] arr ={1,2,3,4};
for(int i : arr){
System.out.println(i);
}
package ForDemo;
import java.util.ArrayList;
import java.util.List;
public class For01 {
public static void main(String[] args) {
int[] arr = {1, 2, 3, 5, 4};
for (int i : arr) {
System.out.println(i);
}
System.out.println("------------");
String[] strArr = {"hello", "java"};
for (String s : strArr) {
System.out.println(s);
}
System.out.println("----------");
List<String> lis = new ArrayList<String>();
lis.add("hello");
lis.add("world");
for (String s : lis) {
System.out.println(s);
}
System.out.println("----------");
//内部是个Iterator迭代器,如果抛出并发修改异常,则为迭代器
for (String s : lis) {
if (s.equals("world")) {
lis.add("java");
}
}
}
}
输出
1
2
3
5
4
------------
hello
java
----------
hello
world
----------
Exception in thread "main" java.util.ConcurrentModificationException
at java.util.ArrayList$Itr.checkForComodification(ArrayList.java:909)
at java.util.ArrayList$Itr.next(ArrayList.java:859)
at ForDemo.For01.main(For01.java:30)
8、LinkedList集合的特有功能
void addFirst(E e) | 在该列表开头插入指定的元素。 |
---|---|
void addLast(E e) | 将指定的元素追加到此列表的末尾。 |
getFirst() | 返回此列表中的第一个元素。 |
E getLast() | 返回此列表中的最后一个元素。 |
removeFirst() | 从此列表中删除并返回第一个元素。 |
removeLast() | 从此列表中删除并返回最后一个元素。 |
9、Set(不包含重复元素的集合)。
Set
- 没有带索引的方法,所以不能使用普通for循环遍历
- HashSet:对集合的迭代顺序不作而任何保证
package List;
import java.util.HashSet;
import java.util.Set;
public class SetDemo {
public static void main(String[] args) {
Set<String> set = new HashSet<String>();
set.add("hello");
set.add("hello");
set.add("hello");
for (String s :set){
System.out.println(s);
}
}
}
输出
hello
10、哈希值(是JDK根据对象的地址或者字符串或者数字算出来的int类型的数值)
- int hashCode() 返回对象的哈希码值。
特点
public class HashDemo {
public static void main(String[] args) {
Student s1 = new Student("刘德华",45);
//同一个对象多次调用hashCode()方法返回的哈希值是相同的
System.out.println(s1.hashCode());
System.out.println(s1.hashCode());
//默认情况下不同对象的哈希值是不同的
//通过方法重写,可以实现不同对象的哈希值是相同的
Student s2 = new Student("刘德华",45);
System.out.println(s2.hashCode());
}
}
输出
356573597
356573597
1735600054
11、HashSet集合概述和特点
特点
- 底层结构是哈希表
- 对集合的迭代顺序不做任何保证,也就是说不保证存储和取出的元素一致
- 没有带索引的方法,所以不能使用普用for循环遍历
- 由于是Set集合,所以是不包含重复元素的集合
12、HashSet集合保证元素唯一性源码分析
- 要保证元素唯一性,需要重写hashCode()和equals()方法
- (自动生成即可,用Alt+Ins中的hashCode()和equals())
11、LinkedHashSet集合概述和特点
- 哈希表和链表实现的Set接口,具有可预测的迭代次序
- 由链表保证元素有序,也就是说元素的存储和取出顺序是一致的
- 由哈希表保证元素唯一,也就是说没有重估的元素
12、TreeSet集合概述和特点
- 元素有序:这里的顺序不是指存储和取出的顺序,而是按照一定的规则进行排序,具体排序方法取决于构造方法
TreeSet():根据其元素的自然顺序进行排序
TreeSet(Comparator comparator):根据指定的比较器进行排序
- 没有带索引的方法,所以不能使用普通for循环遍历
- 由于是Set集合,所以不包含重复元素的集合
package Set;
import java.util.TreeSet;
public class TreeSetDemo {
public static void main(String[] args) {
//这里不能用int,要用包装类型Integer
TreeSet<Integer> tr = new TreeSet<Integer>();
tr.add(15);
tr.add(40);
tr.add(30);
tr.add(35);
tr.add(30);
for (Integer i:tr){//自然排序,且不包含重复元素
System.out.println(i);
}
}
}
输出
15
30
35
40
14、自然排序Compareable的使用
package Set;
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;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
@Override
public int compareTo(Student s) {//按照年龄从小到大排序
//return 1;且为升序
//return 0;认为是重复元素,不会再添加,只能输出一个
//return -1;用降序存储
int num = this.age-s.age;//升序排列,判断大于还是小于或是等于0
int num2 = num==0?this.compareTo(s.name):num;//年龄相同时,按照姓名的字母排序
return num2;
}
}
package Set;
import java.util.TreeSet;
public class TreeSetDemo {
public static void main(String[] args) {
//这里不能用int,要用包装类型Integer
TreeSet<Student> tr = new TreeSet<Student>();
Student s1 = new Student("西施",24);
Student s2 = new Student("貂蝉",27);
Student s3 = new Student("杨玉环",23);
Student s4 = new Student("王昭君",30);
Student s5 = new Student("林东",30);
tr.add(s1);
tr.add(s2);
tr.add(s3);
tr.add(s4);
for (Student s : tr){
System.out.println(s.getName()+","+s.getAge());
}
}
}
输出
杨玉环,23
西施,24
貂蝉,27
林东,30
王昭君,30
- 用TreeSet集合存储自定义对象,无参构造方法使用的是自然排序对元素进行排序的
- 自然排序,就是让元素所属的类实现Compareable接口,重写compareTo(To)方法
- 重写方法时,一定要注意排序规则必须按照要求的主要条件和次要条件来写
package Set;
import java.util.Comparator;
import java.util.TreeSet;
public class TreeSetDemo {
public static void main(String[] args) {
/* //这里不能用int,要用包装类型Integer
TreeSet<Student> tr = new TreeSet<Student>();
Student s1 = new Student("西施",24);
Student s2 = new Student("貂蝉",27);
Student s3 = new Student("杨玉环",23);
Student s4 = new Student("王昭君",30);
Student s5 = new Student("林东",30);
tr.add(s1);
tr.add(s2);
tr.add(s3);
tr.add(s4);
for (Student s : tr){
System.out.println(s.getName()+","+s.getAge());
}*/
TreeSet<Student> ts = new TreeSet<Student>(new Comparator<Student>() {//带参构造
@Override
public int compare(Student s1, Student s2) {
int num = s1.getAge()-s2.getAge(); //因为在Student中变量被private修饰
int num2 = num==0?s1.getName().compareTo(s2.getName()):num;
return num2;
}
});
Student s1 = new Student("西施",24);
Student s2 = new Student("貂蝉",27);
Student s3 = new Student("杨玉环",23);
Student s4 = new Student("王昭君",30);
Student s5 = new Student("林东",30);
ts.add(s1);
ts.add(s2);
ts.add(s3);
ts.add(s4);
ts.add(s5);
for (Student s : ts){
System.out.println(s.getName()+","+s.getAge());
}
}
}
输出
杨玉环,23
西施,24
貂蝉,27
林东,30
王昭君,30
12、成绩排序案例
需求:用TreeSet集合存储多个学生信息(姓名,语文成绩,数学成绩),并遍历该集合,要求:按照总分从高到低排序
package SetDemo;
import java.util.Comparator;
import java.util.TreeSet;
public class SetTest {
public static void main(String[] args) {
//使用比较器排序进行排序
TreeSet<Student> ts = new TreeSet<Student>(new Comparator<Student>() {
@Override
public int compare(Student s1, Student s2) {
//int num = (s2.getCnScore()+s2.getMathScore())-(s1.getCnScore()+s1.getMathScore());
//主要条件
int num = s2.getSum() - s1.getSum();
//次要条件,保证学生都能存入集合中
int num2 = num == 0 ? s1.getCnScore() - s2.getCnScore() : num;//总分不同各科不同也要存入
int num3 = num2 == 0 ? s1.getName().compareTo(s2.getName()) : num2;//总分,各科相同,人名不同也能存入集合
return num3;
}
});
Student s1 = new Student("张三", 95, 99);
Student s2 = new Student("李四", 96, 90);
Student s3 = new Student("王五", 91, 94);
Student s4 = new Student("陈六", 93, 97);
ts.add(s1);
ts.add(s2);
ts.add(s3);
ts.add(s4);
for (Student s : ts) {
System.out.println(s.getName() + ",总分为" + (s.getSum()));
}
}
}
输出
张三,总分为194
陈六,总分为190
李四,总分为186
王五,总分为185
13、生成10个0-20的随机数(不重复的,且无序的用HashSet;有序用TreeSet)
package SetDemo;
import java.util.HashSet;
import java.util.Random;
import java.util.Set;
public class Setdemo {
public static void main(String[] args) {
Set<Integer> ts = new HashSet<Integer>();
Random r = new Random();
while(ts.size()<=10){
ts.add(r.nextInt(20)+1);
}
for (Integer i:ts){
System.out.println(i);
}
}
}
输出
18
2
4
5
7
8
9
10
11
12
15
8、泛型
- 本质:参数化类型(将类型由原来的具体的类型参数化,然后在使用/调用时传入具体的类型)
- 好处:把运行使其的问题提前到了编译期间;避免了强制类型转换
1、泛型类
定义格式
- 格式:修饰符class 类名<类型>{}
- 范例:public class Gender{}(T可以随意写任意表示,常见的T,E,K,L等形式额参数常用于表示泛型)
//通过一个类就可以生成很多不同类型的对象
package Gen;
public class Generic<T> {
private T t;
public T getT() {
return t;
}
public void setT(T t) {
this.t = t;
}
}
package Gen;
public class GenericDemo {
public static void main(String[] args) {
Generic<String> g1 = new Generic<String>();
g1.setT("刘德华");
System.out.println(g1.getT());
System.out.println("-----------");
Generic<Integer> g2 = new Generic<Integer>();
g2.setT(30);
System.out.println(g2.getT());
}
}
输出
刘德华
-----------
30
2、泛型方法
定义格式:
- 修饰符<类型>返回值类型 方法名(类型 变量名){}
- 范例:public void show(T t){}
package Gen;
/*//泛型类改进
public class Generic<T>{
public void show(T t){
System.out.println(t);
}
}*/
//泛型方法改进
public class Generic<T>{
public <T> void show(T t){
System.out.println(t);
}
}
package Gen;
public class GenericDemo {
public static void main(String[] args) {
Generic g = new Generic();
g.show("林东");
g.show(45);
g.show(true);
g.show(13.45);
}
}
输出
林东
45
true
13.45
2、泛型接口
定义格式
- 格式:修饰符interface 接口名<类型>{}
- 范例:public interface Generic{}
package Gen;
public class Generic<T> implements Generic01<T>{
@Override
public void show(T t) {
System.out.println(t);
}
}
package Gen;
public interface Generic01<T> {
void show(T t);
}
package Gen;
public class GenericDemo {
public static void main(String[] args) {
Generic<String> g = new Generic<String>();
g.show("zhang");
Generic<Integer> g2 = new Generic<Integer>();
g2.show(45);
}
}
输出
zhang
45
3、通配符
- 类型通配符:<?>
- List<?>:表示元素类型未知的List,他的元素可以匹配任何的类型
- 这种带通配符的List仅表示它是各种泛型List的父类,并不能把元素添加其中
- 类型通配符上限:<?extends类型>
- List<?extends Number>:他表示的类型是Number或者子类型
- 类型通配符下限:<?super类型>
- List<?super Number>:他表示的类型是Number或者父类型
package Gen;
import java.util.ArrayList;
import java.util.List;
public class GenericDemo {
public static void main(String[] args) {
List<?> l1 = new ArrayList<Object>();
List<?> l2 = new ArrayList<Number>();
List<?> l3 = new ArrayList<Integer>();
//类型通配符==上限==:<?extends类型>
List<? extends Number> l4= new ArrayList<Number>();
List<? extends Number> l5= new ArrayList<Integer>();
//List<? extends Number> l6= new ArrayList<Object>();报错
//类型通配符==下限==:<?super类型>
List<? super Number> l7 = new ArrayList<Object>();
List<? super Number> l8 = new ArrayList<Number>();
//List<? super Number> l9 = new ArrayList<Integer>();报错
}
}
4、可变参数
(可变参数又称参数个数可变,用作方法的形参出现,那么方法参数个数就是可变的了)
- 格式:修饰符 返回类型 方法名(数据类型…变量名)
- 范例:public static int sum (int…a){}
1.可变参数注意事项
- 这里的变量其实是一个数组
- 如果一个方法有多个参数,包含可变参数,可变参数要放在最后
package Gen;
public class GenericDemo {
public static void main(String[] args) {
System.out.println(sum(10,20,30));
System.out.println(sum(10,20,30,60,70));
System.out.println(sum(10,20,30,40,50,70,80));
System.out.println(sum(10,20,30,40,60,90,100,1000));
}
public static int sum(int b,int... a) {
int sum = 0;
for (int i : a) {
sum = i + sum;
}
return sum;
}
}
输出
60
190
300
1350
2.可变参数的使用
Arrays工具类中有一个静态方法:
- public static List aList(T…a):返回由指定数组支持的固定大小的列表
- 返回的集合不能做增删操作,可以做修改操作
List接口中有一个静态方法:
- public static List of(E…elements):返回包含任意数量元素的不可变列表
- 返回的集合不能做增删改操作
Set接口中有一个静态方法:
- public static Set of(E…elements):返回一个包含任意数量元素的不可变集合
- 返回的集合不能做增删操作,没有修改的方法
- 在给元素的时候,不能给重复的元素
9、Map集合概述和使用
1、Map集合概述
- Interface Map<K,V> K:键的类型 V:值的类型
- 将键值映射到值的对象;不能包含重复的键;每个键可以映射到最多一个值
2、Map集合基本功能
方法 | 说明 |
---|---|
V put(K key, V value) | 将指定的值与该映射中的指定键相关联(可选操作)。 |
V put(K key, V value) | 将指定的值与该映射中的指定键相关联(可选操作)。 |
int size() | 返回此地图中键值映射的数量。 |
boolean isEmpty() | 如果此映射不包含键值映射,则返回 true 。 |
void clear() | 从该地图中删除所有的映射(可选操作)。 |
boolean containsKey(Object key) | 如果此映射包含指定键的映射,则返回 true 。 |
boolean containsValue(Object value) | 如果此映射将一个或多个键映射到指定的值,则返回 true 。 |
3、Map集合的获取功能
方法 | 说明 |
---|---|
V get(Object key) | 根据键获取值 |
Set keySet() | 获取所有键的集合 |
Collection values() | 获取所有值的集合 |
Set<Map.Entry<K,V>> entrySet() | 获取所有键值对对象的集合 |
package Map;
import java.util.Collection;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
public class MapDemo1 {
public static void main(String[] args) {
Map<String,Integer> map = new HashMap<String,Integer>();
map.put("刘德华",45);
map.put("chen",45);
map.put("zhasng",45);
System.out.println(map);
System.out.println("------");
System.out.println(map.get("chen"));
System.out.println("------");
Set<String> keySet = map.keySet();
for (String s : keySet){
System.out.println(s);
}
System.out.println("------");
Collection<Integer> values = map.values();
for (Integer k:values){
System.out.println(k);
}
}
}
输出
{chen=45, 刘德华=45, zhasng=45}
------
45
------
chen
刘德华
zhasng
------
45
45
45
4、Map集合的遍历(一)
Set<Map.Entry<K,V>> entrySet() , 获取所有键值对对象的集合
package Map;
import java.util.Collection;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
public class MapDemo1 {
public static void main(String[] args) {
Map<String,Integer> map = new HashMap<String,Integer>();
map.put("刘德华",45);
map.put("chen",45);
map.put("zhasng",45);
Set<Map.Entry<String, Integer>> entrySet = map.entrySet();
for (Map.Entry<String, Integer> s:entrySet){
//根据键值对对象获取键和值
System.out.println(s.getKey()+","+s.getValue());
}
}
}
5、Map集合的遍历案例
package Map;
import javax.lang.model.element.NestingKind;
import java.util.*;
public class MapDemo1 {
public static void main(String[] args) {
Map<String, Student> map = new HashMap<String, Student>();
Student s1 = new Student("Jude", "15");
Student s2 = new Student("Timi", "19");
Student s3 = new Student("Meimei", "17");
Student s4 = new Student("xiaoxiao", "16");
map.put("001", s1);
map.put("002", s2);
map.put("003", s3);
map.put("004", s4);
//1、键找值
Set<String> ms = map.keySet();//获取键的集合
for (String key:ms){
Student value = map.get(key);
System.out.println(key+","+value.getName()+","+ value.getAge());
}
System.out.println("----------");
//2、键值对对象找键和值
Set<Map.Entry<String,Student>> set = map.entrySet();
for (Map.Entry<String,Student> s : set) {
String key = s.getKey();
Student value = s.getValue();
//注意value是对象,要用get方法获取名字和年龄
System.out.println(key + "," + value.getName()+","+value.getAge());
}
}
}
输出
001,Jude,15
002,Timi,19
003,Meimei,17
004,xiaoxiao,16
----------
001,Jude,15
002,Timi,19
003,Meimei,17
004,xiaoxiao,16
- 需求:创建一个HashMap集合,存储三个键值对集合,每一个键值对元素的键是String,值是ArrayList,每一个ArrayList的元素是String,并遍历
package Map;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Set;
public class ArrayList01 {
public static void main(String[] args) {
HashMap<String,ArrayList<String>> hm=new HashMap<String,ArrayList<String>>();
ArrayList<String> array1 = new ArrayList<String>();
array1.add("赵云");
array1.add("诸葛亮");
ArrayList<String> array2 = new ArrayList<String>();
array2.add("唐僧");
array2.add("孙悟空");
ArrayList<String> array3 = new ArrayList<String>();
array3.add("武松");
array3.add("鲁智深");
hm.put("三国演义",array1);
hm.put("西游记",array2);
hm.put("水浒传",array3);
Set<String> keySet = hm.keySet();//先获得键集合
for (String key :keySet){//遍历键集合获得值
System.out.println(key);
ArrayList<String> value = hm.get(key);
for (String t :value){遍历值输出
System.out.println("\t"+t);
}
}
}
}
输出
水浒传
武松
鲁智深
三国演义
赵云
诸葛亮
西游记
唐僧
孙悟空
10、Collections概述和使用
- static <T extends Comparable<? super T>>
void sort(List list) 根据其元素的natural ordering按照升序排列指定的列表。 - static void reverse(List<?> list) 反转指定列表中元素的顺序。
- static void shuffle(List<?> list) 使用默认的随机源随机排列指定的列表。
斗地主案例实现
package DouDizhu;
import java.util.ArrayList;
import java.util.Collections;
public class PokerDemo {
public static void main(String[] args) {
ArrayList<String> array = new ArrayList<String>();
//定义花色
String[] colors = {"♦", "♣", "♠", "♥"};
//定义数子
String[] numbers = {"2", "3", "4", "5", "6", "7", "8", "9", "10", "J", "Q", "K", "A"};
for (String color : colors) {
for (String number : numbers) {
//装入牌盒
array.add(color + number);
}
}
array.add("小王");
array.add("大王");
//洗牌
Collections.shuffle(array);
ArrayList<String> xiaoArray = new ArrayList<String>();
ArrayList<String> daArray = new ArrayList<String>();
ArrayList<String> changArray = new ArrayList<String>();
ArrayList<String> dpArray = new ArrayList<String>();
for (int i = 0; i < array.size(); i++) {//f发牌
String poker = array.get(i);
if (i >= array.size() - 3) {
dpArray.add(poker);
} else if (i % 3 == 0) {//有多少人就对多少人取余
xiaoArray.add(poker);
} else if (i % 3 == 1) {
daArray.add(poker);
} else if (i % 3 == 2) {
changArray.add(poker);
}
}
//看牌
lookPoker("张飞", xiaoArray);
lookPoker("关羽", daArray);
lookPoker("刘备", changArray);
lookPoker("底牌", dpArray);
}
public static void lookPoker(String name, ArrayList<String> array) {
System.out.print(name + "的牌是:");
for (String poker : array) {
System.out.print(poker + " ");
}
System.out.println();
}
}
输出
张飞的牌是:♠Q ♥A ♣5 ♦9 ♣6 ♥6 大王 ♣4 ♦2 ♦3 ♣10 ♦Q ♠4 ♦J ♣K ♥Q ♦A
关羽的牌是:♦4 ♦5 ♣Q ♠6 ♥8 ♣J ♠A ♦6 ♠2 ♥J ♥7 ♥2 ♦K ♥5 ♦7 ♥10 ♣7
刘备的牌是:♥K ♣3 ♥4 ♠7 ♦8 ♣9 ♦10 小王 ♣8 ♥9 ♠10 ♣2 ♠5 ♠J ♠K ♥3 ♣A
底牌的牌是:♠9 ♠3 ♠8
斗地主案例升级实现(对牌排序)
package DouDizhu;
import java.util.*;
public class PokerDemo {
public static void main(String[] args) {
HashMap<Integer, String> hm = new HashMap<Integer, String>();
ArrayList<Integer> array = new ArrayList<Integer>();
//定义花色
String[] colors = {"♦", "♣", "♠", "♥"};
//定义数子
String[] numbers = {"2", "3", "4", "5", "6", "7", "8", "9", "10", "J", "Q", "K", "A"};
int index = 0;
for (String number : numbers) {//注意这里不能先花色再数字,不然会排序错误
for (String color : colors) {
hm.put(index, color + number);
array.add(index);//
index++;
}
}
hm.put(index, "大王");
array.add(index);
index++;
hm.put(index, "小王");
array.add(index);
//洗牌
Collections.shuffle(array);
TreeSet<Integer> xiaoset = new TreeSet<Integer>();
TreeSet<Integer> daset = new TreeSet<Integer>();
TreeSet<Integer> changset = new TreeSet<Integer>();
TreeSet<Integer> dpset = new TreeSet<Integer>();
for (int i = 0; i < array.size(); i++) {//f发牌
int x = array.get(i);
if (i >= array.size() - 3) {
dpset.add(x);
} else if (i % 3 == 0) {//有多少人就对多少人取余
daset.add(x);
} else if (i % 3 == 1) {
changset.add(x);
} else if (i % 3 == 2) {
xiaoset.add(x);
}
}
//看牌
lookPoker("张飞", xiaoset, hm);
lookPoker("关羽", daset, hm);
lookPoker("刘备", changset, hm);
lookPoker("底牌", dpset, hm);
}
//定义看牌方法,遍历TreeSet集合,获取编号,到HashMap集合找对应的牌
public static void lookPoker(String name, TreeSet<Integer> ts, HashMap<Integer, String> hm) {
System.out.print(name + "的牌是:");
for (Integer key : ts) {
String poker = hm.get(key);
System.out.print(poker + " ");
}
System.out.println();
}
}
输出
张飞的牌是:♦2 ♣2 ♣5 ♥5 ♠7 ♦8 ♣9 ♠9 ♠10 ♠J ♥J ♣Q ♠Q ♣K ♣A ♠A ♥A
关羽的牌是:♠4 ♦5 ♠6 ♥6 ♥7 ♣8 ♠8 ♦9 ♥9 ♦10 ♦J ♣J ♦Q ♥Q ♠K ♥K 大王
刘备的牌是:♠2 ♥2 ♦3 ♣3 ♠3 ♥3 ♦4 ♣4 ♥4 ♦6 ♦7 ♥8 ♣10 ♥10 ♦K ♦A 小王
底牌的牌是:♠5 ♣6 ♣7
11、File
1、File概述和构造方法
1.文件和目录路径名的抽象表示。
- 文件和目录是可以通过File封装成对象得
- 对于File而言,其封装的并不是一个真正存在的文件,仅仅是一个路径名而已。它可以是存在的,也可以是不存在的。将来是要通过具体的操作把这个路径的内容转换为具体存在的
2.用户界面和操作系统使用依赖于系统的路径名字符串命名文件和目录。
方法名 | 说明 |
---|---|
File(File parent, String child) | 从父抽象路径名和子路径名字符串创建新的 File实例。 |
File(String pathname) | 通过将给定的路径名字符串转换为抽象路径名来创建新的 File实例。 |
File(String parent, String child) | 从父路径名字符串和子路径名字符串创建新的 File实例。 |
package IOStream;
import java.io.File;
public class IODemo01 {
public static void main(String[] args) {
File f1 = new File("C:\\Users\\hello驴先森\\Desktop\\Java学习笔记\\java.txt");//抽象路径,java实际不存在
System.out.println(f1);
File f2 = new File("C:\\Users\\hello驴先森\\Desktop\\Java学习笔记","java.txt");
System.out.println(f2);
File f3 = new File("C:\\Users\\hello驴先森\\Desktop\\Java学习笔记");
File f4 = new File(f3,"java.txt");
}
}
输出
C:\Users\hello驴先森\Desktop\Java学习笔记\java.txt
C:\Users\hello驴先森\Desktop\Java学习笔记\java.txt
C:\Users\hello驴先森\Desktop\Java学习笔记\java.txt
2、File类创建功能
方法名 | 说明 |
---|---|
boolean createNewFile() | 当且仅当具有该名称的文件尚不存在时,原子地创建一个由该抽象路径名命名的新的空文件。 |
boolean mkdir() | 创建由此抽象路径名命名的目录。 |
boolean mkdirs() | 创建由此抽象路径名命名的目录,包括任何必需但不存在的父目录。 |
package IOStream;
import java.io.File;
import java.io.IOException;
public class IODemo02 {
public static void main(String[] args) throws IOException {
//如果文件不存在,就创建文件,并返回true,如果文件存在,就不创建文件,并返回false
File f1 = new File("C:\\Users\\hello驴先森\\Desktop\\Java学习笔记\\IOStream\\java.text");
System.out.println(f1.createNewFile());
System.out.println("----------");
//如果目录不存在,就创建目录,并返回true,如果目录存在,就不创建目录,并返回false
File f2 = new File("C:\\Users\\hello驴先森\\Desktop\\Java学习笔记\\IOStream\\Javaee");
System.out.println(f2.mkdir());
System.out.println("----------");
//如果目录不存在,就创建文件,并返回true,如果目录存在,就不创建目录,并返回false
File f3 = new File("C:\\Users\\hello驴先森\\Desktop\\Java学习笔记\\IOStream\\Javaweb\\HTML");
System.out.println(f3.mkdirs());
System.out.println("----------");
}
}
输出
true
----------
true
----------
true
----------
3、File类判断和获取功能
方法名 | 说明 |
---|---|
String[] list() | 返回一个字符串数组,命名由此抽象路径名表示的目录中的文件和目录。 |
File[] listFiles() | 返回一个抽象路径名数组,表示由该抽象路径名表示的目录中的文件。 |
boolean isDirectory() | 测试此抽象路径名表示的文件是否为目录。 |
boolean isFile() | 测试此抽象路径名表示的文件是否为普通文件。 |
String getPath() | 将此抽象路径名转换为路径名字符串。 |
String getName() | 返回由此抽象路径名表示的文件或目录的名称。 |
String getAbsolutePath() | 返回此抽象路径名的绝对路径名字符串。 |
boolean exists() | 测试此抽象路径名表示的文件或目录是否存在。 |
3、File类删除
- boolean delete() 删除由此抽象路径名表示的文件或目录。
绝对路径和相对路径
- 绝对路径 :完整的路径名,不需要任何其他信息就可以定位它所表示的文件。例如:E:\Java\java.txt
- 相对路径 :必须使用取其他路径名的信息进行解释,例如:myfile:\java.txt
删除目录时的注意事项:
- 如果一个目录中有内容(目录,文件),不能直接删除。应该先删除目录中的内容,最后才能删除目录。
4、案例
package IOStream;
import java.io.File;
需求:给定一个路径,通过递归完成遍历该目录下的所有内容,并把所有文件的绝对路径输出在控制台
public class IOSream03 {
public static void main(String[] args) {
File srcFile = new File("C:\\Users\\hello驴先森\\Desktop\\Java学习笔记\\IOStream");
getALL(srcFile);
}
public static void getALL(File srcFile){
File[] fileArray = srcFile.listFiles();
if (fileArray != null){
for (File file:fileArray){
if (file.isDirectory()){
getALL(file);
}else {
System.out.println(file.getAbsolutePath());
}
}
}
}
}
输出
C:\Users\hello驴先森\Desktop\Java学习笔记\IOStream\3.txt
C:\Users\hello驴先森\Desktop\Java学习笔记\IOStream\java.text
C:\Users\hello驴先森\Desktop\Java学习笔记\IOStream\Javaee\1.txt
C:\Users\hello驴先森\Desktop\Java学习笔记\IOStream\Javaee\2.txt
C:\Users\hello驴先森\Desktop\Java学习笔记\IOStream\Javaweb\HTML\4.txt
5、IO流概述和分类
IO流分类:(按照数据类型来分的)
- 按照数据的流向
输入流:读数据
输出流:写数据 - 按照数据类型来分
字节流:字节输入流,字节输出流
字符流:字符输入流,字符输出流 - 如果数据通过WIndows自带的记事本软件打开,我们还可以读懂里面的内容,就是用字符流,否则使用字节流。如果你不知道该使用哪种类型的流,就使用字节流
6、字节流
- InputStream:这个抽象类是表示字节输入流的所有类的超类
- OutputStream:这个抽象类是表示字节输出流的所有类的超类
- 子类名特点:子类名称都是以其父名作为子类名的后缀
FileOutputStream:文件输出流用于将数据写入File - FileOutputStream(String name) 创建文件输出流以指定的名称写入文件。
- void write(int b) 将指定的字节写入此文件输出流。
- void close() 关闭此文件输出流并释放与此流相关联的任何系统资源。
7、字节流写数据的三种方式
方法名 | 说明 |
---|---|
void write(byte[] b) | 将 b.length字节从指定的字节数组写入此文件输出流。 |
void write(byte[] b, int off, int len) | 将 len字节从指定的字节数组开始,从偏移量 off开始写入此文件输出流。 |
void write(int b) | 将指定的字节写入此文件输出流。 |
public class IOStream04 {
public static void main(String[] args) throws IOException {
FileOutputStream fos = new FileOutputStream("C:\\Users\\hello驴先森\\Desktop\\Java学习笔记\\IOStream\\Javaweb\\HTML\\fos.txt");
/* byte[] bys = {97,98,99,100};
fos.write(bys);*/
//byte[] getBytes();返回字符串对应的字节数组
byte[] bytes = "abcdef".getBytes();
fos.write(bytes);
fos.close();
}
}
8、字节流写数据的两个小问题
1.字节流写数据如何实现换行呢?
window:\r\n
linux:\n
mac:\r
2.字节流写数据如何实现追加写入呢?
public FileOutputStream(String name,boolean append)
创建文件输出流以指定的名称写入文件。 如果第二个参数为true ,则字节将写入文件的末尾而不是开头。
package IOStream;
import java.io.FileOutputStream;
import java.io.IOException;
public class IOStream04 {
public static void main(String[] args) throws IOException {
FileOutputStream fos = new FileOutputStream("C:\\Users\\hello驴先森\\Desktop\\Java学习笔记\\IOStream\\Javaweb\\HTML\\fos.txt",true);
/* byte[] bys = {97,98,99,100};
fos.write(bys);*/
//byte[] getBytes();返回字符串对应的字节数组
byte[] bytes = "abcdef".getBytes();
fos.write(bytes);
}
}
9、字节流写数据加异常处理
finally:在异常处理时提供finally块来执行所有清除操作。比如说IO流中的释放资源
- 特点:被finally控制的语句一定会执行,除非JVM退出
try{
可能出现异常的代码;
}catch(异常类名 变量名){
异常的处理代码
}finally{
执行所有清楚操作;
}
package IOStream;
import java.io.FileOutputStream;
import java.io.IOException;
public class IOStream04 {
public static void main(String[] args) throws IOException {
FileOutputStream fos = null;//先定义
try {
fos = new FileOutputStream("C:\\Users\\hello驴先森\\Desktop\\Java学习笔记\\IOStream\\Javaweb\\HTML\\fos.txt"); //先定义再初始化对象
fos.write("abcde".getBytes());
}catch (IOException e){
e.printStackTrace();
}finally {
if (fos !=null){ //!!!要先判断是否为空
try {
fos.close();
}catch (IOException e){
e.printStackTrace();
}
}
}
}
}
10、字节流读数据(一次读一个数据)
- FileInputStream(String name) 通过打开与实际文件的连接来创建一个 FileInputStream ,该文件由文件系统中的路径名 name命名。
- int read() 从该输入流读取一个字节的数据。(数据的下一个字节,如果达到文件的末尾, -1 。)
package IOStream;
import java.io.FileInputStream;
import java.io.IOException;
public class IOStream05 {
public static void main(String[] args) throws IOException {
FileInputStream fis = new FileInputStream("C:\\Users\\hello驴先森\\Desktop\\Java学习笔记\\IOStream\\Javaweb\\HTML\\fos.txt");
/* int by = (fis.read());
while(by!=-1) {
System.out.print((char) by);
by = fis.read();
}*/
//对上面进行优化
int by;
while ((by=fis.read())!=-1){
System.out.print((char) by);
}
fis.close();
}
}
输出
abcde
11、字节流进行读写数据(一次读一个字节数据)
package IOStream;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
public class IOStream {
public static void main(String[] args) throws IOException {
FileInputStream fis = new FileInputStream("C:\\Users\\hello驴先森\\Desktop\\Java学习笔记\\IOStream\\Javaweb\\HTML\\fos.txt");
FileOutputStream fos = new FileOutputStream("C:\\Users\\hello驴先森\\Desktop\\Java学习笔记\\IOStream\\Javaweb\\HTML\\4.txt");
if (fis!=null){
int by;
while ((by=fis.read())!=-1){
fos.write(by);
}
}
fis.close();
fos.close();
}
}
12、字节流进行读写数据(一次读一个字节数组数据)
package IOStream;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
public class IOStream06 {
public static void main(String[] args) throws IOException {
FileInputStream fis = new FileInputStream("C:\\Users\\hello驴先森\\Desktop\\Java学习笔记\\IOStream\\Javaweb\\HTML\\4.txt");
byte[] by = new byte[1024];//1024及其整数倍
int len;
while ((len = fis.read(by))!=-1){
//String(byte[] bytes, int offset, int length) 通过使用平台的默认字符集解码指定的字节子阵列来构造新的 String 。
System.out.println(new String(by,0,len));
}
fis.close();
}
}
输出
abcde
13、案例:复制图片
package IOStream;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
public class IOStream07 {
public static void main(String[] args) throws IOException {
FileOutputStream fos = new FileOutputStream("C:\\Users\\hello驴先森\\Desktop\\Java学习笔记\\IOStream\\Javaweb\\java\\证件照lv.JPG");
FileInputStream fis = new FileInputStream("C:\\Users\\hello驴先森\\Desktop\\Java学习笔记\\IOStream\\Javaweb\\HTML\\证件照lv.JPG");
byte[] bys = new byte[2048];
if (fis != null) {
int len;
while ((len = fis.read()) != -1) {
fos.write(bys,0,len);//void write(byte[] b, int off, int len) 将 len字节从指定的字节数组开始,从偏移量 off开始写入此文件输出流。
}
}
fis.close();
fos.close();
}
}
14、字节缓冲流
- BufferedOutputStream该类实现缓冲输出流。通过设置这样的输出流,应用程序可以向底层输出流写入字节,而不必为写入的每个字节导致底层系统的调用。(提高效率)
- BufferedInputStream创建BufferedInputStream将创建一个内部缓冲区数组。 当从流中读取或跳过字节时,内部缓冲区将根据需要从所包含的输入流中重新填充,一次很多字节
构造方法
- 字节缓冲输出流:BufferedOutputStream(OutputStream out)
- 字节缓冲输入流:BufferedInputStream(InputStream in)
为什么构造方法需要的是字节流,而不是具体的问价或者路径呢
- 字节缓冲流仅仅是提供缓冲区,而真正的读写数据还得依靠基本的字节流对象进行操作
15、字符流
为什么会出现字符流
- 由于字节流操作中文不是特别方便,Java就提供了字符流
字符流=字节流+编码表
用字节流复制文本文件时,文本文件也会有中文,但是没有问题,原因时最终底层操作会自动进行字节拼接成中文,如何识别是中文的呢? - 汉字在存储时,无论选择哪种编码存储,第一个字节都是负数,通过判断是什么编码来选用几个字节
- UTF-8占用三个字节,GBK占用2个字节
15、字符流中的编码解码问题
1、编码解码
编码
- byte[] getBytes():使用平台的默认字符集将该String编码为一系列字节,将结果存储到新的字节数组中
- byte[] getBytes(String charsetName):使用指定的字符集将该String编码为一系列字节,将结果存储到新的字节数组中
解码 - String(byte[]bytes):通过平台的默认字符集解码指定的指定数组来构造新的String
- String(byte[]bytes,String charsetName):通过指定的字符集来解码指定的字节数组来构造新的String
- 编码和解码应该相统一
package IOStream;
import java.io.UnsupportedEncodingException;
import java.util.Arrays;
public class IOStream08 {
public static void main(String[] args) throws UnsupportedEncodingException {
String s = "中国";
byte[] by = s.getBytes();
/*System.out.println(Arrays.toString(by));//[-28, -72, -83, -27, -101, -67]
*/
/* byte[] bt = s.getBytes("UTF-8");
System.out.println(Arrays.toString(by));//[-28, -72, -83, -27, -101, -67]
*/
// byte[] bt = s.getBytes("GBK");
System.out.println(Arrays.toString(by));//[-42, -48, -71, -6]
/* String ss = new String(by);
System.out.println(ss);//中国*/
/* String ss = new String(by,"UTF-8");
System.out.println(ss);//中国*/
String ss = new String(by,"GBK");
System.out.println(ss);//涓浗
}
}
2、字符流抽象基类
- Reader:字符输入流的抽象类
- Writer:字符输出流的抽象类
- OutputStreamWriter是从字符流到字节流的桥梁:使用指定的charset将写入的字符编码为字节
- InputStreamReader是从字节流到字符流的桥梁:它读取字节,并使用指定的charset将其解码为字符
方法 | 说明 |
---|---|
OutputStreamWriter(OutputStream out) | 创建一个使用默认字符编码的OutputStreamWriter。 |
OutputStreamWriter(OutputStream out, String charsetName) | 创建一个使用命名字符集的OutputStreamWriter。 |
InputStreamReader(InputStream in) | 创建一个使用默认字符集的InputStreamReader。 |
InputStreamReader(InputStream in, String charsetName) | 创建一个使用命名字符集的InputStreamReader。 |
3、字符流写数据的五种方式
方法名 | 说明 |
---|---|
void write(int c) | 写一个字符 |
void write(char[] cbuf) | 写入一个字符数组 |
void write(char[] cbuf,int off,int len) | 写入字符数组的一部分 |
void write(String str) | 写入一个字符串 |
void write(String str,int off,int len) | 写入一个字符串的一部分 |
- void flush() 刷新流
4、字符流读数据的两种方式
方法名 | 说明 |
---|---|
int write() | 一次读一个字符 |
int write(char[] cbuf) | 一次读一个字符数组 |
5、字符缓冲流
- BufferedWriter:将文本写入字符输出流,缓冲字符,以提供单个字符,数组和字符串的高效写入。
方法名 | 说明 |
---|---|
BufferedWriter(Writer out) | 创建使用默认大小的输出缓冲区的缓冲字符输出流。 |
BufferedWriter(Writer out, int sz) | 创建一个新的缓冲字符输出流,使用给定大小的输出缓冲区。 |
- BufferedReader:从字符输入流读取文本,缓冲字符,以提供字符,数组和行的高效读取。
方法名 | 说明 |
---|---|
BufferedReader(Reader in) | 创建使用默认大小的输入缓冲区的缓冲字符输入流。 |
BufferedReader(Reader in, int sz) | 创建使用指定大小的输入缓冲区的缓冲字符输入流。 |
package IOStream;
import java.io.*;
public class IOStream10 {
public static void main(String[] args) throws IOException {
/* BufferedWriter bw = new BufferedWriter(new FileWriter("C:\\Users\\hello驴先森\\Desktop\\新建文件夹\\bw.txt"));
bw.write("hello\r\n");
bw.write("hello\r\n");
bw.close();*/
BufferedReader br = new BufferedReader(new FileReader("C:\\\\Users\\\\hello驴先森\\\\Desktop\\\\新建文件夹\\\\bw.txt"));
/* int len;
while ((len = br.read()) != -1) {
System.out.print((char) len);
}*/
char[] ch = new char[1024];
int len;
while ((len=br.read(ch))!=-1){
System.out.println(new String(ch,0,len));
}
}
br.close();
}
输出
hello
hello
6、字符缓冲流特有功能
BufferedWriter:
-void newLine():写一行行分隔符,行分隔符字符串由系统属性定义
BufferedReader
- public String readLine():读一行文字。结果包含行的内容的字符串,不包括任何终止字符,如果流的结尾已经到达,则为null
读写数据复制文件的标准过程
String line;
while((line=br.readline()!=-1){
bw.write(line);
bw.newLine();
bw.flush();
}
需求:把ArrayList集合中的字符串数据写入到文本文件中,要求:每一个字符串元素作为文件中的一行数据
package IOStream;
import java.io.*;
import java.util.ArrayList;
public class IOStream10 {
public static void main(String[] args) throws IOException {
ArrayList<String> array = new ArrayList<String>();
array.add("hello");
array.add("world");
array.add("java");
BufferedWriter bw = new BufferedWriter(new FileWriter("C:\\Users\\hello驴先森\\Desktop\\新建文件夹\\java.txt"));
for (String s:array){
bw.write(s);
bw.newLine();
bw.flush();
}
bw.close();
}
}
7、复制文件异常处理
try…catch…finally
try{
可能出现异常的代码;
}catch(异常名 变量名){
异常的处理代码;
}finally{
执行所有清楚操作;
}
JDK7改进方案
try(定义流对象){
可能出现异常的代码;
}catch(异常名 变量名){
异常的处理代码;
}
//自动释放资源
JDK9改进方案
定义输入流对象;
定义输出流对象;
try(输入流对象:输出流对象){
可能出现异常的代码;
}catch(异常名 变量名){
异常的处理代码;
}
//自动释放资源
16、特殊操作流
1、标准输入输出流
System类中有两个静态的成员变量
-
public static final InputStream in“标准”输入流。 该流已经打开,准备提供输入数据。 通常,该流对应于键盘输入或由主机环境或用户指定的另一个输入源。
-
public static final PrintStream out“标准”输出流。 此流已经打开并准备好接受输出数据。 通常,此流对应于显示输出或由主机环境或用户指定的另一个输出目标
-
如何把字节流转换为字符流?用转换流
-
使用字符流能不能够实现一次读取一行数据呢?可以
-
但是,一次读取一行数据的方法是字符缓冲流的特有方法
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
String line = br.readLine();
System.out.print(line);
- 但上面过于麻烦,Java就提供了一个类实现键盘录入(Scanner)
2、打印流
打印流分类:
- 字节打印流:PrintStream
- 字符打印流:PrintWriter
打印流的特点: - 只负责输出数据,不负责读取数据
- 有自己的特有方法
字节打印流 - PrintStream(String fileName):使用指定的文集名创建新的打印流
方法名 | 说明 |
---|---|
PrintWriter(String fileName) | 使用指定的文件名创建一个新的PrintWriter,而不需要自动执行行刷新。 |
PrintWriter(Writer out, boolean autoFlush) | 创建一个新的PrintWriter。 |
2、对象序列化流
- ObjectOutputStream将Java对象的原始数据类型和图形写入OutputStream。 可以使用ObjectInputStream读取(重构)对象。 可以通过使用流的文件来实现对象的持久存储。 如果流是网络套接字流,则可以在另一个主机上或另一个进程中重构对象。
- void writeObject(Object obj) 将指定的对象写入ObjectOutputStream。
注意: - 一个对象要想被序列化,该对象所属的类必须必须实现Serializable接口
- Serializable是一个标记接口,实现该接口,不需要重写任何方法
3、对象反序列化流
对象反序列化流
- ObjectInputStream反序列化先前使用ObjectOutputStream编写的原始数据和对象。
构造方法
- ObjectInputStream(InputStream in) 创建从指定的InputStream读取的ObjectInputStream。
方法
- Object readObject() 从ObjectInputStream读取一个对象。
4、特殊操作流
package IOStream;
import java.io.*;
import java.util.Properties;
public class IOStream12 {
public static void main(String[] args) throws IOException {
// myStore();
myLoad();
}
private static void myLoad() throws IOException {
Properties prop = new Properties();
FileReader fr = new FileReader("C:\\Users\\hello驴先森\\Desktop\\Java学习笔记\\fw.txt");
prop.load(fr);
fr.close();
System.out.println(prop);
}
private static void myStore() throws IOException {
Properties prop = new Properties();
prop.put("001","zhangsan");
prop.put("002","lisai");
prop.put("003","ahsfsha");
FileWriter fw = new FileWriter("C:\\Users\\hello驴先森\\Desktop\\Java学习笔记\\fw.txt");
prop.store(fw,null);
fw.close();
}
}
输出
{003=ahsfsha, 002=lisai, 001=zhangsan}