JAVA期末复习笔记

目录

基本数据类型

标识符

数组

方法

方法重载

面向对象

键盘录入

API

String类

ArrayList类 集合

static

继承

多态

权限修饰符

final关键字 

抽象类

接口

内部类

GUI图形化界面

集合进阶

异常

IO流

多线程


基本数据类型
数据类型关键字内存占用取值范围
整数byte1-128 ~ 127
short2

-2^15 ~ 2^15-1(-32768~32767)

int 4-2^31 ~ 2^31-1
long 8-2^63 ~ 2^63-1
浮点数float41.401298e-45 ~ 3.402823e+38
double84.9000000e-324 ~ 1.797693e+308
字符char20-65535
布尔boolean1true , false
  • 如果要定义 一个整数类型的变量,不知道选择哪种数据类型了,默认使用int。

  • 如果要定义 一个小数类型的变量,不知道选择哪种数据类型了,默认使用double。

  • 如果要定义一个long类型的变量,那么在数据值的后面需要加上L后缀。(大小写都可以,建议大写。)

容量小的类型自动转换为容量大的数据类型;

数据类型按容量大小排序为: byte, short, char -> int -> long -> float ->double byte, short, char之间不会相互转换,他们三者在计算时首先转换为int类型

标识符
  • 必须由数字、字母、下划线_、美元符号$组成。
  • 数字不能开头
  • 不能是关键字
  • 区分大小写
数组

两种定义方式:数据类型 [] 数组名,比如:int [] array;

                         数据类型  数组名 [],比如: int array []。

静态初始化:数据类型[] 数组名 = new 数据类型[]{元素1,元素2,元素3,元素4...};

比如:int[] arr = new int[]{11,22,33};

          double[] arr = new double[]{1.1,1.2,1.3};

简化格式:数据类型[] 数组名 = {元素1,元素2,元素3,元素4...};

比如:int[] array = {1,2,3,4,5};

​           double[] array = {1.1,1.2,1.3};

动态初始化:数据类型[] 数组名 = new 数据类型[数组的长度];

比如:1.定义一个数组,存3个人的年龄,年龄未知   int[] agesArr = new int[3];
           2.定义一个数组,存班级10名学生的考试成绩,考试成绩暂时未知,考完才知道。
              int[] scoresArr = new int[10];

方法

method,程序中最小的执行单元。(其实就是函数)

无参数方法:

定义格式:

public static void 方法名 () {
    //方法体;
}

调用格式:

方法名();

方法必须先定义,后调用,否则程序将报错。

带参数方法:

定义格式:

public static void 方法名 (参数1,参数2,参数3...) {
    //方法体;
}

调用格式:

方法名(参数1,参数2,参数3...);

方法调用时,参数的数量与类型必须与方法定义中的设置相匹配,否则程序将报错。

带返回值方法:

定义格式:

public static 数据类型 方法名 (参数) {
    //方法体;
}

调用格式:

方法名(参数);
数据类型 变量名 = 方法名(参数);

isEvenNumber ( 5 ) ;
boolean  flag =  isEvenNumber ( 5 ); 

方法的返回值通常会使用变量接收,否则该返回值将无意义。

注意事项:

1.方法不能嵌套定义

2.void表示无返回值,可以省略return,也可以单独的书写return,后面不加数据

方法重载

方法重载指同一个类中定义的多个方法之间的关系,满足下列条件的多个方法相互构成重载

  •  多个方法在同一个类中
  •  多个方法具有相同的方法名
  •  多个方法的参数不相同,类型不同或者数量不同

注意:

  • 重载仅对应方法的定义,与方法的调用无关,调用方式参照标准格式

  • 重载仅针对同一个类中方法的名称与参数进行识别,与返回值无关,换句话说不能通过返回值来判定两个方法是否相互构成重载

注:

System.out.println(“内容”); 输出内容并换行

System.out.print(“内容”); 输出内容不换行

System.out.println(); 起到换行的作用

面向对象

类和对象的关系

  • 类:类是对现实生活中一类具有共同属性和行为的事物的抽象
  • 对象:是能够看得到摸的着的真实存在的实体
  • 简单理解:**类是对事物的一种描述,对象则为具体存在的事物

类的定义:

  • 属性:在类中通过成员变量来体现(类中方法外的变量)
  • 行为:在类中通过成员方法来体现(和前面的方法相比去掉static关键字即可)

public class 类名 {
	// 成员变量
	变量1的数据类型 变量1;
	变量2的数据类型 变量2;
	…
	// 成员方法
	方法1;
	方法2;	
}

对象的使用:

 创建对象
        格式:类名 对象名 = new 类名();
        范例:Phone p = new Phone();

    使用对象
        1:使用成员变量
            格式:对象名.变量名
            范例:p.brand
        2:使用成员方法
            格式:对象名.方法名()
            范例:p.call()


public class PhoneDemo {
    public static void main(String[] args) {
        //创建对象
        Phone p = new Phone();

        //使用成员变量
        System.out.println(p.brand);
        System.out.println(p.price);

        p.brand = "小米";
        p.price = 2999;

        System.out.println(p.brand);
        System.out.println(p.price);

        //使用成员方法
        p.call();
        p.sendMessage();
    }
}

多个对象在堆内存中,都有不同的内存划分,成员变量存储在各自的内存区域中,成员方法多个对象共用的一份。

成本变量和局部变量:

  • 类中位置不同:成员变量(类中方法外)局部变量(方法内部或方法声明上)

  • 内存中位置不同:成员变量(堆内存)局部变量(栈内存)

  • 生命周期不同:成员变量(随着对象的存在而存在,随着对象的消失而消失)局部变量(随着方法的调用而存在,醉着方法的调用完毕而消失)

  • 初始化值不同:成员变量(有默认初始化值)局部变量(没有默认初始化值,必须先定义,赋值才能使用)

封装:

 是面向对象三大特征之一(封装,继承,多态)

对象代表什么,就得封装对应的数据,并提供数据对应的行为。

封装代码实现:将类的某些信息隐藏在类内部,不允许外部程序直接访问,而是通过该类提供的方法来实现对隐藏信息的操作和访问;
成员变量private,提供对应的getXxx()/setXxx()方法。

构造方法:

创造对象 Student stu = new Student();

class Student {
    private String name;
    private int age;

    //构造方法
    public Student() {
        System.out.println("无参构造方法");
    }

    public void show() {
        System.out.println(name + "," + age);
    }
}
/*
    测试类
 */
public class StudentDemo {
    public static void main(String[] args) {
        //创建对象
        Student s = new Student();
        s.show();
    }
}

构造方法的创建:如果没有定义构造方法,系统将给出一个默认的无参数构造方法;如果定义了构造方法,系统将不再提供默认的构造方法。

构造方法的重载:如果自定义了带参构造方法,还要使用无参数构造方法,就必须再写一个无参数构造方法。

推荐的使用方式:无论是否使用,都手工书写无参数构造方法。

重要功能:可以使用带参构造,为成员变量进行初始化。
 

键盘录入

next(),nextline():接受任何数据,但都会返回一个字符串。

nextInt():只能接受整数。

nextDouble():能接收整数和小数,但是都会看做小数返回。录入字母会报错。

next(),nextInt(),nextDouble()在接收数据的时候,会遇到空格,回车,制表符其中一个就会停止接收数据。但是这些符号 + 后面的数据还在内存中并没有接收。如果后面还有其他键盘录入的方法,会自动将这些数据接收。

nextLine()方法是把一整行全部接收完毕。

键盘录入分为两套:

- next()、nextInt()、nextDouble()这三个配套使用。

如果用了这三个其中一个,就不要用nextLine()。

- nextLine()单独使用。

如果想要整数,那么先接收,再使用Integer.parseInt进行类型转换。

类型转换示例:

Scanner sc = new Scanner(System.in);
String s = sc.nextLine();//键盘录入123
System.out.println("此时为字符串" + s);//此时123是字符串
int i = Integer.parseInt(s);//想要整数再进行转换
System.out.println("此时为整数:" + i);
API

API (Application Programming Interface) :应用程序编程接口

java中的API:指的就是 JDK 中提供的各种功能的 Java类,这些类将底层的实现封装了起来,我们不需要关心这些类是如何实现的,只需要学习这些类如何使用即可,我们可以通过帮助文档来学习这些API如何使用。

String类

String 类代表字符串,Java 程序中的所有字符串文字(例如“abc”)都被实现为此类的实例。也就是说,Java 程序中所有的双引号字符串,都是 String 类的对象。String 类在 java.lang 包下,所以使用的时候不需要导包。

  • 字符串不可变,它们的值在创建后不能被更改

  • 虽然 String 的值是不可变的,但是它们可以被共享

  • 字符串效果上相当于字符数组( char[] ),但是底层原理是字节数组( byte[] )

常见构造方法:

public class StringDemo01 {
    public static void main(String[] args) {
        //public String():创建一个空白字符串对象,不含有任何内容
        String s1 = new String();
        System.out.println("s1:" + s1);

        //public String(char[] chs):根据字符数组的内容,来创建字符串对象
        char[] chs = {'a', 'b', 'c'};
        String s2 = new String(chs);
        System.out.println("s2:" + s2);

        //public String(byte[] bys):根据字节数组的内容,来创建字符串对象
        byte[] bys = {97, 98, 99};
        String s3 = new String(bys);
        System.out.println("s3:" + s3);

        //String s = “abc”;	直接赋值的方式创建字符串对象,内容就是abc
        String s4 = "abc";
        System.out.println("s4:" + s4);
    }
}

两种创建字符串对象方式:

  • 通过构造方法创建

    通过 new 创建的字符串对象,每一次 new 都会申请一个内存空间,虽然内容相同,但是地址值不同。

  • 直接赋值方式创建

    以“”方式给出的字符串,只要字符序列相同(顺序和大小写),无论在程序代码中出现几次,JVM 都只会建立一个 String 对象,并在字符串池中维护。

字符串比较:

==号的作用:

  • 比较基本数据类型:比较的是具体的值

  • 比较引用数据类型:比较的是对象地址值

equals方法:

public boolean equals(String s)     比较两个字符串内容是否相同、区分大小写

public class StringDemo02 {
    public static void main(String[] args) {
        //构造方法的方式得到对象
        char[] chs = {'a', 'b', 'c'};
        String s1 = new String(chs);
        String s2 = new String(chs);

        //直接赋值的方式得到对象
        String s3 = "abc";
        String s4 = "abc";

        //比较字符串对象地址是否相同
        System.out.println(s1 == s2);//false
        System.out.println(s1 == s3);//false
        System.out.println(s3 == s4);//true
        System.out.println("--------");

        //比较字符串内容是否相同
        System.out.println(s1.equals(s2));//true
        System.out.println(s1.equals(s3));//true
        System.out.println(s3.equals(s4));//true
    }
}

 StringBuilder:看作一个容器,创建后里面的内容是可变的。

public class StringBuilderDemo3 {
    public static void main(String[] args) {
        //1.创建对象
        StringBuilder sb = new StringBuilder("abc");

        //2.添加元素
        /*sb.append(1);
        sb.append(2.3);
        sb.append(true);*/

        //反转
        sb.reverse();

        //获取长度
        int len = sb.length();
        System.out.println(len);


        //打印
        //普及:
        //因为StringBuilder是Java已经写好的类
        //java在底层对他做了一些特殊处理。
        //打印对象不是地址值而是属性值。
        System.out.println(sb);
    }
}

链式编程:

public class StringBuilderDemo4 {
    public static void main(String[] args) {
        //1.创建对象
        StringBuilder sb = new StringBuilder();

        //2.添加字符串
        sb.append("aaa").append("bbb").append("ccc").append("ddd");

        System.out.println(sb);//aaabbbcccddd

        //3.再把StringBuilder变回字符串
        String str = sb.toString();
        System.out.println(str);//aaabbbcccddd

    }
}

StringJoiner

  • StringJoiner跟StringBuilder一样,也可以看成是一个容器,创建之后里面的内容是可变的。

  • 作用:提高字符串的操作效率,而且代码编写特别简洁,但是目前市场上很少有人用。

  • JDK8出现的

//1.创建一个对象,并指定中间的间隔符号
StringJoiner sj = new StringJoiner("---");
//2.添加元素
sj.add("aaa").add("bbb").add("ccc");
//3.打印结果
System.out.println(sj);//aaa---bbb---ccc


//1.创建对象
StringJoiner sj = new StringJoiner(", ","[","]");
//2.添加元素
sj.add("aaa").add("bbb").add("ccc");
int len = sj.length();
System.out.println(len);//15
//3.打印
System.out.println(sj);//[aaa, bbb, ccc]
String str = sj.toString();
System.out.println(str);//[aaa, bbb, ccc]
ArrayList类 集合

长度可变;添加数据的时候不需要考虑索引,默认将数据添加到末尾。

只能存储引用数据类型。

常用方法:

构造方法:
public ArrayList();创建一个空的集合对象

成员方法:
public boolean add(要添加的元素) 将指定的元素追加到此集合的末尾

public boolean remove(要删除的元素) 删除指定元素,返回值表示是否删除成功

public E remove(int index) 删除指定索引处的元素,返回被删除的元素

public E set(int index,E element) 修改指定索引处的元素,返回被修改的元素

public E get(int index) 返回指定索引处的元素

public int size() 返回集合中的元素的个数
static

static是静态的意思。 static可以修饰成员变量或者修饰成员方法

被static修饰的成员变量,叫做静态变量。被该类的所有对象共享。

方法同上。可以直接通过类名.xxx进行访问。

1.当 static 修饰成员变量或者成员方法时,该变量称为静态变量,该方法称为静态方法。该类的每个对象都共享同一个类的静态变量和静态方法。任何对象都可以更改该静态变量的值或者访问静态方法。但是不推荐这种方式去访问。因为静态变量或者静态方法直接通过类名访问即可,完全没有必要用对象去访问。

2.无static修饰的成员变量或者成员方法,称为实例变量,实例方法,实例变量和实例方法必须创建类的对象,然后通过对象来访问。

3.static修饰的成员属于类,会存储在静态区,是随着类的加载而加载的,且只加载一次,所以只有一份,节省内存。存储于一块固定的内存区域(静态区),所以,可以直接被类名调用。它优先于对象存在,所以,可以被所有对象共享。

4.无static修饰的成员,是属于对象,对象有多少个,他们就会出现多少份。所以必须由对象调用。

继承

假如多个类中存在相同属性和行为时,我们可以将这些内容抽取到单独一个类中,那么多个类无需再定义这些属性和行为,只要继承那一个类即可。

多个类可以称为子类,单独被继承的那一个类称为父类、超类(superclass)或者基类。

继承就是子类继承父类的属性和行为,使得子类对象可以直接具有与父类相同的属性、相同的行为。子类可以直接访问父类中非私有的属性和行为。

好处:1.提高代码的复用性(减少代码冗余、相同代码重复利用)

2.使类与类之间产生了关系

extends关键字继承,并且Java是单继承的,一个类只能继承一个直接父类。

class 父类 {
	...
}

class 子类 extends 父类 {
	...
}

并不是父类所有的内容都可以给子类继承的:

子类不能继承父类的构造方法。

子类可以继承父类的私有成员(成员变量、方法),只是子类无法直接访问而已,可以通过getter/setter方法访问父类的private成员变量。

子父类中出现了同名的成员变量时,子类会优先访问自己对象中的成员变量

想访问父类的话,要用到super关键字;

super.父类成员变量名

eg.
// 访问子类中的num
System.out.println("Zi num=" + this.num);
// 访问父类中的num
System.out.println("Fu num=" + super.num);

如果子类父类中出现不重名的成员方法,这时的调用是没有影响的。对象调用方法时,会先在子类中查找有没有对应的方法,若子类中存在就会执行子类中的方法,若子类中不存在就会执行父类中相应的方法。

如果子类父类出现重名的成员方法,则创建子类对象调用该方法的时候,子类对象会优先调用自己的方法。

方法重写:子类中出现与父类一模一样的方法时(返回值类型,方法名和参数列表都相同),会出现覆盖效果,也称为重写或者复写。声明不变,重新实现

@Override:注解,重写注解校验!

这个注解标记的方法,就说明这个方法必须是重写父类的方法,否则编译阶段报错。

建议重写都加上这个注解,一方面可以提高代码的可读性,一方面可以防止重写出错!

加上后的子类代码形式如下:

public class Cat extends Animal {
     // 声明不变,重新实现
    // 方法名称与父类全部一样,只是方法体中的功能重写写了!
    @Override
    public void cry(){
        System.out.println("我们一起学猫叫,喵喵喵!喵的非常好听!");
    }
}
  • 子类构造方法执行的时候,都会在第一行默认先调用父类无参数构造方法一次。

  • 子类构造方法的第一行都隐含了一个super()去调用父类无参数构造方法,super()可以省略不写。

继承的特点:1.Java只支持单继承,不支持多继承。2.一个类可以有多个子类。3.可以多层继承。

多态

同类型的对象,表现出的不同形态。

父类类型 对象名称 = 子类对象;

当使用多态方式调用方法时,首先检查父类中是否有该方法,如果没有,则编译错误。也就是说,不能调用子类拥有,而父类没有的方法。编译都错误,更别说运行了。这也是多态给我们带来的一点"小麻烦"。所以,想要调用子类特有的方法,必须做向下转型。

向上转型(自动转换):多态本身是子类类型向父类类型向上转换(自动转换)的过程,这个过程是默认的。 当父类引用指向一个子类对象时,便是向上转型。

使用格式:父类类型  变量名 = new 子类类型();   如:Animal a = new Cat();

向下转型(强制转换):父类类型向子类类型向下转换的过程,这个过程是强制的。 一个已经向上转型的子类对象,将父类引用转为子类引用,可以使用强制类型转换的格式,便是向下转型。

使用格式:子类类型 变量名 = (子类类型) 父类变量名;  如:Aniaml a = new Cat();   Cat c =(Cat) a;  

instanceof关键字: 

为了避免ClassCastException(类型转换异常 )的发生,Java提供了 instanceof 关键字,给引用变量做类型的校验,格式如下:

变量名 instanceof 数据类型 
如果变量属于该数据类型或者其子类类型,返回true。
如果变量不属于该数据类型或者其子类类型,返回false。

public class Test {
    public static void main(String[] args) {
        // 向上转型  
        Animal a = new Cat();  
        a.eat();               // 调用的是 Cat 的 eat

        // 向下转型  
        if (a instanceof Cat){
            Cat c = (Cat)a;       
            c.catchMouse();        // 调用的是 Cat 的 catchMouse
        } else if (a instanceof Dog){
            Dog d = (Dog)a;       
            d.watchHouse();       // 调用的是 Dog 的 watchHouse
        }
    }  
}

JDK14的时候提出了新特性,把判断和强转合并成了一行
//新特性
//先判断a是否为Dog类型,如果是,则强转成Dog类型,转换之后变量名为d
//如果不是,则不强转,结果直接是false
if(a instanceof Dog d){
    d.lookHome();
}else if(a instanceof Cat c){
    c.catchMouse();
}else{
    System.out.println("没有这个类型,无法转换");
}

包在操作系统中其实就是一个文件夹。包是用来分门别类的管理技术,不同的技术类放在不同的包下,方便管理和维护。

命名规范:路径名.路径名.xxx.xxx   // 例如:com.itheima.oa

  • 包名一般是公司域名的倒写。例如:黑马是www.itheima.com,包名就可以定义成com.itheima.技术名称。

  • 包名必须用”.“连接。

  • 包名的每个路径名必须是一个合法的标识符,而且不能是Java的关键字。

导包:

什么时候需要导包?

情况一:在使用Java中提供的非核心包中的类时

情况二:使用自己写的其他包中的类时

什么时候不需要导包?

情况一:在使用Java核心包(java.lang)中的类时

情况二:在使用自己写的同一个包中的类时

使用不同包下的相同类时,就需要使用全类名了。

//使用全类名的形式即可。
//全类名:包名 + 类名
//拷贝全类名的快捷键:选中类名crtl + shift + alt + c 或者用鼠标点copy,再点击copy Reference
com.itheima.homework.demo1.Student s1 = new com.itheima.homework.demo1.Student();
com.itheima.homework.demo2.Student s2 = new com.itheima.homework.demo2.Student();
权限修饰符
  • public:公共的,所有地方都可以访问。

  • protected:本类 ,本包,其他包中的子类都可以访问。

  • 默认(没有修饰符):本类 ,本包可以访问。

    注意:默认是空着不写,不是default

  • private:私有的,当前类可以访问。

public > protected > 默认 > private

publicprotected默认private
同一类中
同一包中的类
不同包的子类
不同包中的无关类

可见,public具有最大权限。private则是最小权限。

编写代码时,如果没有特殊的考虑,建议这样使用权限:

  • 成员变量使用private,隐藏细节。

  • 构造方法使用public ,方便创建对象。

  • 成员方法使用public ,方便调用方法。 

final关键字 

Java提供了`final` 关键字,表示修饰的内容不可变。

final:不可改变,最终的含义。可以用于修饰类、方法和变量。

  • 类:被修饰的类,不能被继承。

  • 方法:被修饰的方法,不能被重写。

  • 变量:被修饰的变量,有且仅能被赋值一次。

被final修饰的常量名称,一般都有书写规范,所有字母都大写。  

抽象类

我们把没有方法体的方法称为抽象方法。Java语法规定,包含抽象方法的类就是抽象类

abstract是抽象的意思,用于修饰方法和类。

抽象方法:使用abstract关键字修饰方法,该方法就成了抽象方法,抽象方法只包含一个方法名,而没有方法体。

抽象类:如果一个类包含抽象方法,那么该类必须是抽象类。注意:抽象类不一定有抽象方法,但是有抽象方法的类必须定义成抽象类

继承抽象类的子类必须重写父类所有的抽象方法。否则,该子类也必须声明为抽象类。

接口

接口是更加彻底的抽象,JDK7之前,包括JDK7,接口中的只有包含:抽象方法和常量。接口同样是不能创建对象的。

定义格式

//接口的定义格式:
interface 接口名称{
    // 抽象方法
}

// 接口的声明:interface
// 接口名称:首字母大写,满足“驼峰模式”

接口中的抽象方法默认会自动加上public abstract修饰,程序员无需自己手写。

接口的实现:

类与接口的关系为实现关系,即类实现接口,该类可以称为接口的实现类,也可以称为接口的子类。实现的动作类似继承,格式相仿,只是关键字不同,实现使用implements关键字。

实现接口的格式:(可以被多实现)

/**接口的实现:
    在Java中接口是被实现的,实现接口的类称为实现类。
    实现类的格式:*/
class 类名 implements 接口1,接口2,接口3...{

}

1.必须重写实现的全部接口中所有抽象方法。

2.如果一个类实现了接口,但是没有重写完全部接口的全部抽象方法,这个类也必须定义成抽象类。

3.意义:接口体现的是一种规范,接口对实现类是一种强制性的约束,要么全部完成接口申明的功能,要么自己也定义成抽象类。这正是一种强制性的规范。

接口与接口的多继承:一个接口可以同时继承多个接口。

注意:类与接口是实现关系。接口与接口是继承关系。

接口继承接口就是把其他接口的抽象方法与本接口进行了合并。

内部类

将一个类A定义在另一个类B里面,里面的那个类A就称为内部类,B则称为外部类。可以把内部类理解成寄生,外部类理解成宿主。

分类:

成员内部类,类定义在了成员位置 (类中方法外称为成员位置,无static修饰的内部类)

宿主:外部类对象。

使用格式:外部类.内部类

获取内部类对象的两种方式:

方式一:外部直接创建成员内部类的对象

外部类.内部类 变量 = new 外部类().new 内部类();

方式二:在外部类中定义一个方法提供内部类的对象

public class Test {
    public static void main(String[] args) {
        Outer.inner oi = new Outer().new inner();
        oi.method();
    }
}

class Outer {	// 外部类
    private int a = 30;

    // 在成员位置定义一个类
    class inner {
        private int a = 20;

        public void method() {
            int a = 10;
            System.out.println(???);	// 10   答案:a
            System.out.println(???);	// 20	答案:this.a
            System.out.println(???);	// 30	答案:Outer.this.a
        }
    }
}

静态内部类,类定义在了成员位置 (类中方法外称为成员位置,有static修饰的内部类)

1.静态内部类可以直接访问外部类的静态成员。

2.静态内部类不可以直接访问外部类的非静态成员,如果要访问需要创建外部类的对象。

3.静态内部类中没有银行的Outer.this。

使用格式:外部类.内部类

创建格式:外部类.内部类 变量 = new 外部类.内部类构造器

局部内部类,类定义在方法内

class 外部类名 {
	数据类型 变量名;
	
	修饰符 返回值类型 方法名(参数列表) {
		// …
		class 内部类 {
			// 成员变量
			// 成员方法
		}
	}
}

匿名内部类,没有名字的内部类,可以在方法中,也可以在类中方法外。

//匿名内部类格式
new 父类名或者接口名(){
    // 方法重写
    @Override 
    public void method() {
        // 执行语句
    }
};

//使用方式
interface Swim {
    public abstract void swimming();
}

public class Demo07 {
    public static void main(String[] args) {
        // 使用匿名内部类
		new Swim() {
			@Override
			public void swimming() {
				System.out.println("自由泳...");
			}
		}.swimming();

        // 接口 变量 = new 实现类(); // 多态,走子类的重写方法
        Swim s2 = new Swim() {
            @Override
            public void swimming() {
                System.out.println("蛙泳...");
            }
        };
        s2.swimming();
    }
}

实际上,如果我们希望定义一个只要使用一次的类,就可考虑使用匿名内部类。匿名内部类的本质作用是为了简化代码。

GUI图形化界面

AWT包

Swing包

集合进阶

数组和集合的区别

相同点:都是容器,可以存储多个数据

不同点:数组的长度是不可变的,集合的长度是可变的;

数组可以存基本数据类型和引用数据类型;

集合只能存引用数据类型,如果要存基本数据类型,需要存对应的包装类。

List系列集合:添加的元素是有序、可重复、有索引

Set系列集合:添加的元素是无序、不重复、无索引

Collection集合:是单列集合的顶层接口。

常见的使用方法:
boolean add(E e);  //添加元素

boolean remove(Object o);  //从集合中移除指定的元素

boolean removeIf(Object o);  //根据条件进行移除

void clear();  //清空集合中的元素

boolean contains(Object o);  //判断集合中是否存在指定的元素

boolean isEmpty();  //判断集合是否为空

int size();  //集合的长度,也就是集合中元素的个数

Collection集合的遍历:

(1)迭代器遍历

Iterator<E> iterator();  //返回迭代器对象,默认指向当前对象的0索引

boolean hasNext();  //判断当前位置是否有元素可以被取出

E next();  //获取当前位置的元素,将迭代器对象移向下一个索引位置

eg:
ArrayList<String> list = new ArrayList<>();

Iterator<String> it = list.iterator();

while(it.hasNext()){
            String s = it.next();
            if("b".equals(s)){//指向谁,那么此时就删除谁.
                it.remove();
            }

迭代器遍历完毕,指针不会复位;循环中只能使用一次next方法;迭代器遍历时,不能使用集合的方法进行增加或删除。

(2)增强for遍历(所有的单列集合和数组)

  • 它是JDK5之后出现的,其内部原理是一个Iterator迭代器

  • 实现Iterable接口的类才可以使用迭代器和增强for

  • 简化数组和Collection集合的遍历

for(集合/数组中元素的数据类型 变量名 :  集合/数组名) {

​		// 已经将当前遍历到的元素封装到变量中了,直接使用变量即可

​	}


eg:
ArrayList<String> list = new ArrayList<>();
for(string s : list){
    System.out.println(s);
}

 修改增强for中的变量,不会改变集合中原本的数据。

(3)Lambda表达式

利用forEach方法

public class A07_CollectionDemo7 {
    public static void main(String[] args) {
       /* 
        lambda表达式遍历:
                default void forEach(Consumer<? super T> action):
        */

        //1.创建集合并添加元素
        Collection<String> coll = new ArrayList<>();
        coll.add("zhangsan");
        coll.add("lisi");
        coll.add("wangwu");
        //2.利用匿名内部类的形式
        //底层原理:
        //其实也会自己遍历集合,依次得到每一个元素
        //把得到的每一个元素,传递给下面的accept方法
        //s依次表示集合中的每一个数据
       /* coll.forEach(new Consumer<String>() {
            @Override
            public void accept(String s) {
                System.out.println(s);
            }
        });*/

        //lambda表达式
        coll.forEach(s -> System.out.println(s));
    }
}
异常

指的是程序在执行过程中,出现的非正常的情况,最终会导致JVM的非正常停止。

在Java等面向对象的编程语言中,异常本身是一个类,产生异常就是创建异常对象并抛出了一个异常对象。Java处理异常的方式是中断处理。

异常作用:(1)用来查询bug的关键参考信息

(2)可以作为方法内部的一种特殊返回值,以便通知调用者底层执行情况

Throwable体系:Error:严重错误,绝症,无法处理;

Exception:异常,可以通过代码纠正。

Throwable常用方法:

public void printStackTrace():控制台打印异常的详细信息。

包含了异常的类型,异常的原因,还包括异常出现的位置,在开发和调试阶段,都得使用printStackTrace。

public String getMessage():获取发生异常的原因。

public String toString():获取异常的类型和异常描述信息(不用)。

异常处理方式:

(1)JVM虚拟机默认处理方式:把异常的名称,原因,出现位置打印在控制台;程序停止运行,异常下面的代码不会再执行了。

(2)自己处理异常(捕获异常):try...catch...

try{
     编写可能会出现异常的代码
}catch(异常类型  e){
     处理异常的代码
     //记录日志/打印异常信息/继续抛出异常
}


eg:
public class TryCatchDemo {
    public static void main(String[] args) {
        try {// 当产生异常时,必须有处理方式。要么捕获,要么声明。
            read("b.txt");
        } catch (FileNotFoundException e) {// 括号中需要定义什么呢?
          	//try中抛出的是什么异常,在括号中就定义什么异常类型
            System.out.println(e);
        }
        System.out.println("over");
    }
    /*
     *
     * 我们 当前的这个方法中 有异常  有编译期异常
     */
    public static void read(String path) throws FileNotFoundException {
        if (!path.equals("a.txt")) {//如果不是 a.txt这个文件 
            // 我假设  如果不是 a.txt 认为 该文件不存在 是一个错误 也就是异常  throw
            throw new FileNotFoundException("文件不存在");
        }
    }
}

finally代码块: 有一些特定的代码无论异常是否发生,都需要执行。另外,因为异常会引发程序跳转,导致有些语句执行不到。而finally就是解决这个问题的,在finally代码块中存放的代码都是一定会被执行的。

try...catch....finally:自身需要处理异常,最终还得关闭资源。比如IO流中,当打开了一个关联文件的资源,最后程序不管结果如何,都需要把这个资源关闭掉。

当只有在try或者catch中调用退出JVM的相关方法,此时finally才不会执行,否则finally永远会执行。

(3) 抛出处理

throws 写在方法定义处,表示声明一个异常,告诉调用者使用本方法可能会有哪些异常。

public void 方法()throws 异常类名1,,异常类名2...{...}

编译时异常必须要写!运行时异常可以不写。

throw 写在方法内,用来手动抛出一个指定的异常对象,交给调用者,并结束当前方法。

public void 方法(){

        throw new NullPointerException();

}

throw new 异常类名(参数);

IO流

读写文件中的数据。(以程序(内存)为参照物)

根据数据的流向分类:

input输入流:把数据从其他设备上读取到内存中的流。

output输出流:把数据从`内存` 中写出到`其他设备`上的流。

根据数据的类型分类:

字节流:以字节为单位,读写数据的流。

字符流:以字符为单位,读写数据的流。

顶级父类:

输入流输出流
字节流InputStreamOutputStream
字符流ReaderWriter

字节流:

字节输出流:

三种输出方式:

public class Test1 {
    public static void main(String[] args) throws IOException {
        FileOutputStream fos = new FileOutputStream("D:\\aaa.txt");
        fos.write(97);
        fos.close();
    }
}

public class FOSWrite {
    public static void main(String[] args) throws IOException {
        // 使用文件名称创建流对象
        FileOutputStream fos = new FileOutputStream("fos.txt");     
      	// 字符串转换为字节数组
      	byte[] b = "黑马程序员".getBytes();
      	// 写出字节数组数据
      	fos.write(b);
      	// 关闭资源
        fos.close();
    }
}
输出结果:
黑马程序员


public class FOSWrite {
    public static void main(String[] args) throws IOException {
        // 使用文件名称创建流对象
        FileOutputStream fos = new FileOutputStream("fos.txt");     
      	// 字符串转换为字节数组
      	byte[] b = "abcde".getBytes();
		// 写出从索引2开始,2个字节。索引2是c,两个字节,也就是cd。
        fos.write(b,2,2);
      	// 关闭资源
        fos.close();
    }
}
输出结果:
cd

 回车换行:

String wrap = "\r\n";
byte[] byte1 = wrap.getBytes();
fos.write(byte1);



fos.write("\r\n".getBytes());

续写:在文件后面加上true

 FileOutputStream fos = new FileOutputStream("fos.txt",true);

字节输入流:

构造举例:
// 使用File对象创建流对象
File file = new File("a.txt");
FileInputStream fos = new FileInputStream(file);

// 使用文件名称创建流对象
FileInputStream fos = new FileInputStream("b.txt");

读取字节数据:
(1)read方法,每次读取一个字节,提升为int类型,读取到文件末尾返回-1;
public class FISRead {
    public static void main(String[] args) throws IOException{
      	// 使用文件名称创建流对象
       	FileInputStream fis = new FileInputStream("read.txt");
      	// 读取数据,返回一个字节
        int read = fis.read();
        System.out.println((char) read);
        read = fis.read();
        System.out.println((char) read);
        read = fis.read();
        System.out.println((char) read);
        read = fis.read();
        System.out.println((char) read);
        read = fis.read();
        System.out.println((char) read);
      	// 读取到末尾,返回-1
       	read = fis.read();
        System.out.println( read);
		// 关闭资源
        fis.close();
    }
}

(2)使用字节数组读取:read(byte[] b)每次读取b的长度个字节到数组中,返回读取到的有效字节个数,读取到末尾时,返回`-1` 
public class FISRead {
    public static void main(String[] args) throws IOException{
      	// 使用文件名称创建流对象.
       	FileInputStream fis = new FileInputStream("read.txt"); // 文件中为abcde
      	// 定义变量,作为有效个数
        int len ;
        // 定义字节数组,作为装字节数据的容器   
        byte[] b = new byte[2];
        // 循环读取
        while (( len= fis.read(b))!=-1) {
           	// 每次读取后,把数组变成字符串打印
            System.out.println(new String(b,0,len));//  len 每次读取的有效字节个数
        }
		// 关闭资源
        fis.close();
    }
}

流的关闭原则:先开后关,后开先关。

文件拷贝

FileInputStream fis = new FileInputStream("D:\\movie.mp4");
FileOutputStream fos = new FileOutputStream("myio\\copy.mp4");

int b;
while((b = fis.read()) != -1){
    fos.write(b);
}

fos.close();
fis.close();



int len;
byte[] bytes = new byte[1024 * 1024 * 5];//  5M大小的字节数组
while((len = fis.read(bytes)) != -1){
    fos.write(bytes,off,0,len);
}

字符流:

字符输入流Reader:

public class FRRead {
    public static void main(String[] args) throws IOException {
      	// 使用文件名称创建流对象
       	FileReader fr = new FileReader("read.txt");
      	// 定义变量,保存数据
        int b ;
        // 循环读取
        while ((b = fr.read())!=-1) {
            System.out.println((char)b);
        }
		// 关闭资源
        fr.close();
    }
}



public class FRRead {
    public static void main(String[] args) throws IOException {
      	// 使用文件名称创建流对象
       	FileReader fr = new FileReader("read.txt");
      	// 定义变量,保存有效字符个数
        int len ;
        // 定义字符数组,作为装字符数据的容器
         char[] cbuf = new char[2];
        // 循环读取
        while ((len = fr.read(cbuf))!=-1) {
            System.out.println(new String(cbuf,0,len));
        }
		// 关闭资源
        fr.close();
    }
}

字符输出流Writer:

public class FWWrite {
    public static void main(String[] args) throws IOException {
        // 使用文件名称创建流对象
        FileWriter fw = new FileWriter("fw.txt");     
      	// 写出数据
      	fw.write(97); // 写出第1个字符
      	fw.write('b'); // 写出第2个字符
      	fw.write('C'); // 写出第3个字符
      	fw.write(30000); // 写出第4个字符,中文编码表中30000对应一个汉字。
      
      	/*
        【注意】关闭资源时,与FileOutputStream不同。
      	 如果不关闭,数据只是保存到缓冲区,并未保存到文件。
        */
        // fw.close();
    }
}
多线程

进程:程序的基本执行实体。

线程:操作系统能够进行运算调度的最小单位。它被包含在进程之中,是进程中的实际运作单位。

并发:同一时刻,多个指令在单个CPU上交替执行。

并行:同一时刻,多个指令在多个CPU上同时执行。

实现方式:

(1)继承Thread类
public class MyThread extends Thread {
    @Override
    public void run() {
        for(int i=0; i<100; i++) {
            System.out.println(getName() + "HelloWorld");
        }
    }
}

public class MyThreadDemo {
    public static void main(String[] args) {
        MyThread my1 = new MyThread();
        MyThread my2 = new MyThread();

        t1.setName("线程1");
        t2.setName("线程2");

//        my1.run();
//        my2.run();

        //void start() 导致此线程开始执行; Java虚拟机调用此线程的run方法
        my1.start();
        my2.start();
    }
}

/*
1.为什么要重写run()方法?
因为run()是用来封装被线程执行的代码

2.run()方法和start()方法的区别?
run():封装线程执行的代码,直接调用,相当于普通方法的调用
start():启动线程;然后由JVM调用此线程的run()方法
*/

(2)实现Runnable接口
public class MyRunnable implements Runnable {
    @Override
    public void run() {
        for(int i=0; i<100; i++) {
            System.out.println(Thread.currentThread().getName()+":"+i);
        }
    }
}

public class MyRunnableDemo {
    public static void main(String[] args) {
        //创建MyRunnable类的对象
        MyRunnable my = new MyRunnable();

        //创建Thread类的对象,把MyRunnable对象作为构造方法的参数
        //Thread(Runnable target)
//        Thread t1 = new Thread(my);
//        Thread t2 = new Thread(my);
        //Thread(Runnable target, String name)
        Thread t1 = new Thread(my,"坦克");
        Thread t2 = new Thread(my,"飞机");

        //启动线程
        t1.start();
        t2.start();
    }
}

  • 16
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值