code4sk/java/JavaExam/java期末试卷练习
2023-10-18 16:17:32 +08:00

649 lines
23 KiB
Text
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

//2023.06.28 Java期末复习课程
1.写出程序运行结果
class A{
public A(){
System.out.println("Hello!");
}
public A(String s){
this();
System.out.println("My name is"+s);
}
}
class B extends A{
public static void main(String[] args){
B b=new B("Amy");
}
public B(){
System.out.println("I am Amy.");
}
public B(String s){
super(s);
System.out.println("How are you!");
}
}
程序运行结果如下:
Hello!
My name is Amy
How are you!
首先程序从B类的主方法开始执行。在主方法中创建了一个B类的对象b并调用了带有一个String类型参数的构造方法参数为"Amy"。由于B类继承自A类因此构造B类对象时会先调用父类A的构造方法。
在A类的构造方法中首先打印输出"Hello!"。接着B类的构造方法调用了父类A的带有一个String类型参数的构造方法这里传入了"Amy"作为参数。在A类的带有一个String类型参数的构造方法中先调用了A类的无参构造方法this()),所以又会打印输出"Hello!"。然后,打印输出"My name is Amy"。
接着回到B类的构造方法继续执行后续的代码。在B类的构造方法中打印输出"I am Amy."。最后,打印输出"How are you!"。
因此,程序运行结果为:
Hello!
My name is Amy
How are you!
*******************************************************************************************************
2.下列try catch语句块中的第二个语句S1将引起一个异常试回答下列问题。
try{
S1;
S2;
}catch(ExceptionType1 e){
}catch(ExceptionType2 e){
}finally{
S3;
}
S4
(1)S2会执行吗?
(2)如果异常未被捕获S3会被执行吗?S4会被执行吗?
(3)如果catch子句捕获了异常S3会被执行吗?S4会被执行吗?
(1) S2不会执行。由于S1引发了异常程序将会跳转到catch子句而不会继续执行后面的语句。
(2) 如果异常未被捕获S3会被执行。无论是否发生异常finally块中的代码都会被执行。但是S4不会被执行因为异常发生后程序会跳出try-catch-finally语句块。
(3) 如果catch子句捕获了异常S3会被执行。无论是否发生异常finally块中的代码都会被执行。S4也会被执行因为异常已经被处理并且程序会继续执行后面的语句。
如果异常未被捕获程序会跳转到catch子句之前的位置不会执行后面的语句但finally块中的代码仍会被执行。
如果catch子句捕获了异常程序会继续执行catch子句之后的语句包括finally块中的代码。
*******************************************************************************************************
3.下列代码简单模拟了多个窗口购买火车票会出现下图问题请问代码如何修改提示synchronized
class BuyTicket implements Runnable{
int ticketnum=10;//共有十张宁波到北京的火车票
public void run{
for(int i=1;i<=20;i++){//每个窗口有20人在排队买票
if(ticketnum>0)//票数大于0买票
System.out.println(Thread.currentThread().getName()+"买到从宁波到北京的第"+ticketnum--+"张车票")
}
}
}
public class Test{
public static void main(String[] args){
BuyTicket t=new BuyTicket();
Thread t1=new Thread(t,"1号窗口");
t1.start();
Thread t2=new Thread(t,"2号窗口");
t2.start();
Thread t3=new Thread(t,"3号窗口");
t3.start();
}
}
问题出在多个线程同时访问ticketnum变量时可能会出现竞争条件导致数据不一致。为了解决这个问题可以使用synchronized关键字来保证多个线程访问ticketnum变量时的同步性。
修改后的代码如下:
class BuyTicket implements Runnable{
private int ticketnum=10;//共有十张宁波到北京的火车票
public synchronized void run(){
for(int i=1;i<=20;i++){//每个窗口有20人在排队买票
if(ticketnum>0){//票数大于0买票
System.out.println(Thread.currentThread().getName()+"买到从宁波到北京的第"+ticketnum--+"张车票");
}
}
}
}
public class Test{
public static void main(String[] args){
BuyTicket t=new BuyTicket();
Thread t1=new Thread(t,"1号窗口");
t1.start();
Thread t2=new Thread(t,"2号窗口");
t2.start();
Thread t3=new Thread(t,"3号窗口");
t3.start();
}
}
在BuyTicket类的run方法上加上synchronized关键字这样就可以保证在多线程环境下只有一个线程能够访问run方法从而避免了多个线程同时修改ticketnum的问题。这样可以保证每个窗口买票时的操作是互斥的不会出现问题。
在BuyTicket类的run方法上添加了synchronized关键字这样每个窗口在执行run方法时都会获得对象锁保证了同一时间只有一个窗口在买票。这样就避免了多个窗口同时买同一张票的问题。
*******************************************************************************************************
4.阅读以下代码片段,回答问题
import java.awt.event.*;
import javax.swing.*;
import java.awt.*;
class EventTest extends JFrame implements ActionListener/*a*/{
JButton btn1,btn2;Container ctpn;
EventTest(){
ctpn=this.getContentPane();//b
btn1=new JButton("Blue");
btn2=new JButton("Red");
btn1.addActionListener(this);//c
btn2.addActionListener(this);
this.setTitle("Action Event");setSize(200,150);
this.setLayout(new FlowLayout(FlowLayout.CENTER)); //d
this.ctpn.add(btn1);ctpn.add(btn2);
this.setVisible(true);
}
public void actionPerformed(ActionEvent e){
JButton btn=(JButton)e.getSource();//e
if(btn==btn1) ctpn.setBackground(Color.blue);
if(btn==btn2)
ctpn.setBackground(Color.red);
}
public static void main(String args[]){
EventTest frm=new EventTest();
}
}
(1)在"//"后添加注释
(2)画出程序的运行效果,并说程序完成的功能
(1) 在"//"后添加注释:
import java.awt.event.*; // 导入事件相关的包
import javax.swing.*; // 导入Swing相关的包
import java.awt.*; // 导入AWT相关的包
class EventTest extends JFrame implements ActionListener{ //a 继承JFrame类并实现ActionListener接口,ActionListener接口是一个事件监听器接口用于处理按钮点击事件
JButton btn1,btn2; // 创建两个按钮对象
Container ctpn; // 创建一个容器对象
EventTest(){
ctpn=this.getContentPane();//b getContentPane()方法用于获取容器的内容面板。
btn1=new JButton("Blue"); // 创建名为"Blue"的按钮
btn2=new JButton("Red"); // 创建名为"Red"的按钮
btn1.addActionListener(this); //c 为按钮添加事件监听器,addActionListener(this)方法将当前类实例作为按钮的事件监听器
btn2.addActionListener(this); //c 为按钮添加事件监听器
this.setTitle("Action Event"); // 设置窗口标题为"Action Event"
setSize(200,150); // 设置窗口大小为200x150像素
this.setLayout(new FlowLayout(FlowLayout.CENTER)); //d 设置布局为居中对齐的流式布局
this.ctpn.add(btn1); // 将"Blue"按钮添加到容器中
ctpn.add(btn2); // 将"Red"按钮添加到容器中
this.setVisible(true); // 设置窗口可见
}
public void actionPerformed(ActionEvent e){
JButton btn=(JButton)e.getSource(); //e 获取触发事件的按钮对象
if(btn==btn1) ctpn.setBackground(Color.blue); // 如果是"Blue"按钮触发的事件,将容器背景设置为蓝色
if(btn==btn2) ctpn.setBackground(Color.red); // 如果是"Red"按钮触发的事件,将容器背景设置为红色
}
public static void main(String args[]){
EventTest frm=new EventTest(); // 创建EventTest对象
}
}
(2) 程序的运行效果:
程序创建了一个窗口,窗口标题为"Action Event"大小为200x150像素。窗口中有两个按钮一个是"Blue"按钮,另一个是"Red"按钮。当点击"Blue"按钮时,窗口的背景颜色会变为蓝色;当点击"Red"按钮时,窗口的背景颜色会变为红色。
程序完成的功能是该程序演示了如何使用Java的事件处理机制通过按钮的事件监听器实现了当点击不同的按钮时改变窗口的背景颜色。
5.下列代码完成了邮箱系统的登陆功能,请在注释位置编写相应代码写出运行结果。相关信息和Java帮助如下:
User表id username password
1 zhangsan 123
2 lisi 234
数据库操作类已实现,大纲视图如下:
JDBCUtils
url:String
user:String
password:String
driver:String
{...}
getConnection():Connection
close(Statement,Connection):void
close(ResultSet,Statement,Connection):void
接口Connection下的方法
Statement createStatement() 创建一个Statement对象来将SQL语句发送到数据库
接口Statement下的方法
ResultSet executeQuery(String sql) 执行给定的SQL语句该语句返回单个ResultSet对象。
接口ResultSet下的方法
boolean next() 将光标从当前位置先前移一行。
import java.sql.*;
public class LoginTest{
public static void main(String[] args){
String username="lisi";
String pasasword="123";
boolean flag=new LoginTest().login(username,password);
if(flag) System.out.println("登陆成功");
else System.out.println("用户名或密码错误");
}
public boolean login(String username,String password){
if(username==null||password==null){
return false;
}
Connection conn=null;PreparedStatement pstmt=null;ResultSet rs=null;
try{
conn=JDBCUtils.getConnection();
//添加数据库操作代码
}catch(SQLException e){
e.printStackTrace();
}finally{
JDBCUtils.close(rs,pstmt,conn);
}
return false;
}
}
answer:
pstmt = conn.prepareStatement("SELECT * FROM User WHERE username = ? AND password = ?");
pstmt.setString(1, username);
pstmt.setString(2, password);
rs = pstmt.executeQuery();
if(rs.next()){
return true; // 用户名和密码匹配,登录成功
}
import java.sql.*;
public class LoginTest{
public static void main(String[] args){
String username="lisi";
String password="123";
boolean flag=new LoginTest().login(username,password);
if(flag) System.out.println("登陆成功");
else System.out.println("用户名或密码错误");
}
public boolean login(String username,String password){
if(username==null||password==null){
return false;
}
Connection conn=null;PreparedStatement pstmt=null;ResultSet rs=null;
try{
conn=JDBCUtils.getConnection();
pstmt = conn.prepareStatement("SELECT * FROM User WHERE username = ? AND password = ?");
pstmt.setString(1, username);
pstmt.setString(2, password);
rs = pstmt.executeQuery();
if(rs.next()){
return true;
}
}catch(SQLException e){
e.printStackTrace();
}finally{
JDBCUtils.close(rs,pstmt,conn);
}
return false;
}
}
运行结果:
用户名或密码错误
程序通过调用login方法进行登录验证传入用户名和密码参数。在login方法中首先判断用户名和密码是否为空如果为空则直接返回false。然后获取数据库连接通过PreparedStatement对象执行SQL语句查询用户表使用占位符设置用户名和密码参数。如果查询结果存在则返回true表示登录成功否则返回false表示用户名或密码错误。
在main方法中调用login方法并根据返回结果输出相应的提示信息。在本例中用户名为"lisi",密码为"123",所以输出结果为"用户名或密码错误"。
6.下面有两个Java源文件(Lute.java和Music.java),阅读程序,回答问题。
a:Lute.java
package mypack;
interface Instrument{//乐器
int NUM=5;
void play();
String what();
void adjust();
}
class Wind implements Instrument{//管乐器
public void play(){
System.out.println("Wind.play()");
}
public String what() {return "Wind";}
public void adjust() {}
}
class Stringed{//有弦乐器
int StringNum;
Stringed(int num){
this.StringNum=num;
}
}
public class Lute extends Stringed implements Instruments{//古琵琶
public Lute(int num){
super(num);
}
public void play(){
System.out.println("lute.play()");
}
public String what() {return "lute"};
public void adjust() {}
}
b.Music.java
import mypack.*
public class Music{
public static void main(String[] args){
Lute test=new Lute(6);
test.play();
}
}
(1)以上代码分别有哪些接口、类,在哪些包中,有公共类吗?
(2)类Wind中的adjust()方法是抽象方法吗?能省略吗?为什么?
(3)类Lute和类Stringed是什么关系Lute类中有成员变量吗
(4)类Lute中的方法是public修饰符能省略吗为什么
(5)请写出程序的运行结果。
(1)以上代码接口有"Instrument",类有'Wind','Stringed','Lute','Music',都在'mypack'包中。
在'Lute.java'中有一个公共类'Lute'。在'Music.java'文件中有一个公共类'Music'。
(2)类Wind中的adjust()方法不是抽象方法。它不能省略。如果省略adjust()方法的实现则Wind类必须声明为抽象类。
(3)类Lute是类Stringed的子类。它们之间是继承关系。Lute类中有一个名为StringNum的成员变量。
(4) 类Lute中的方法的修饰符是public可以省略。这是因为Lute类实现了Instrument接口在接口中的所有方法都是公共的因此在实现接口方法时默认的访问修饰符是public。
(5) 程序的运行结果是lute.play()
二.程序设计题
1.“具有报警功能的移门”针对上述描述请用类、接口等面向对象知识进行设计实现方法中不必写出具体实现代码用System.out.println()。
根据描述,我们可以设计以下类和接口来实现具有报警功能的移门:
1. 接口Alarm
- 方法void alarm(),用于触发报警功能。
2. 类Door
- 属性isOpen表示门的状态true表示门开着false表示门关着
- 方法void open(),用于打开门
- 方法void close(),用于关闭门
- 方法void alarm()实现Alarm接口中的方法用于触发报警功能
- 方法void move(),用于移动门的位置
- 方法void displayStatus(),用于显示门的当前状态
设计实现如下:
interface Alarm {
void alarm();
}
class Door implements Alarm {
private boolean isOpen;
public void open() {
isOpen = true;
System.out.println("门已打开");
}
public void close() {
isOpen = false;
System.out.println("门已关闭");
}
public void alarm() {
System.out.println("门正在报警");
}
public void move() {
System.out.println("门正在移动");
}
public void displayStatus() {
System.out.println("门的状态:" + (isOpen ? "开着" : "关着"));
}
}
这样设计的类和接口可以实现具有报警功能的移门。Door类实现了Alarm接口并实现了alarm()方法用于触发报警功能。同时Door类还具有打开门、关闭门、移动门、显示门状态的功能。
2.数据可视化在统计报表有重要应用,柱状图以及折线图等图形是以不同视角展示数据。假设对于同一份二维数据,系统要求根据不同情景,展示不同图形(柱形图或折线图),且数据变化,图形自动变化(刷新),而且,需要预留接口,以方便需求升级,如同一份数据还支持饼图。为了满足以上需求,请设计类系,并写一个测试类,进行模拟。具体要求:
(a) 设计一个数据类,且有一份订阅者列表,可具备对订阅者(图形)列表的管理功能(删除与增加),当数据变化时,自动触发订阅者更新图形。
(b) 设计一个图形的抽象类,具备根据数据绘制图形的功能,并具备订阅数据和取消订阅的功能。
(c) 写一个测试类,模拟上述过程。
备注方法中不必写出具体实现代码用System.out.println()说明即可。
根据需求,我们可以设计以下类来满足要求:
1. 数据类Data
- 属性subscribers订阅者列表
- 方法addSubscriber(Subscriber subscriber),用于添加订阅者
- 方法removeSubscriber(Subscriber subscriber),用于移除订阅者
- 方法updateData(),用于更新数据并通知订阅者
2. 抽象类Graph
- 属性data数据对象
- 方法subscribe(),用于订阅数据
- 方法unsubscribe(),用于取消订阅数据
- 抽象方法draw(),用于根据数据绘制图形
3. 具体图形类BarGraph柱状图和LineGraph折线图
- 方法draw()实现Graph抽象类中的draw()方法,根据数据绘制柱状图或折线图
设计实现如下:
import java.util.ArrayList;
import java.util.List;
// 数据类
class Data {
private List subscribers;
public Data() {
subscribers = new ArrayList<>();
}
public void addSubscriber(Graph subscriber) {
subscribers.add(subscriber);
}
public void removeSubscriber(Graph subscriber) {
subscribers.remove(subscriber);
}
public void updateData() {
// 更新数据
System.out.println("数据更新");
// 通知订阅者更新图形
for (Graph subscriber : subscribers) {
subscriber.draw();
}
}
}
// 抽象图形类
abstract class Graph {
protected Data data;
public Graph(Data data) {
this.data = data;
}
public void subscribe() {
data.addSubscriber(this);
}
public void unsubscribe() {
data.removeSubscriber(this);
}
public abstract void draw();
}
// 具体图形类:柱状图
class BarGraph extends Graph {
public BarGraph(Data data) {
super(data);
}
public void draw() {
System.out.println("绘制柱状图");
}
}
// 具体图形类:折线图
class LineGraph extends Graph {
public LineGraph(Data data) {
super(data);
}
public void draw() {
System.out.println("绘制折线图");
}
}
// 测试类
public class Test {
public static void main(String[] args) {
// 创建数据对象
Data data = new Data();
// 创建柱状图和折线图
Graph barGraph = new BarGraph(data);
Graph lineGraph = new LineGraph(data);
// 订阅数据
barGraph.subscribe();
lineGraph.subscribe();
// 更新数据,图形自动变化
data.updateData();
// 取消订阅折线图
lineGraph.unsubscribe();
// 更新数据,只有柱状图会变化
data.updateData();
}
}
根据需求设计了数据类Data、抽象图形类Graph以及具体图形类BarGraph和LineGraph。测试类Test中模拟了订阅数据、更新数据以及取消订阅的过程。
测试类中先创建了数据对象Data然后创建了柱状图BarGraph和折线图LineGraph。接着订阅了数据然后更新数据可以看到柱状图和折线图都会自动绘制图
形。最后取消了对折线图的订阅,再次更新数据时,只有柱状图会变化。
3.当前,在我国,不同的企业类型有不同的税收计算方法,假设有高新企业、外资企业、普通企业。现有税收系统,可计算每一类企业的收税,也可自动计算某个地区(如鄞州区)的税收,一般地,某个地区的企业都有不同类型的企业存在。为了满足以上需求,请设计类系,并写一个测试类,进行模拟。具体要求:
(a) 设计一抽象类:企业,具备计算税收的功能。
(b) 高新企业、外资企业、普通企业应该是企业的子类,都具有计算税收的功能。
(c) 设计一个地区类,它是由不同类型的企业构成,具备计算地区税收的功能。
(d) 写一个测试类,进行模拟。
备注方法中不必写出具体实现代码用System.out.println(),或者直接返回一个值进行说明即可。提示:抽象类、方法重写、泛型等的应用。
根据需求,我们可以设计以下类来满足要求:
1. 抽象类Enterprise企业
- 方法calculateTax(),用于计算税收
2. 子类HighTechEnterprise高新企业、ForeignEnterprise外资企业、NormalEnterprise普通企业
- 方法calculateTax(),重写父类的计算税收方法
3. 类Region地区
- 属性enterprises不同类型的企业列表
- 方法addEnterprise(Enterprise enterprise),用于添加企业
- 方法removeEnterprise(Enterprise enterprise),用于移除企业
- 方法calculateRegionTax(),用于计算地区税收
设计实现如下:
abstract class Enterprise {
public abstract double calculateTax();
}
class HighTechEnterprise extends Enterprise {
public double calculateTax() {
System.out.println("计算高新企业的税收");
return 0.0;
}
}
class ForeignEnterprise extends Enterprise {
public double calculateTax() {
System.out.println("计算外资企业的税收");
return 0.0;
}
}
class NormalEnterprise extends Enterprise {
public double calculateTax() {
System.out.println("计算普通企业的税收");
return 0.0;
}
}
class Region {
private List enterprises;
public Region() {
enterprises = new ArrayList<>();
}
public void addEnterprise(Enterprise enterprise) {
enterprises.add(enterprise);
}
public void removeEnterprise(Enterprise enterprise) {
enterprises.remove(enterprise);
}
public double calculateRegionTax() {
double regionTax = 0.0;
for (Enterprise enterprise : enterprises) {
regionTax += enterprise.calculateTax();
}
return regionTax;
}
}
public class Test {
public static void main(String[] args) {
// 创建地区对象
Region region = new Region();
// 添加不同类型的企业
region.addEnterprise(new HighTechEnterprise());
region.addEnterprise(new ForeignEnterprise());
region.addEnterprise(new NormalEnterprise());
// 计算地区税收
double regionTax = region.calculateRegionTax();
System.out.println("地区税收:" + regionTax);
}
}
根据需求设计了抽象类Enterprise、子类HighTechEnterprise、ForeignEnterprise和NormalEnterprise以及类Region。测试类Test中模拟了创建地区对象、添加不同类型的企业、计算地区税收的过程。
测试类中先创建了地区对象Region然后添加了高新企业HighTechEnterprise、外资企业ForeignEnterprise和普通企业NormalEnterprise。接着计算地区税收可以看到会调用各个企业子类的计算税收方法并计算出地区的总税收。最后将地区税收输出。