java复习

java复习

第一章

java的特点

  • 平台无关性 利用虚拟机
  • 面向对象 封装 继承 多态
  • 多线程
  • 安全
  • 动态

java 3种平台

  • Java SE 标准版

  • Java EE 企业版

  • Java ME 微型版

应用程序主类

  • public static void main(String args[]){}

源文件命名规则

  • 只能有一个类是public类
  • 源文件的名字必须与这个public类名字完全相同扩展名是.java
  • 如果源文件没有public类,那么源文件的名字只要与某个类名字相同即可 .java
  • 区分大小写

问答题

  • 源文件生成的字节码在运行时都加载到内存中吗

    • 不是,动态随运行需要才加载
  • 字节码不是机器码

  • 为什么java程序可以跨平台

    • java具有平台无关性,利用java虚拟机
  • 在Java程序中有多个类文件时,用Java命令应该运行那个类?

    • 具有main方法的类

第二章

标志符和关键字

  • 标志符:用来标志类名、变量名....

    • 规则:由字母、下划线、美元符号和数字组成,并且第一个字符不能是数字 区分大小写 不能是关键字
  • 关键字:java中被赋予特定意义的一些单词

    • P22

Scanner

  • sc.nextByte() sc.nextDouble() ...
  • sc.hasNextDouble() sc.hasNextInt() ...

问答题

  • int x=120;

    byte b =120;

    b = x;

    哪条语句是错误的

    • b = x; -> b = (byte) x; 高精度向低精度转换要强转 byte取值范围从-128到127
  • byte b = (byte)(-129);

    • 由于byte数据范围限制 实际 b = 127; 溢出

第四章

成员变量

  • 静态(带static修饰符)成员变量/函数与普通成员变量/函数的区别:

    • 所有static成员变量/函数在类中只有一份被所有类的对象共享
    • 所有普通成员变量/函数在类的每个对象中都有独立的一份
    • 静态函数中只能调用静态函数/变量;普通函数中既可以调用普通函数/变量,也可以调用静态函数/变量。
  • 对于final成员变量,定义时必须初始化,对象可以操作使用,但不能更改

方法

  • 除构造方法外,类似C++里的函数,必须声明返回值。

  • 方法声明中用关键字static修饰的称为类方法或静态方法(只能调用类方法),不用static修饰的称为实例方法(都能调用)

  • 实例方法必须通过先new一个对象来调用

  • 类方法可以直接通过类名调用

  • 参数传值

    • 类似C++函数,不利用引用符号传值时,调用的方法内变量值改变不会改变main方法内原参数的值
    • 引用类型参数的传值 P61-62

方法重载

  • 方法重载是指一个类中可以有多个方法具有相同的名字,但这些方法的参数必须不同 或者是 参数的个数不同 或者是 参数的类型不同
  • 方法的返回类型参数的名字不参与比较
  • 如果两个方法的名字相同,即使方法类型不同,也必须保证参数不同。

  • 通过关键字package声明包语句

问答题

  • import java.awt.*; 和 import java.awt.Button 有什么不同

    • import java.awt.*; 导入awt包中的所有类,import java.awt.Button只引入Button一个类
  • 有哪几种访问权限修饰符?说出其中一种修饰符的作用。

    • public privae protected private作用是只允许本类对象访问

实验一

  • 编写Java程序,贪心猪游戏,一个简单的两人掷色子游戏,先达到或者超过100分的玩家获胜。玩家轮流进行游戏,每次掷出一个六面色字。

    如果玩家掷出1,不得分并换人。
    如果玩家掷出2-6,就可以选择:再掷一次,或保留得分。这样的话会吧所有得分计入该玩家的成绩并换人。
    请编写人家对贪心猪游戏程序。轮到玩家时,程序会显示双方成绩和之前的点数。玩家可以输入“r”重掷色子,或者输入“h”保留得分。

    计算机程序会根据以下规则进行游戏:

    轮到计算机游戏时候,持续掷色子,直到达到或者超过20分才予以保留。如果计算机获胜或掷出1,则本轮立即结束。
    玩家先掷色子。

package org.example;

public class Person_1 {
    private int sum, num;
    public int getSum() {
        return sum;
    }
    public void setSum(int sum) {
        this.sum = sum;
    }
    public int getNum() {
        return num;
    }
    public void setNum(int num) {
        this.num = num;
    }
}

   public void setNum(int num) {
        this.num = num;
    }
}

import java.util.*;
public class Main {
    public static void main(String[] args)
    {
        int flag=0;    //判断游戏是否结束
        Scanner scanner=new Scanner(System.in);
        Computer_1 computer=new Computer_1();   //创建计算机玩家
        Person_1 person=new Person_1();     //创建普通玩家
        while(true)
        {
            System.out.println("\n————普通玩家正在进行游戏————");
            int i=(int) (Math.random() * 6 + 1) ;     //生成随机数1—6
            int temp=0;       //是否跳过此轮
            if(i!=1) {          //如果玩家掷出1,不得分并换人,否则继续
                System.out.println("此轮点数为:"+i+",是否重掷(r/h):");
                String str=scanner.next();
                while((!str.equals("r"))&&(!str.equals("h"))){
                    System.out.println("请重新输入r或h:");
                    str=scanner.next();
                }
                while(str.equals("r")) {
                    i=(int) (Math.random() * 6 + 1) ;
                    if(i!=1){      //有选择地权力
                        System.out.println("此轮点数为:"+i+",是否重掷?(重掷:r/保留得分:h)");
                        str=scanner.next();
                    }
                    else {
                        System.out.println("此轮点数为:"+i+",无法重掷!");
                        temp=1;    //掷到1,无条件跳过
                        break;
                    }
                }
            }
            else{
                System.out.println("掷出点数1,结束本轮");
                temp=1;
            }
            if(temp!=1){     //允许保存
                person.setNum(i);
                person.setSum(person.getSum()+i);
            }
            System.out.println("普通玩家目前总点数为:"+person.getSum());
            if(person.getSum()>=100){      //普通玩家点数大于100
                System.out.println("普通玩家胜利!");
                flag=1;
            }
            if(flag==1)
                break;
            temp=0;      //归零
            System.out.println("————计算机玩家正在进行游戏————");
            i=(int) (Math.random() * 6 + 1) ;   //随机生成整数1-6
            int csum=0;
            while(temp==0){
                if(i!=1&&csum<20&&(csum+computer.getSum()<100))
                    csum+=i;  //计算机随机抛出的点数相加
                else
                    temp=1;
                System.out.println("此次点数为"+i+",此轮点数为:"+csum);
                i=(int) (Math.random() * 6 + 1) ;
            }
            if(csum>=20)   //抛出点数相加大于20保存
            {
                computer.setNum(csum);
                computer.setSum(computer.getSum()+csum);
            }
            else
                System.out.println("此轮点数不足20");
            System.out.println("计算机玩家目前总点数为:"+computer.getSum());
            if(computer.getSum()>=100){
                System.out.println("电脑玩家胜利!");
                flag=1;
            }
            if(flag==1)
                break;
        }
    }
}

第五章

继承

  • 关键字extends

  • 子类只能有一个父类

  • 子类能继承父类中 不是private的成员变量 和 不是private的方法,继承的父类方法可以直接利用子类访问

final类和final方法

  • final类不能被继承,即不能有子类,例如String类由于对编译器正常运行有重要作用,不能被轻易改变,故修饰为final类
  • final方法不能被重写

对象的上转型对象

  • 子类对象的上转型,即把子类创建的对象的引用放到一个父类的对象中

  • 上转型对象不是父类创建的对象,而是子类对象的“简化”形态,它不关心子类新增的功能,只关心子类继承重写的功能。

  • image-20240507152908395
  • 子类的上转型对象可以调用子类的方法,而父类则不行

  • image-20240507153620564

接口

  • 关键字interface定义接口 interface XXX

  • 接口体中包含常量定义和方法定义,接口体只进行方法声明,不提供方法实现

    • 例如

      interface Printable{
      	final int Max = 100;
          void add();
          float sum(float x, float y);
      }
      
  • 一个类通过使用关键字implements声明自己实现一个或多个接口

    • class A implments Printabl, Addable
    • 如果一个类声明自己实现某个接口,则必须实现该接口的所有方法
    • 接口也可以被继承
    • 不同类可以使用相同的接口
接口回调
  • 接口回调
    • image-20240507155931529
  • 接口作为参数
    • image-20240507155955774

内部类

  • Java支持在一个类里面声明另一个类,这样的类称为内部类,而包含内部类的类称为外嵌类。
  • 一个类把他的内部类看成自己的一个成员。
  • 内部类不可声明类变量和类方法
  • 在内部类中,其外嵌类的成员变量仍然有效。内部类也可以调用外嵌类中的方法
    • image-20240507163331507

匿名类

与类有关的匿名类
  • 此类体被认为是该类的一个子类去掉类声明后的类体

  • new + 类名XX 相当于new一个子类,同时继承或重写其父类XX,该子类没有名字

  • 匿名类一定是内部类

  • 匿名类的主要用途就是给方法需要的参数传值

    • 假设 f(B x) 是一个方法,该方法内部调用B类中的方法

      void f(B x){
      	//x调用B类中方法
      }
      

      此时就可以利用类B的匿名类,传参时重写父类B中的方法,使得 f() 调用重写的方法

      f (new B(){
      	//匿名类的类体,继承或重写B类方法
      }); //在传参的括号内重写
      

      举个例子

      image-20240507165832723

      匿名类中重写了 look()函数 需要调用的 Student类中的 speak()函数

与接口有关的匿名类
  • 此类体被认为是实现了XXX接口的类去掉声明后的类体

  • 也就是new + 接口名称()

    • new Computable(){
          //该类体内包含实现接口Computable()所需的全部方法
      }
      
  • 也是给方法传参时使用

    • image-20240507170933365

异常类

  • 利用try-catch语句来处理异常,把可能发生异常的语句放进try{},如果发生异常,终止try部分执行,转入执行catch{}部分

  • image-20240507172719482

  • 自定义异常类

    • 使用关键字throws声明如果程序抛出所要产生的异常情况,如果满足异常情况,该方法结束执行并抛出异常,否则该方法正常向下执行

      • 求解正数的平方根。自己定义一个异常类,当向该方法传递的参数是负数时,发生MyException异常

        class MyException extends Exception{  //自定义异常函数,类似try-catch 里的catch
            String message;
            MyException(int n){
                message = n + "不是正数";
            }
            public String getMessage(){
                return message;
            }
        }
        class A{
            public void f(int n) throws Myexception{ //该方法声明一个自定义异常MyException
                if (n < 0)
                {
                    MyException ex = new Myexception(n); //new异常类MyException的子类ex
                    throw(ex); //抛出异常ex,结束方法f的执行
                }
                //进行到这里证明没有抛异常
                double number = Math.sqrt(n);
                System.out.println(n + "的平方根:" + number);
            }
        }
        public class Example{
            public static void main(String args[]){
                A a = new A();
                try{ //将可能发生异常的语句放进try
                    a.f(28);
                    a.f(-8);
                }
                catch (MyException e){ System.out.println(e.getMessage());}
            }
        }
        

        image-20240507174423268

问答题

  • 子类重写继承的方法的规则是什么?

  • 方法重写时一定要保证方法的名字、类型、参数个数和类型同父类的某个方法完全相同,只有这样,子类继承的这个方法才被隐藏

  • 假设父类有个一个方法

    public double f(double x , double y){

    return x+y;

    }是否允许子类再声明如下方法

    public float f(double x,double y){

    return 23;

    }

    • 允许,该子类重写了该方法,就隐藏了父类的方法。但是如果子类重写的继承方法与父类该方法只有返回值不同,就会编译错误CE。
  • 什么类可以有抽象的方法?

  • abstract修饰的类。接口中也可以有abstract方法

  • 什么叫对象的上转型对象

  • 用子类的构造方法构造出来的对象,赋值给父类对象

  • 什么叫接口回调

  • 用实现接口的类创建的对象,赋值给该接口声明的接口变量。

  • 编写一个类,该类有如下方法

    public int f(int a,int b){ }//要求返回a和b的最大公约数

    再编写一个该类的子类,要求子类重写方法f()

    而且重写的方法将返回两个整数的最小公倍数。

    要求:在重写的方法的方法体中首先调用被隐藏的方法返回a和b 的最大公约数m,然后将(a*b)/m 返回(也就是最小公倍数);

    在应用程序的主类中分别使用父类和子类创建对象,并分别调用方法f()计算两个正整数的最大公约数和最小公倍数。

    不符合要求的做法 由于求最大公约数里的递归函数导致super.f(a, b)出现异常?

    import java.util.Scanner;
    
    class A{
        public int f1(int m, int n){ //计算m和n的最小公约数
            return n == 0 ? m : f1(n, m % n); //由于这里函数有递归,导致子类重写该函数时,发生错误,改了函数名就行
        }
    }
    class B extends A{
        public int f(int m, int n){ //子类重写方法f
            int division = super.f1(m, n); //调用被隐藏的方法返回a和b的最大公约数division
            return (m * n) / division; //返回最小公倍数 就是两数相乘除以最大公约数
        }
    }
    
    public class Main{
        public static void main(String[] args){
            A a = new A();
            B b = new B();
            Scanner sc = new Scanner(System.in);
            int m = sc.nextInt();
            int n = sc.nextInt();
            System.out.println(a.f1(m, n));
            System.out.println(b.f(m, n));
        }
    }
    

    改成这样就行

    package org.example;
    
    import java.util.Scanner;
    
    class A{
        public int f(int m, int n){ //计算m和n的最小公约数
            while(n != 0)
            {
                //c 一定小于 b
                int c = m % n;
                //小括号左边放除数,右边放约数
                m = n;
                n = c;
            }
            return m;
        }
    }
    class B extends A{
        public int f(int m, int n){ //子类重写方法f
            int division = super.f(m, n); //调用被隐藏的方法返回a和b的最大公约数division
            return (m * n) / division; //返回最小公倍数 就是两数相乘除以最大公约数
        }
    }
    
    public class Main{
        public static void main(String[] args)throws Exception{
            A a = new A();
            B b = new B();
            Scanner sc = new Scanner(System.in);
            int m = sc.nextInt();
            int n = sc.nextInt();
            System.out.println(a.f(m, n));
            System.out.println(b.f(m, n));
        }
    }
    
  • 首先编写一个抽象的类,要求该抽象的类有3个抽象的方法:

    public abstract void f(int x);

    public abstract void f(int x, int y);

    public abstract double h(double x);

    然后分别给出这个抽象类的3个子类。

    要求:在应用程序的主类中使用这些子类创建对象,再让它们上转型对象调用方法f()、g()和h();

    • abstract class A{
          public abstract void f(int x);
      	public abstract void g(int x, int y);
      	public abstract double h(double x);
      }
      
      //抽象类的三个子类
      class A1 extends A{
          public void f(int x){
              System.out.println(x);
          }
      	public void g(int x, int y){
              int z = x + y;
              System.out.println(z);
          }
      	public double h(double x){
              return x * x;
          }
      }
      class A2 extends A{
          public void f(int x){
              System.out.println("Hello" + x);
          }
      	public void g(int x, int y){
              int z = x - y;
              System.out.println(z);
          }
      	public double h(double x){
              return Math.sqrt(x);
          }
      }
      class A3 extends A{
          public void f(int x){
              System.out.println("你好:" + x);
          }
      	public void g(int x, int y){
              double z = (double)x / y;
              System.out.println(z);
          }
      	public double h(double x){
              return 1 / x;
          }
      }
      public class Main{
          public static void main(String[] args){
              //子类对象的上转型对象
              A a = new A1();
              a.f(10);
              a.g(12, 20);
              System.out.println(a.h(100));
              
              a = new A2();
              a.f(10);
              a.g(12, 20);
              System.out.println(a.h(100));
              
              a = new A3();
              a.f(10);
              a.g(12, 20);
              System.out.println(a.h(100));
          }
      }
      
  • 首先编写一个类,要求该类实现一个接口,该接口有3个抽象的方法:

    public abstract void f(int x);

    public abstract void f(int x, int y);

    public abstract double h(double x);

    要求:在应用程序的主类中使用该类创建对象,并使用接口回调来调用方法f()、g()和h();

    • interface A{
          public abstract void f(int x);
      	public abstract void g(int x, int y);
      	public abstract double h(double x);
      }
      
      //抽象类的三个子类
      class A1 implements A{
          public void f(int x){
              System.out.println(x);
          }
      	public void g(int x, int y){
              int z = x + y;
              System.out.println(z);
          }
      	public double h(double x){
              return x * x;
          }
      }
      class A2 implements A{
          public void f(int x){
              System.out.println("Hello" + x);
          }
      	public void g(int x, int y){
              int z = x - y;
              System.out.println(z);
          }
      	public double h(double x){
              return Math.sqrt(x);
          }
      }
      class A3 implements A{
          public void f(int x){
              System.out.println("你好:" + x);
          }
      	public void g(int x, int y){
              double z = (double)x / y;
              System.out.println(z);
          }
      	public double h(double x){
              return 1 / x;
          }
      }
      public class Main{
          public static void main(String[] args){
              //接口回调
              A a = new A1();
              a.f(10);
              a.g(12, 20);
              System.out.println(a.h(100));
              
              a = new A2();
              a.f(10);
              a.g(12, 20);
              System.out.println(a.h(100));
              
              a = new A3();
              a.f(10);
              a.g(12, 20);
              System.out.println(a.h(100));
          }
      }
      

第六章

字符串转整型

调用java.lang.Integer下的parseInt函数

int x;
String s = "6542";
x = Integer.parseInt(s);

String和StringBuffer区别

  • StringBuffer类能创建可修改的字符串序列,类似C++里的vector?

    StringBuffer s = new StringBuffer("I love you");
    s.append("ok"); //利用append()追加字符串序列
    
  • String类创建的字符串对象存储空间是不可修改的,但StringBuffer类创建后可以修改字符串序列,实体内存空间可以改变,便于存放可变字符串

Scanner类三种用法

  • 读取输入

  • 使用默认分隔标记解析字符串

    • 以空格作为标记

      String NBA = "I love this game";
      Scanner sc = Scanner(NBA); //放入字符串NBA
      while(sc.hasNext()){
      	String str = sc.next(); //以空格为标记分割字符串
      }
      

      image-20240507203651144

  • 使用正则表达式作为分隔标记解析字符串

问答题

  • 对于StringBuffer字符串

    StringBuffer str = new StringBuffer("abcdefg");

    ​ str = str.delete(2,4);

    写出 System.out.println(str) 的结果

    • abefg

      不会删除e,e的坐标为4,delete(2, 4)里的4为需要删除的下一个字符的下标

  • 编写一个应用程序,用户从键盘输入一行含有数字的字符串,程序输出该字符串中全部数字字符。

    • 如果单词不是数字型单词,调用nextInt() 或 nextDouble() 方法将发生InputMismatchException 异常

    • image-20240507204655929

第七章

问答题

  • 怎样实例化一个calendar对象?

    • Calendar类是一个抽象类,不能直接实例化。通过调用getInstance()方法获取一个Calendar对象的实例。

      import.util.Calendar;
      Calendar calendar = Calendar.getInstance();
      
  • LinkedList泛型是一种什么数据结构?

  • LinkedList是一种链表数据结构,它是Java中的一个泛型类

  • 编写一个程序,输出某年某月的日历页,通过main方法的参数将年和月传递到程序中

    • import java.util.Calendar;
      
      class CalendarDisplay{
       private int year;
       private int month;
       public CalendarDisplay(int year,int month){
        this.year=year;
        this.month=month-1;
       }
       
       //返回当前月份的总天数。
       public int getNumberOfDaysInMonth(int year,int month){
              int num=0;
              if(month == 1|| month == 3 || month == 5 || month == 7 || month == 8 || month == 10 || month == 12)
                      num = 31;
              else if(month == 4 || month == 6 || month == 9|| month == 11)
                      num = 30;
              else if(month == 2){
                      if(year%4==0&&year%100!=0||year%400==0)
                              num = 29;
                      else
                              num = 28;
              }
              return num;
          }
       
       public void display(){
          Calendar cal=Calendar.getInstance();
             cal.set(year, month, 1);
             int weekOf=cal.get(Calendar.DAY_OF_WEEK)-1;    
             month++;
             String a[]=new String[weekOf+getNumberOfDaysInMonth(year,month)];   
             for(int i=0;i<weekOf;i++){
              a[i]="";
             }
             for(int i=weekOf,n=1;i<weekOf+getNumberOfDaysInMonth(year,month);i++){
              a[i]=String.valueOf(n);
              n++;
             }     
             System.out.println("  这是"+year+"年"+month+"月的日历页!");
             System.out.printf("%10c%10c%10c%10c%9c%8c%10c/n",'日','一','二','三','四','五','六');
             for(int i=0;i<a.length;i++){
              if(i%7==0&&i!=0)
               System.out.println("/n");
              System.out.printf("%5s",a[i]);  
             }
       }
      }
      
      public class ch07_1 {
       public static void main(String[] args) {
            new CalendarDisplay(Integer.parseInt(args[0]),Integer.parseInt(args[1])).display();
       }
      
      }
      

第八章

线程的生命周期

  • 新建
  • 运行
  • 中断
  • 死亡

8-5

  • image-20240507211012965

    image-20240507211043756

8-8

  • image-20240507211119272

    image-20240507211201574

sleep类

  • sleep(int millsecond)

  • 线程的调度执行是按照其优先级的高低顺序进行的,当高级线程不完成时,轮不到低级线程,当高级线程需要低级线程做一些工作时,他需要让出处理器给低级线程,为了达到这个目的,在高级线程的run()方法中调用sleep()方法使自己放弃处理器资源,休眠一段时间。

  • 休眠时间长短由sleep()内参数决定,millsecond是以毫秒为单位的休眠时间

问答题

  • 线程和进程的关系

    • 线程是进程的一部分,一个进程可以包含多个线程
  • 线程由几种状态

    • 新建 运行 中断 死亡
  • 引起线程中断的原因

    • image-20240507212511037
  • 模仿例子8-2,编写三个线程,分别在控制台输出信息。

  • 模仿例子8-4编写三个线程,让它们共享更多的单元。

实验3.1

  • 创建类TimerAlarm,让它继承Thread并实现一个秒表的功能,不要使用内置的Timer类,先按照时:分:秒打印时间,然后换一行打印总的秒数。

    • import java.util.Scanner;
      
      public class TimerAlarm {
      	public static void main(String[] args) {
      		Timer t1 = new Timer();  //新建子线程
      		t1.start();   //启动线程
      	}
      }
      
      class Timer extends Thread{
      	Object lock = new Object();
      	int min=0,sec=0,hou=0;
      	int n;   //用于返回秒数
      	boolean pause = false;  //阻塞标志
      	
      	void pauseThread() {  //将阻塞信号开启
              this.pause = true;   
          }
      	
      	void show() {    //打印总秒数
      		System.out.println(hou+":"+""+min+":"+sec);
      		int n=(hou*3600+min*60+sec);  
      		System.out.print(" "+n+'\n');
      	}
      	
      	void OnPause() {  //阻塞方法
              synchronized (lock) {
                  try {
                      lock.wait();  //阻塞线程方法
                  } catch (InterruptedException e) {
                      e.printStackTrace();
                  }
              }
          }
      	
      	 public void run() {
               super.run();
               while (true) {
                   if (pause) {            
                       OnPause();
                   }
                   try { 
                  	     sec++;
                  	     show();	//每加一秒打印一次            	
      		         if(sec==60) {sec=0;min++;}   //60秒后,分钟加1,秒数清零
      		         if(min==60){min=0;sec=0;hou++;} //60分钟后,小时加1, 秒和分钟清零
                       Thread.sleep(1000);              
                   } catch (Exception e) {
                       e.printStackTrace();
                   }
               }
           }
       }
      
      

第九章

  • Java的I/O流库提供大量的流类(在包 java.io中),其中由四个重要的抽象类:InputStream(字节输入流),Reader(字符输入流),OutputStream(字节输出流),Writer(字符输出流)

问答题

  • FileInputStream流的read()方法与FileReader流的read()方法有和不同?

    • FileInputStream流从输入流中顺序读取单个字节的数据。该方法返回字节数据值(0--255之间的整数)到末尾返回-1
      FileReader流,输入流调用该方法从源中读取一个字符,该方法返回一个0---65535之间的一个整数(Unicode字符值)到末尾返回-1
  • 编写一个程序读取文本文件的内容

    • import java.io.BufferedReader;
      import java.io.FileReader;
      import java.io.IOException;
      
      public class ReadTextFile {
          public static void main(String[] args) {
              String fileName = "D:\\test.txt"; // 指定要读取的文件名
              try (BufferedReader br = new BufferedReader(new FileReader(fileName))) {
                  String line;
                  while ((line = br.readLine()) != null) { // 逐行读取文件内容
                      System.out.println(line); // 打印每行内容到控制台
                  }
              } catch (IOException e) {
                  e.printStackTrace(); //在命令行打印异常信息
              }
          }
      }
      

实验3.2

  • 使用输入输出流,将文件words.txt 文件内容读出,然后以倒序的方式重新保存在新的文件newwords.txt里面,并为每个单词编号。如果在保存的时候newwords文件已经存在,应该产生FileFundException,并将其捕获处理。

    • import java.io.BufferedReader;
      import java.io.BufferedWriter;
      import java.io.FileNotFoundException;
      import java.io.FileReader;
      import java.io.FileWriter;
      import java.io.IOException;
      import java.util.ArrayList;
      
      public class InOut {
      private static final String NUll = null;  
      //将null强制转换为String类,不抛出异常
      public static void main(String[] args) throws IOException {
                                  //throws是方法可能抛出异常的声明
          	    BufferedReader br = null;
      		BufferedWriter bw = null;
      		try {
      			br = new BufferedReader(new FileReader("words.txt"));
      			bw = new BufferedWriter(new FileWriter("newwords.txt")); 
      	        ArrayList<String> list = new ArrayList<>(); //创建动态数组对象
      	        String line;
      	        while((line = br.readLine()) != NUll){
      	            list.add(line);  //向集合列表中添加对象
      	        }
      	        int j=1;
      	        for(int i=list.size()-1 ;i>= 0 ;i--){
      	        	bw.write(j+".");    //写入每个单词的序号
      	            bw.write(list.get(i));     //将单词以倒序的方式写入文件
      	            bw.newLine();       //换行
      	            j++;
      	        }
      	        bw.flush();   //刷新缓冲流
      	        br.close();   //关闭文件
      	        bw.close();
      		} catch (FileNotFoundException e) {
      			System.out.println("找不到指定文件!");
      		}catch (IOException e) {
      			e.printStackTrace();    //在命令行打印异常信息
      		}
          }
      }
      
      

第十章

实验四

  • 编写一个对输入的英文单词按照字典排序的程序,当在一个文本域输入若干个英文字单词,单击字典排序按钮,另一个文本域 对输入的英文单词进行排序;当按清空按钮,另一个文本区域的内容同时清空。要求通过Swing组件完成本程序的编写。

    • import java.awt.event.ActionEvent;
      import java.awt.event.ActionListener;
      import java.util.StringTokenizer;
      import javax.swing.JButton;
      import javax.swing.JFrame;
      import javax.swing.JTextArea;
      
      public class MyFrame{
      	public static void main(String args[]) {
      		new MyFra();
      	}
      }
      class MyFra extends JFrame  //继承JFrame 类,实现构建一个窗口的功能和特性
      {
      	JButton buttonRight;   //右边的按钮
      	JTextArea textRight;   //右边的文本框
      	JButton buttonLeft;    //左边的按钮
      	JTextArea textLeft;   //左边的文本框
      	MyFra()    //构造函数
      	{
      		buttonLeft = new JButton("字典排序");
      		buttonRight = new JButton("清空");
      		textLeft = new JTextArea();
      		textRight = new JTextArea();
      		this.setLayout(null);  //设置为空布局,准确地定位组件在容器的位置和大小
      		this.add(textLeft); 
      		this.setBounds(200, 200, 600, 400);  //设置窗口在屏幕上的位置和大小
      		textLeft.setBounds(50, 20, 100, 200);  //设置左边文本框的位置和大小
      		textLeft.setVisible(true);     //窗口可见
      		this.add(textRight);
      		textRight.setBounds(200, 20, 100, 200);  //设置右边文本框的位置和大小
      		textRight.setVisible(true);
      		textRight.setEditable(false);   //右边文本框不可编辑
      		this.add(buttonLeft);
      		buttonLeft.setBounds(50, 250, 100, 20);  //设置左边按钮的位置和大小
      		buttonLeft.setVisible(true);
      		buttonLeft.addActionListener(new ActionListener()   //获得监视器
      		{
      			public void actionPerformed(ActionEvent e)  //此方法对事件做出处理
      			{
      				sort();      //按左边按钮进行排序
      			}
      		});
      		this.add(buttonRight);
      		buttonRight.setBounds(200, 250, 100, 20);    //设置右边按钮的位置和大小
      		buttonRight.setVisible(true);
      		buttonRight.addActionListener(new ActionListener()  //获得监视器
      		{
      			public void actionPerformed(ActionEvent e) 
      			{
      				clear();   //按右边按钮执行清空操作
      			}
      		});
      		setVisible(true);
      		validate();   //确保组件具有有效的布局
      	}
      	private void clear()    //清空
      	{
      		textLeft.setText("");
      		textRight.setText("");
      	}
      	private void sort()    //排序
      	{
      		String[] words = getWords();   //获取单词
      		dictionary(words);     //调用dictionary函数将其排序
      		for (int i = 0; i < words.length; i++)
      		{
      			if (words[i].equals(null)) 
      			{
      				return;
      			}
      			System.out.println(words[i]);
      			textRight.append(words[i] + "\n"); //在右边文本框输出排好的单词
      		}
      	}
      	private void dictionary(String[] words)//冒泡法将数组中的字符串按字典序排序
      	{
      		for (int i = 0; i < words.length; i++) 
      		{
      			if (words[i].equals(null)) 
      			{
      				return;
      			}
      			for (int j = i + 1; j < words.length; j++)
      			{
      				if (words[i].compareTo(words[j]) > 0)
      				{
      					String temp = words[i];
      					words[i] = words[j];
      					words[j] = temp;
      				}
      			}
      		}
      	}
      	private String[] getWords()  
      	{
      		String left = textLeft.getText();  //输入到左边文本框
      		StringTokenizer token = new StringTokenizer(left, "\n"); 
       //使用StringTokenizer类,其中分割标记为'/n'
      		int count = token.countTokens();    //得到计数变量的值
      		String[] words = new String[count];
      		int i = 0;
      		while (token.hasMoreTokens())   //控制循环,获取目标字符串
      		{
      			String current = token.nextToken();
      			if (current.matches("\\p{Alpha}+"))  //使用正则表达式匹配字母
      			{
      				words[i] = current;
      				i++;
      			}
      		}
      		String[] result = new String[i];
      		for (int j = 0; j < i; j++) 
      		{
      			result[j] = words[j];
      		}
      		return result;    //将过滤掉的字符串数组返回
      	}
      }
      
      
  • 用 JFrame 创建两个窗口

    • import javax.swing.*;
      public class E {
          public static void main(String[] args){
              JFrame frame1 = new JFrame("第一个窗口");
              JFrame frame1 = new JFrame("第二个窗口");
              
              //设置窗口在屏幕上的位置及大小
              frame1.setBounds(60, 100, 188, 108);
              frame2.setBounds(260, 100, 188, 108);
              frame1.setVisible(true);
              frame1.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE); //释放当前窗口
              frame2.setVisible(true);
              frame2.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); //退出程序
          }
      }
      
posted @ 2024-05-08 15:09  MsEEi  阅读(13)  评论(0)    收藏  举报