Wanjia Huang

西南交通大学 软件工程

0%

【笔记】JAVA期末复习[上]

​ 2021年JAVA期末复习笔记

Java语言基础

  1. 动态数组的创建

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    public static void main(String[] args) {
    //输入n个实数,建立数组,排序后输出
    Scanner in = new Scanner(System.in);
    System.out.println("请输入n=");
    int i,j,n;
    n = in.nextInt();
    double a[]=new double[n];
    System.out.println("请输入n个实数");
    for(i=0;i<n;i++){
    a[i]=in.nextDouble();
    }
    }
  2. 控制台输入输出

    1
    2
    3
    4
    5
    6
    7
    8
    9
    用Scanner类实现数据输入
    (仅JDK1.50或更高版本支持)
    用法: import java.util.Scanner;
    Scanner in=new Scanner(System.in);
    String s=in.next(); //输入1个字符串(空格/Tab/换行分隔)
    String t=in.nextLine(); //输入1个字符串(换行分隔)
    int a=in.nextInt(); //输入1个整数
    float b=in.nextFloat(); //输入1个单精度实数
    double c=in.nextDouble(); //输入1个双精度实数
  3. 数组的定义与使用

    1
    2
    3
    4
    5
    6
    7
    8
      先定义数组名再使用new
    syntax: 数组名=new T[元素个数];
    例: float a[];
    a=new float[10]; // 数组a有10个元素
     已分配空间的数组可以用new重新分配空间
    例: double a[]=new double[5]; // 数组a有5个元素

    a=new double[10]; // 数组a重新分配10个元素

    二维数组

    image-20211223090849349
  4. 标识符的语法规定

大小写约定:变量名小写开头;类名大写开头.

  1. Java变量

    Java程序中不允许在类定义之外定义全局变量,即Java语言没有全局变量的概念; Java没有指针类型的变量,从而提高了程序的可读性和安全性。

  2. Java类外不能定义函数,因此所有函数必须定义在某个类中;

类与对象基础

  1. 类是抽象的概念,仅仅是模板

    对象是一个你能够看得到、摸得着的具体实体

  2. 初始值及同名问题

    • Java会给成员变量一个初始值
    • Java不会给局部变量赋予初始值
    • 在同一个类中,成员变量和局部变量同名时,局部变量具有更高的优先级
  3. java doc注释

    使用“/*”开始和“/”结束,用来注释类、属性和方法等

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    /**
    * mySchool类
    *@author John
    *@version 1.0 2016/06/21
    */
    方法的doc注释
    /**
    * 计算总成绩
    * @return total
    */

    JavaDoc能够从源代码中抽取类、属性、方法等的注释,形成一个配套的API帮助文档

  4. 调用方法时不能指定实参类型!

  5. 包管理

    创建包使用关键字package
    导入包使用关键字import

  6. 方法重载

    • 一个类名字相同的多个方法

    • 这些方法的参数必须不同。Java可通过参数列表的不同来辨别重载的方法

    • 返回值可以相同,也可以不同

  7. 类的访问控制

    面向对象的三大特性:封装,继承,多态

    封装的步骤:1.修改属性可见性 2.创建共有的setter/getter方法 3.在setter/getter方法中加入属性控制语句

    • 类的访问控制

      • 类的访问控制只有两种,无修饰符(缺省)以及public,当使用无修饰符时,其他包的类不能访问。
    • 类成员的访问控制

      ·公有(public)
      可以被其他任何对象访问(前提是对类成员所在的类有访问权限)
      ·保护(protected)
      只可被同一类及其子类的实例对象访问
      ·私有(private)
      只能被这个类本身访问,在类外不可见
      `默认(default)
      仅允许同一个包内的访问;又被称为“包(package)访问权限”

    • 关键字“this”

      如果形式参数名与实例变量名相同,则需要在实例变量名之前加this关键字,否则系统会将实例变量当成形式参数。

  8. 构造方法

    • 一种和类同名的特殊方法,用来初始化对象

    • Java中的每个类都有构造方法,用来初始化该类的一个新的对象,没有定义构造方法的类,系统自动提供默认的构造方法

    • 特点

      • 方法名与类相同
      • 没有返回类型,修饰符void也不行
      • 通常被声明为公有的
      • 可以有任意多个参数
      • 主要工作是完成对象的初始化
      • 不能在程序中显式的调用【显示调用即为直接使用类名调用,隐式调用的思想是构件不直接调用一个过程,而是触发或广播一个或多个事件。系统中的其它构件中的过程在一个或多个事件中注册,当一个事件被触发,系统自动调用在这个事件中注册的所有过程,这样,一个事件的触发就导致了另一模块中的过程的调用。】
      • 在生成一个对象时,系统会自动调用该类的构造方法为新生成的对象初始化
    • 默认构造方法

      • 如果类的声明中没有声明构造方法,那么Java编译器会提供一个默认的构造方法
      • 默认构造方法没有参数,其方法体为空
      • 使用默认的构造方法初始化对象时,如果在类声明中没有给实例变量赋初值,则对象的属性值为零或空
    • 自定义构造方法与重载

      • 构造方法可以被重载,其重载与方法的重载一致。
      • 在方法调用时,Java可以通过参数列表的不同来辨别应调用哪一个方法
    • 自定义无参构造方法(易错,重要)

      • 无参的构造方法对其子类的声明很重要。如果在一个类中不存在无参的构造方法,则要求其子类声明时必须声明构造方法,否则在子类对象的初始化时会出错

      • 用户在进行类声明时,如果没有声明任何构造方法,系统会赋给此类一个默认(无参)的构造方法。但是,只要用户声明了构造方法,即使没有声明无参的构造方法,系统也不再赋默认的构造方法

      • ```java
        class Bush {
        Bush(int i) {}
        Bush(double d) {}
        }
        如果写:new Bush();
        编译器将要告诉你找不到对应的构造方法

        1
        2
        3
        4
        5
        6
        7
        8
        9
        10
        11
        12
        13

        改正的方法是要再声明一个无参的构造方法。

        9. 静态变量【类变量】

        - 也称为静态变量,声明时需要加static修饰符

        - 不管类的对象有多少,类变量只存在一份,在整个类中只有一个值

        - **类初始化的同时就被赋值**

        - 调用方式

        类名.属性
        类名.方法名()
        对象.属性
        对象.方法名()

        1
        2
        3
        4
        5
        6
        7
        8
        9
        10
        11
        12
        13
        14
        15
        16
        17
        18



        ## 继承

        1. JAVA只支持类的单继承,每个子类只能有一个直接父类【但是可以用接口实现多重继承】

        子类对象与父类对象存在“IS A”(或“is a kind of”)的关系

        父类是所有子类的公共属性及方法的集合,子类则是父类的特殊化

        2. 继承的语法

        ```java
        class childClass extends parentClass
        {
        //类体
        }
  9. 属性隐藏

    • 子类中声明了与父类中相同的成员变量名,则从父类继承的变量将被隐藏。

    • 访问隐藏的父类属性【两种方法】

      • 调用从父类继承的方法,则操作的就是父类继承的属性

      • 调用被隐藏的属性

        1
        super.属性
  10. 方法覆盖

    • 覆盖方法的返回类型,方法名称,参数的个数及类型必须和被覆盖的方法一摸一样

    • 覆盖方法的访问权限可以比被覆盖的宽松,但是不能更为严格

    • 必须覆盖的方法

      派生类必须覆盖基类中的抽象的方法,否则派生类自身也成为抽象类.

    • 不能覆盖的方法

      • 基类中声明为final的终结方法
      • 基类中声明为static 的静态方法
  11. 有继承时的构造方法【易错】

    遵循以下原则:

    • 子类不能从父类继承构造方法

    • 好的程序设计方法是在子类的构造方法中调用某一个父类构造方法,调用语句必须出现在子类构造方法的第一行,可使用super关键字

      1
      2
      3
      4
      public Professor(int aNumber, String aPhoneNumber, String aResearch) {
      super(aNumber, aPhoneNumber);
      research = aResearch;
      }
    • 如子类构造方法的声明中没有明确调用父类构造方法,则系统在执行子类的构造方法时会自动调用父类的默认构造方法(即无参的构造方法)

  12. 终结类与终结方法

    • 定义

      被final修饰符修饰的类和方法

    • 特点

      终结类:不能有派生类

      终结方法:不能被派生类覆盖

    • 终结类作用

      • 安全:黑客用来搅乱系统的一个手法是建立一个类的派生类,然后用他们的类代替原来的类
      • 设计:你认为你的类是最好的或从概念上你的类不应该有任何派生类
    • 终结方法作用

      • 对于一些比较重要且不希望子类进行更改的方法,可以声明为终结方法。可防止子类对父类关键方法的错误重写,增加了代码的安全性和正确性
      • 提高运行效率。通常,当java运行环境(如java解释器)运行方法时,它将首先在当前类中查找该方法,接下来在其超类中查找,并一直沿类层次向上查找,直到找到该方法为止
  13. 抽象类及抽象方法

    • 定义及特点

      • 代表一个抽象概念的类
      • 没有具体实例化对象的类,不能用new进行实例化
      • 类前需要加修饰符abstract
      • 可包含常规类能够包含的任何东西,例如构造方法,非抽象方法
      • 也可包含抽象方法,这种方法只有方法的声明,而没有方法的实现
      • 只有抽象类才能有抽象方法,即如果一个类中含有抽象方法,则必须将这个类声明为抽象类
    • 定义

      • 抽象类的定义

        1
        2
        3
        abstract class Number {
        . . .
        }
      • 抽象方法的定义

        1
        public abstract <returnType> <methodName>(...);

        仅有方法头,而没有方法体和操作实现
        具体实现由当前类的不同子类在它们各自的类声明中完成

  14. 类的组合

    • 继承是”is a”,组合是”has a”

接口与多态

  1. 接口定义

    • 与抽象类一样都是定义多个类的共同属性
    • 使抽象的概念更深入了一层,是一个“纯”抽象类,它只提供一种形式,并不提供实现
  2. 接口语法

    • 声明格式

      1
      2
      3
      [接口修饰符] interface 接口名称 [extends 父接口名]{
      //方法的原型声明或静态常量
      }
    • 数据成员要求

      数据成员一定要赋初值,并且不能再修改,允许直接省略final关键字

    • 方法要求

      接口中的方法必须是“抽象方法”,不允许有方法体,允许省略public及abstract关键字

  3. 接口的实现

    • 接口不能用new运算符直接产生对象,必须利用其特性设计新的类,再用新类来创建对象

    • 利用接口设计类的过程,称为接口的实现,使用implements关键字

    • 语法

      1
      2
      3
      4
      public class 类名称 implements 接口名称 { 
      /* Bodies for the interface methods */
      /* Own data and methods. */
      }

      注意:必须实现接口的所有方法,来自接口的方法必须声明为public

  4. 多重继承

    • Java的设计以简单实用为导向,不允许一个类有多个父类

    • 但允许一个类可以实现多个接口,通过这种机制可实现多重继承

    • 语法

      1
      2
      3
      4
      [类修饰符] class  类名称  implements 接口1,接口2,  …
      {
      … …
      }
  5. 接口的扩展

    继承的接口应该实现原先接口的所有方法

  6. 塑型

    • 又称类型转换
    • 有两种方式,显式跟隐式
    • 塑型的对象
      • 基本数据类型
      • 引用变量
        • 将对象暂时当成更一般的对象来对待,并不改变其类型
        • 只能被塑型为
          • 任何一个父类类型
          • 对象所属的类实现的一个接口
          • 被塑型为父类或接口后,再被塑型回其本身所在的类
          • image-20211223105502771
    • 塑型为父类之后,方法会减少
  7. 静态绑定与动态绑定

    • 什么是绑定

      • 方法定义与方法调用的关联称为绑定
    • 静态绑定

      • 编译器在编译时可以解析的绑定称为静态或早期绑定。staticprivatefinal构造方法的绑定是编译时为什么? 原因是无法覆盖这些方法,并且在编译时确定类的类型。

      • 示例:在这里,我们有两个类人类和男孩。这两个类都有相同的方法walk(),但方法是静态的,这意味着它不能被覆盖,所以即使我在创建对象obj时使用了Boy类的对象,它也会调用父类方法。因为引用是Human类型(父类)。因此,每当静态,私有和最终方法的绑定发生时,类的类型由编译器在编译时确定,然后绑定发生在那里。

        1
        2
        3
        4
        5
        6
        7
        8
        9
        10
        11
        12
        13
        14
        15
        16
        17
        18
        19
        20
        21
        22
        23
        class Human{
        public static void walk()
        {
        System.out.println("Human walks");
        }
        }
        class Boy extends Human{
        public static void walk(){
        System.out.println("Boy walks");
        }
        public static void main( String args[]) {
        /* Reference is of Human type and object is
        * Boy type
        */
        Human obj = new Boy();
        /* Reference is of HUman type and object is
        * of Human type.
        */
        Human obj2 = new Human();
        obj.walk();
        obj2.walk();
        }
        }

        输出:

        1
        2
        Human walks
        Human walks
    • 动态绑定

      • 当编译器无法在编译时解析调用/绑定时,此类绑定称为动态绑定或后期绑定。方法覆盖是动态绑定的一个完美示例,因为覆盖父类和子类具有相同的方法,在这种情况下,对象的类型确定要执行的方法。对象的类型在运行时确定,因此称为动态绑定
    • 二次分发

      • 对输出消息的请求被分发两次

      • ```java
        public class Car{
        public void start(){
        System.out.println(“Car start”);
        }
        }

        public class CarA extents Car{
        public void start(){
        System.out.println(“CarA start”);
        }
        }

        public class CarB extents Car{
        public void start(){
        System.out.println(“CarB start”);
        }
        }

        public class DoMain{
        public void startCar(Car car){
        System.out.println(“car start”);
        }

        public void startCar(CarA carA){
        System.out.println(“CarA start”);
        }

        public void startCar(CarB carB){
        System.out.println(“CarB start”);
        }

        public static void main(String[] args){
        Car car = new Car();
        Car carA = new CarA();
        Car carB = new CarB();

        DoMain domain = new DoMain();
        domain.startCar(car);
        domain.startCar(carA);
        domain.startCar(carB);
        }
        }

        1
        2
        3
        4
        5
        6
        7
        8
        9
        10
        11
        12
        13
        14
        15
        16
        17
        18
        19
        20
        21
        22
        23
        24
        25
        26
        27
        28
        29
        30

        这里的结果很简单:3次都是 `Car start`,因为这里涉及到了java中放入静态绑定,也就是说`domain`实例调用哪个方法是在编译期就确定了,而编译期间三次调用的方法的参数都是`Car`类型的。而关于jvm的静态绑定和动态绑定又是另外一方面的内容了,所以这里就不展开来讲了。

        改进之后:

        ```JAVA
        public class DoMain{
        public void startCar(Car car){
        car.start();
        }

        public void startCar(CarA carA){
        carA.start();
        }

        public void startCar(CarB carB){
        carB.start();
        }

        public static void main(String[] args){
        Car car = new Car();
        Car carA = new CarA();
        Car carB = new CarB();

        DoMain domain = new DoMain();
        domain.startCar(car);
        domain.startCar(carA);
        domain.startCar(carB);
        }
        }

字符串

  1. 字符串是常量,它们的值在创建之后不能被修改

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    public static void main(String[] args)
    {
    String s = "ABCDEF";
    System.out.println("s = " + s);
    s = "123456";
    System.out.println("s = " + s);
    }
    打印的结果:
    s = ABCDEF
    s = 123456

    从结果上看,确实是如此,s的值改变了。

    •其实,这里存在一个误区,s呢 ,仅仅是一个String对象的引用并不是对象本身。对象在内存中是一块内存区,而s只是一个引用,它指向了一个具体的对象。

    •在创建String对象的时候,s指向的是内存中的”ABDCEF”,当执行语句s = “123456”后,其实又创建了一个新的对象”123456”,而s重新指向了这个新的对象,同时原来的”ABCDEF”并没有发生改变,仍保存在内存中。

    • 无论你是用s=新的s,还是s=s.replace,这里虽然打印出来的值变了,但其实是其将引用s指向了一个新的String对象
    • value成员变量是private final修饰的,而String类中并没有提供set/get等公共方法来修改值,所以String类的外部无法修改String,同时final保证了在String内部,只要值初始化了,也不能被改变。
  2. 字符缓冲区支持可变的字符串

    • 在使用String同StringBuffer类时,虽然两者都是final类,不允许被继承,在本质上都是字符数组。
      • 不同的是,String的长度是不可变的而后者长度可变,在进行连接操作时,String每次返回一个新的String实例,而StringBuffer的append方法直接返回this
      • 所以当进行大量的字符串连接操作时,不推荐使用String因为它会产生大量的中间String对象
  3. String类常用方法

    • length()

      返回此字符串长度

    • equals()

      比较存储在两个字符串对象的内容是否一致

    • image-20211223134307967
    • 字符串比较,不考虑大小写

      使用equalsIgnoreCase()方法
      使用toLowerCase()方法
      使用toUpperCase( )方法

    • 字符串连接

      • 使用“+”

        1
        s=s1+s2
      • 使用.concat()方法

        1
        2
        3
        4
        String s = new String("你好,");
        String name = new String("张三!");
        String sentence = s.concat(name);
        System.out.println(sentence);
    • 字符串检查

      • 如检查邮箱格式是否正确

      • ```java
        //检查邮箱格式
        if (email.indexOf(‘@’) !=- 1 && email.indexOf(‘.’) != -1 > email.indexOf(‘@’)){
        emailCorrect = true;
        }else{
        System.out.println(“Email无效。”);
        }

        1
        2
        3
        4
        5
        6
        7
        8
        9
        10
        11
        12
        13
        14
        15
        16
        17
        18
        19
        20
        21
        22
        23
        24

        - substring

        - public String substring(int beginindex, int endindex)
        - 提取beginindex和endindex之间的字符串部分
        - beginindex: 字符串的位置从0开始算;endindex: 字符串的位置从1开始算

        - 字符串拆分

        - String类提供了split()方法,将一个字符串分割为子字符串,结果作为字符串数组返回

        - ```java
        public class Lyric {
        public static void main(String[] args) {
        String words="长亭外 古道边 芳草碧连天 晚风扶 柳笛声残 夕阳山外山";
        String[ ] printword=new String[100];
        System.out.println("***原歌词格式***\n"+words);
        System.out.println("\n***拆分后歌词格式***");
        printword=words.split(" "); //拆分字符串,返回值为字符串数组
        for(int i=0;i<printword.length;i++){
        System.out.println( printword[i] );
        }
        }
        }
  4. StringBuffer

    • 声明

      1
      StringBuffer sb = new StringBuffer();
    • 用法

      sb.toString(); //转化为String类型
      sb.append("**"); //追加字符串
      sb.insert (1, “**”); //插入字符串

  5. 总结

    String类提供了大量的操作字符串的方法
    获得字符串的长度:length()
    比较字符串:equals()
    连接字符串:concat()
    提取字符串:substring()
    搜索字符串:indexOf()
    拆分字符串:split()
    常用的StringBuffer类提供的方法
    转换成String类型:toString()
    连接字符串:append()
    插入字符串:insert()

异常

  1. JAVA如何进行异常处理

    image-20211223140721153 image-20211223141146046
    • 异常对象常用的方法

      方法名 说 明
      void printStackTrace() 输出异常的堆栈信息
      String getMessage() 返回异常信息描述字符串, 是printStackTrace()输出信息的一部分
      image-20211223141325068 image-20211223141358751
  2. 常见异常类型

    异 常 类 型 说 明
    Exception 异常层次结构的父类
    ArithmeticException 算术错误情形,如以零作除数
    ArrayIndexOutOfBoundsException 数组下标越界
    NullPointerException 尝试访问 null 对象成员
    ClassNotFoundException 不能加载所需的类
    IllegalArgumentException 方法接收到非法参数
    ClassCastException 对象强制类型转换出错
    NumberFormatException 数字格式转换异常,如把”abc”转换成数字
  3. try-catch-finally【重点】

    image-20211223141653908

    finally 关键字用来创建在 try 代码块后面执行的代码块。

    无论是否发生异常,finally 代码块中的代码总会被执行。

    在 finally 代码块中,可以运行清理类型等收尾善后性质的语句。

    finally 代码块出现在 catch 代码块最后,语法如下:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    try{
    // 程序代码
    }catch(异常类型1 异常的变量名1){
    // 程序代码
    }catch(异常类型2 异常的变量名2){
    // 程序代码
    }finally{
    // 程序代码
    }
  4. 存在return的try-catch-finally块

    image-20211223142330201
  5. 多重catch【重点】

    image-20211223142149274
  6. 两个问题

    • 面试题:try-catch块中存在return语句,是否还执行finally块,如果执行,说出执行顺序
      • 还执行
      • 先执行finally块,再执行return语句
    • try-catch- finally块中, finally块唯一不执行的情况是什么?
      • exit(1);
  7. throw和throws的区别

    ​ throws: 当一个方法产生一个它不处理的异常时,那么就需要在该方法的头部声明这个异常,以便将该异常传递到方法的外部进行处理。使用 throws 声明的方法表示此方法不处理异常。

    1
    returnType method_name(paramList) throws Exception 1,Exception2,…{…}

    ​ 子类方法声明抛出的异常类型应该是父类方法声明抛出的异常类型的子类或相同,子类方法声明抛出的异常不允许比父类方法声明抛出的异常多。

    ​ throw: throw 语句用来直接拋出一个异常,后接一个可拋出的异常类对象,其语法格式如下:

    1
    throw ExceptionObject;
    • throws表示出现异常的一种可能性,并不一定会发生这些异常;throw则是抛出了异常,执行throw则一定抛出了某种异常
    • 两种不会由函数去处理,真正的处理由函数的上层调用处理
    • throw是具体向外抛异常的,抛出的是一个异常实例;throws声明了是哪种类型的异常,使它的调用者可以捕获这个异常
    • throws出现在方法函数头;而throw出现在函数体
    • 通常在一个方法(类)的声明处通过 throws 声明方法(类)可能拋出的异常信息,而在方法(类)内部通过 throw 声明一个具体的异常信息。

Applet

java.awt包含用于创建用户界面和绘制图形图像的所有类

  1. Applet工作原理

    • Applet与Application的不同

      Applet与Application的主要区别在于它们的执行方式不同
      Application是使用命令行命令直接运行,从其main()方法开始运行的;
      Applet则是在浏览器中运行的;

    • Applet程序开发主要步骤

      • 编辑建立Java Applet源程序
      • 编译Applet源程序生成字节码文件
      • 编辑建立HTML文件,在HTML文件内利用
        <applet>标记,嵌入Applet小应用程序。
      • 直接在浏览器中运行
    • first Applet

      • ```java
        import java.applet.*;
        public class MyApplet extends Applet

    { … …}

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12

    每一个小应用程序都继承自java.applet.Applet类,而且必 须是public类,与文件名同名;

    - 编辑HTML网页文件;嵌入小应用程序

    ```html
    hello.html:
    <HTML>
    <HEAD>
    <TITLE>嵌入网页中的应用程序</TITLE> </HEAD>
    <APPLET CODE="HelloApplet.class" WIDTH=200 HEIGHT=100>
    </HTML>

  2. Applet生命周期

    小应用程序的生命周期与浏览器相关,完全由浏览器控制;

    1. 打开浏览器时,创建(init)方法运行;
      • Applet第一次加载时,自动调用创建并初始化Applet 对象;
      • 他只会被加载一次
    2. 显示Applet时,启动(start)方法运行;
      • 浏览器运行Applet时,start方法会被自动调用;
      • 或者从其它页面返回包含Applet的页面时,start方法也会被自动调用;
      • start方法可被多次调用
    3. 不显示Applet时,停止(stop)方法运行;
      • 离开Applet所在页面时,会调用stop()停止Applet的运行;
      • stop作用: 用户离开包含Applet的页面时,停止一些耗费系统资源的活动,如播放动画,播放音乐文件等。
      • 如果Applet中没有动画、音乐文件,可不使用
    4. 关闭浏览器时,撤销(destroy)方法运行;
  3. Graphics

    任何与绘图有关的操作第一 个要用的是java.awt.Graphics类, Graphics类的对象不是由new产生的, 而是由系统或其他方式直接将生成好的 Graphics对象当作方法的参数,再交 给程序设计者去处理.

    1
    paint(Graphics g)

    相关的函数:

    • drawLine

      • public abstract void drawLine(int x1, int y1, int x2, int y2)

      • 在此图形上下文的坐标系中,使用当前颜色在点 (x1, y1) 和 (x2, y2) 之间画一条线。

      • ```java
        public void paint(Graphics g) {
        g.drawLine(20,200,300,200);
        g.drawLine(20,200,20,20);
        g.drawLine(20,170,15,170);
        g.drawLine(20,140,15,140);
        g.drawLine(20,110,15,110);
        g.drawLine(20,80,15,80);
        g.drawLine(20,50,15,50);
        }

        1
        2
        3
        4
        5
        6
        7
        8
        9

        - **drawString**

        - public abstract void drawString(String str, int x, int y)

        - 使用此图形上下文的当前字体和颜色绘制由指定 string 给定的文本。最左侧字符的基线位于此图形上下文坐标系的 (x, y) 位置处。

        - ```java
        g.drawString("50-60",25,213)
    • fillRect

      • public abstract void fillRect(int x, int y, int width, int height)
      • 填充指定的矩形。该矩形左边缘和右边缘分别位于 x 和 x + width - 1。上边缘和下边缘分别位于 y 和 y + height - 1。得到的矩形覆盖 width 像素宽乘以 height 像素高的区域。使用图形上下文的当前颜色填充该矩形。
  4. Color类

    • g.setColor(Color.red);设置红色

    • 其他设置颜色方法

      • Color(int r,int g,int b) //RGB
      • Color(int rgb)
    • ```java
      Color c = new Color(0,255,0);
      g.setColor(c);

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      19
      20
      21
      22
      23
      24

      5. Font类

      - 常用构造方法
      - Font(字体名,字型,字号)

      ## GUI设计

      1. 界面的基本组织方式

      - 由JFrame创建初始的用户界面
      - 由JPanel、JscrollPane、JTabbedPane等创建中间容器
      - 由基本组件类创建有关的组件
      - 将基本组件按照某种布局添加到中间容器中。
      - 将中间容器按照某种布局添加到顶层容器中,形成满足用户需求的操作界面

      2. DEMO1 获得JFrame的容器并添加组件

      ```java
      Container con = getContentPane();
      JPanel panel = new JPanel();
      JButton butt = new JButton("Press Me");
      panel.add(butt);
      con.add(panel);
  5. JLabel

    标签(JLabel)是最简单的组件,用于显示单行静态文本。用户只能查看其内容而不能对其进行修改。

    1
    JLabel label1 = new JLabel(“姓名”);
  6. JButton

    1
    JButton b_sub=new JButton("确认");
  7. 文本框

    • JTextField:单行的文本框

      【记忆点:setEditable()方法可以设置是否可编辑】

      1
      2
      JTextField tf1 = new JTextField(10);
      pan.add(tf1);
    • JTextArea:多行的文本区

      应用中经常将文本区对象放入一个滚动窗格中,以使用滚动条功能,方法如下

      1
      2
      3
      JTextArea result=new JTextArea(10,30);
      JScrollPane sp=new JScrollPane(result);
      pan.add(sp);
  8. 单选按钮(JRadioButton)

    使用单选按钮经常用到ButtonGrup类,其负责维持只有一个单选按钮处于选中状态,如下

    1. 创建按钮对象

      ButtonGroup bg = new ButoonGroup();

    2. 创建若干单选按钮对象

      JRadioButton b1 = new JRadioButton(“x”);

      JRadioButton b2 = new JRadioButton(“y”);

    3. 将各单选按钮添加到按钮组中

      bg.add(b1);

      bg.add(b2);

    4. 将单选按钮添加到其他容器中

      容器对象.add(b1);

      容器对象.add(b2);

  9. 复选框 JCheckbox

    1
    2
    3
    4
    5
    6
    Jlabel l_ah=new JLabel("爱好");
    JCheckBox[] hobby={new JCheckBox("音乐"),new JCheckBox("足球"),new JCheckBox("绘画")};
    pan.add(l_ah);
    pan.add(hobby[0]);
    pan.add(hobby[1]);
    pan.add(hobby[2]);

    image-20211223154721967

  10. JList【列表框】

    1
    2
    3
    4
    5
    6
    7
    8
    9
    JLabel   l_xk=new JLabel("选课");
    String[] coursesNames = {"数据结构“,"操作系统“,"网络原理",
    "Java程序设计“,"分布式系统开发技术",
    "计算机导论“,"密码学",
    "计算机组成原理“,"编译原理",
    "图形学”};
    course = new JList(coursesNames);
    pan.add(l_xk);
    pan.add(course);

image-20211223154914038

  1. JComboBox【下拉列表】

    1
    2
    3
    4
    5
    6
    7
    8
    9
    JLabel  l_yx=new JLabel("院系");
    pan.add(l_yx);
    String[] departmentNames = {
    "计算机科学与技术系",
    "电子信息与技术系",
    "计算机工程系”};
    JComboBox department = new JComboBox(departmentNames);
    department.setEditable(false);
    pan.add(department);

    image-20211223155213013

  2. JPasswordField【密码域】

    1
    2
    3
    password=new JPasswordField(20);
    password.setEchoChar('*');
    pan.add(password);

    image-20211223155224836

  3. JSlider【滑动条】

  4. 布局

    • BorderLayout

      image-20211223155733385
      1
      按照东、西、南、北、中5个方位排列各组件
      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      创建BorderLayout布局对象BorderLayout l = new BorderLayout();
      创建容器对象 JPanel panel = new JPanel();
      设置容器对象的布局或使用默认布局 panel.setLayout(l);
      向容器中添加组件对象(设组件对象已创建) panel.add(组件对象,方位);
      //方位的取值为: BorderLayout.EAST 或
      “East” BorderLayout.WEST 或
      “West” BorderLayout.SOUTH
      或 “South” BorderLayout.NORTH
      或 “North” BorderLayout.CENTER
      或 “Center”(默认)
    • GridLayout

      • 按照二维网格以相同大小依次排列各组件

      • ```java
        GridLayout();//一行、每个组件一列
        GridLayout(int rows,int cols);//行列数
        GridLayout(rows,cols,int hgap,int vgap); //行行、列列的间距,默认值为0个像素

        1
        2
        3
        4
        5
        6
        7
        8
        9
        10
        11
        12

        - 布局的使用

        ```java
        创建GridLayout布局对象
        GridLayout l = new GridLayout(2,2);
        创建容器对象
        JPanel panel = new JPanel();
        设置容器对象的布局或使用默认布局
        panel.setLayout(l);
        向容器中添加组件对象(设组件对象已创建)
        panel.add(组件对象);

        FlowLayout:Ø该布局以行为单位依次排列各组件,一行排不下时,另起一行,其为JPanel的默认布局

        BorderLayout:按照东、西、南、北、中5个方位排列各组件 顶层容器的默认布局都是BorderLayout

        GridLayout:按照二维网格以相同大小依次排列各组件

AWT组件及其事件处理机制

  1. 委托事件模型

    当事件发生时,产生事件对象(即事件源),会把信息转给“事件监听器”处理的一种方式。
    信息是java.awt.event事件类库中,某个类所创建的对象,称为“事件对象(event object)”

  2. 三个重要概念

    1.事件源——发生事件的对象,如:按钮
    2.监听器——对事件源实施监视的对象,如:包含按钮的窗口
    3.处理事件的接口——监听器对象自动调用一个方法,负责处理事件源发生的事件。

  3. 最简单的实现流程

    • 导入ActionEvent事件包

      • import java.awt.event.*
    • 类MyFrame声明实现ActionListener接口

      • ```java
        class MyFrame extends Frame implements ActionListener{
        }
        1
        2
        3
        4
        5

        - 将窗口注册为btnChange的监听器

        - ```java
        btnChange.addActionListener(this);
    • 实现接口的方法

      • ```java
        public void actionPerformed(ActionEvent e) //④实现接口的方法
        {
        setBackground(Color.yellow);
        }
        1
        2
        3
        4
        5
        6
        7
        8
        9
        10
        11
        12
        13
        14
        15
        16
        17
        18
        19
        20
        21
        22
        23
        24
        25
        26
        27
        28
        29
        30
        31
        32
        33
        34

        - ```java
        import java.awt.*;
        import java.awt.event.*; // ①导入ActionEvent事件包

        class MyFrame extends Frame implements ActionListener
        // ②类MyFrame声明实现ActionListener接口
        {
        Button btnChange=new Button("变色");
        MyFrame(String s)
        {
        super(s);
        setSize(300,200);
        setBackground(Color.white);
        setResizable(false);
        setVisible(true);
        setLayout(new FlowLayout());

        add(btnChange);
        btnChange.addActionListener(this); //③将窗口注册为btnChange的监听器
        }
        public void actionPerformed(ActionEvent e) //④实现接口的方法
        {
        setBackground(Color.yellow);
        }
        }
        public class testButton
        {
        public static void main(String args[])
        {
        MyFrame myFrm=new MyFrame("变色窗口");
        }
        }

    • image-20211223160954314
  4. 部分事件类、监听接口及接口中的方法

    事件源 产生事件****的类型 监听器接口 监听器接口提供的方法
    Button ActionEvent ActionListener actionPerformed(ActionEvent e)
    CheckBox ItemEvent ItemListener itemStateChange(ItemEvent e)
    TextField ActionEvent****TextEvent ActionListener****TextListener **actionPerformed(ActionEvent e)textValueChange(TextEvent **e)
    Window WindowEvent WindowListener windowActivated(WindowEvent **e)**windowClosing(WindowEvent **e)**windowOpened(WindowEvent **e)**……
  5. 例子:猜数字

    1
    2
    3
    4
    5
    6
    7
    step1:
    声明组件
    private int number;
    Button button_getnum = new Button("得到随机数");
    Button button_yep = new Button("确定");
    Label label_info = new Label("请输入你的猜测",Label.CENTER);
    TextField tx = new TextField("0",10);
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    step2:
    设置窗口属性,这一步在该类的构造函数里面写。
    guessFrame(String s)
    {
    super(s);
    setSize(300,200);
    setResizable(false);
    setVisible(true);
    setLayout(null);
    }
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    step3:
    添加控件
    guessFrame(String s)
    {
    super(s);
    setSize(300,200);
    setResizable(false);
    setVisible(true);
    setLayout(null);

    lblInfo.setBounds(50,50,120,20);
    add(lblInfo);
    txtInput.setBounds(50,80,120,20);
    add(txtInput);
    btnGetNum.setBounds(50,120,80,20);
    add(btnGetNum);
    btnEnter.setBounds(150,120,50,20);
    add(btnEnter);
    }
    1
    2
    3
    4
    step4:
    添加监听器【控件.addActionListener】
    btn_getnum.addActionListener(this);
    btn_yep.addActionListener(this);
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    step5:
    实现ActionListener接口中的actionPerformed方法
    【记忆点:lable.getText()可以取文本框中的值】
    【记忆点:Integer.parseInt(String)可以将String转换为Int】
    【记忆点:NumberFormatException为值类型异常】
    public void actionPerformed(ActionEvent e)
    {
    if(e.getSource()==btnGetNum) //单击 “得到随机数”接钮
    {
    number=(int)(Math.random()*100)+1;
    }
    else if(e.getSource()==btnEnter) //单击 “确定”接钮
    {
    int guess=0;
    try
    {
    guess=Integer.parseInt(txtInput.getText()); //获取文本框中的数值
    if (guess==number)
    {
    lblInfo.setText("你猜对!");
    }
    else if(guess>number)
    {
    lblInfo.setText("你猜高了!");
    txtInput.setText(null);
    }
    else if(guess<number)
    {
    lblInfo.setText("你猜低了!");
    txtInput.setText(null);
    }
    }
    catch(NumberFormatException event)
    {
    lblInfo.setText("请输入数字字符");
    }
    }
    }
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    public class guessFrame extends Frame implements ActionListener
    {
    private number;
    TextFiled txt = new TextFiled(0,"10");
    Button btn1 = new Button("得到随机数");
    Button btn2 = new Button("确定");
    Label label_info = new Label("请输入你的猜测",Label.CENTER);

    guessFrame(String s){
    super(s);
    setResizable(false); //这里拼错了
    setVisiable(true);
    setLayout(null); //这里忘了

    add(label_info);
    ...;

    }

    public void actionPerformed(ActionEvent e){
    if(e.getSource()==btn1){
    number = (int)(Math.random()*100)+1;
    }
    else if(e.getSource()==btn2){
    int guess =0;
    try{
    guess=Integer.parseInt(txtInput.getText());
    if(guess = number){
    ...
    }
    else if(guess < number){
    ...
    }
    else if(guess > number){
    ...
    }
    }
    }
    }
    }