Java期末考试复习题

第一题

题目描述

C语⾔标准库函数int atoi (const char *)和long int atol ( const char *),可以分别将给定的字符串转 换为整数(int)和⻓整数(long)。具体转换规则如下:丢弃前⾯的空⽩字符(空格、水平以及垂 直制表、换页、回车、换行,其相应的ASCII码值附后),直到第⼀个非空白字符为止;从该字符开 始,接收可选的+或-号,后跟任意的⼗进制数字字符并将其解释为数字值;字符串在构成整数的数 字字符之后可以包含额外的其它字符,⼀旦遇到这样的字符,转换⽴即停⽌;如果字符串的第⼀个
非空⽩字符并不是⼀个有效的数字字符,或者它为空或仅仅包含空⽩字符,那么不会执⾏转换,仅仅返回0。以下是对外提供这两个功能的NumUtil类,请根据该转换规则以及中的注释:(1)如果类 或有关⽅法的声明中存在错误,说明如何修改。main()方法体中,除了编号部分,不允许被修改。
(2)完成相关⽅法,要求不得使⽤标准Java⾃身的有关解析数值的类及其⽅法;(3)在main()⽅法中,根据下表中所给的测试⽤例执⾏单元测试(并⾮实际产品开发中的测试⽅式)。

java代码实现


public class NumUtil {
	//判断是否是空字符
	static private boolean isWhitespace(char c) {
		/*(1)*/
		switch(c) {
			case ' ':
			case '\t':
			case '\f':
			case '\r':
			case '\n':
			case '\u000b':
				return true;
			default:
				return false;
		}
	}
	//找到第一个非空字符的位置
	static private int skipWhitespace(String source) {
		//(2)
		int i = 0;
		while(i < source.length()) {
			if(isWhitespace(source.charAt(i)))
				i++;
			else
				break;
		}
		return i;
	}


	//字符串转化成长整数
	public static long atol(String source) {
		int sign = 1, i;	// sign of the result long integer, i current position in source 
		long res = 0;	// the final result long integer
		// skip the whitespaces (3)
		i = skipWhitespace(source);
		if(i == source.length()) return res;//这里应该判断一下非空字符下标是否越界
		// process the sign symbol (4)
		switch(source.charAt(i)) {
			case '+':
				i++;
				break;
			case '-':
				sign = -1;
				i++;
				break;
			default:
				break;
		}
		// process any digit characters 
		//(5)
		for(; i < source.length(); i++) {
			char c = source.charAt(i);
			if(c >= '0' && c <= '9')
				res = 10 * res + c - '0';
			else
				break;
		}
		// return the converted result long integer return (6)
		return res*sign;
	}
	
	//字符串转整数,直接将long强值转化即可
	public static int atoi(String source) {
		//(7)
		return (int)atol(source);
	}
	
	
	/**
	*	Determine if the given test had passed and output the  result
	*	according to the following format:
	*	<pre>
	*	Test case: n -> passed|failed
	*	where n is the number of the test case.
	*	</pre>
	*	@param test the number of the test case.
	*	@param factual the converted integer.
	*	@param expected the expected integer.
	*/
	//根据上面注释给出的格式输出测试结果
	public static void check(int test, int factual, int expected) { 
		//(8)
		if(factual == expected) {
			System.out.println("Test case: "+test+ " -> passed");
		}
		else {
			System.out.println("Test case: "+test+ " -> failed");
		}
	}
	// Just for test!
	public static void main(String[] args) {
		// test case 1 
		//main函数中不能直接调用非静态函数,应该创建对象或者转成静态函数
		String source = "";
		int res = atoi(source); 
		check(1, res, 0);
		// test case 2 
		//也就是一个测试示例
		source = " \t\f\r\n\u000b12345a8";//(9)
		res = atoi(source); 
		check(2, res, 12345);
		// test case 3

		// test case 4
		
		// test case 5
	
	}
}

在这里插入图片描述

第二题

题目描述

在Web应⽤程序中,为了提⾼系统的响应性,可以将⽤户请求的结果缓存在内存中。当⽤户后续请求相同的资源时,不必从数据存储中提取,⽽可以直接从内存中提供;当某个⽤户对相同的资源 进⾏更新时,除了更新数据存储,还应该更新缓存,但统⼀资源标识符(URI-Uniform ResourceIdentifier)不能更改;当请求删除某个资源被时,除了从数据存储中将其删除之外,如果该资源已
经被缓存,还应将其从缓存中删除;为了降低系统内存的消耗,每隔⼀定的时间,应该清除缓存中 超过⼀定期限的项⽬。缓存的项⽬中包括请求的URI(字符串形式)、应答体(字符串形式)以及进⼊缓存的时间(UNIX纪元即⾃从1970年1⽉1⽇0时0分0秒以来的毫秒数)。为了简单起⻅,不考虑 多服务器的分布式缓存⽽仅仅考虑单台服务器,但需要考虑多线程同步问题。以下表示HTTP应答缓 存的类HttpCache在整个JVM中只能有⼀个实例,要求采⽤惰性(lazy)⽅式实例化,并且在多线程 环境下,对该类的实例化不得采⽤同步锁。所需要的有关类的⽅法在后续的表中给出。请编写以下 代码⻣架中编号为(1)、(2)等部分的代码(答题时标注相应的序号)并说明HttpCache在多线程环境 下哪些些⽅法需要同步以及在当前条件下如何同步。测试数据在后⾯的表格中给出。

java代码实现

CacheItem.java

package com.njfu.cache;
public class CacheItem { 
	private String uri; //统一资源标识符
	private long since;//进入缓存时间
	private String body;//应答体
	// constructor (1)
	public CacheItem(String uri, String body) {
		this.uri = uri;
		this.body = body;
		//获取当前系统时间,单位为毫秒
		this.since = System.currentTimeMillis();
	}
	// accessor for uri (2)
	public void setUri(String uri) {
		this.uri = uri;
	}
	public String getUri() {
		return uri;
	}
	// accessor for since (3)
	public void setSince(long since) {
		this.since = since;
	}
	public long getSince() {
		return since;
	}
	// accessor for body (4)
	public void setBody(String body) {
		this.body = body;
	}
	public String getBody() {
		return body;
	}
	// When call System.out.println(aCacheItem), output “URI: uri, Since: since, Body: body” (5)
	//直接字符串拼接即可
	public String toString() {
		return "URI: "+uri+", Since: "+since+", Body: "+body;
	}
}


CacheItem.java

package com.njfu.cache;
import java.util.HashMap;
import java.util.Iterator;	// for Java 8- 
import java.util.Map;
import java.util.Set;	// Optional
//Don’t inherit from HahMap etc. 
public class HttpCache {
	
	//Cache all the HTTP responses
	private Map<String, CacheItem> cache;
	//7, 8, 9就是为了惰性单例
	//Make the globall instance of the HTTP response cache (7)
	private static class CacheMaker {
		private static final HttpCache instance = new HttpCache();
	}
	//constructor (8)私有的构造方法,禁止直接实例化
	private HttpCache() {
		this.cache = new HashMap<>();
	}
	/**
	*	Retrieve the globally unique instance of the HTTP response cache.
	*	@return the globally unique instance of the HTTP response cache.
	*/
	//通过方法创建实例
	public static HttpCache getInstance() { 
		//(9)
		return CacheMaker.instance;
	}
	
	
	/**
	*	Cache the HTTP response to the given resource URI.
	*	@param uri the URI of the requested resource.
	*	@param body the HTTP response body for the requested resource.
	*	@return true, if the cache item for the given URI has already
	*	existed, it was just updated; false, this is a new resource
	*	request.
	*/
	public synchronized boolean cache(String uri, String body) { 
		//(10)
		//利用哈希表判断cache中是否存在uri,如果存在则进行更新,返回true
		//不存在则插入当前item,返回false
		CacheItem item = this.cache.get(uri);
		if(item == null) {
			this.cache.put(uri, new CacheItem(uri, body));
			return false;
		}
		item.setBody(body);
		item.setSince(System.currentTimeMillis());
		return true;
	}
	
	
	/**
	*	Try to retrieve the cached response body by the given request URI.
	*	@param uri the request URI whose response body would be retrieved.
	*	@return the response body corresponding to the given request
	*	URI or null if the cache does not contain it.
	*/
	public synchronized String get(String uri) { 
		//(11)
		//直接调用hashmap的get函数,不空返回相对应的应答体,否则直接返回空
		CacheItem item = this.cache.get(uri);
		return item == null ? null : item.getBody();
	}
	
	
	/**
	*	Remove the cached HTTP response by the given resource URI.
	*	@param uri the URI of the resource to deleted.
	*	@return true, if the cache do contain the HTTP response for
	*	the given resource URI and it was deleted; false, otherwise.
	
	*/
	public synchronized boolean delete(String uri) { 
		//调用hashmap中的方法remove删除统一资源标识符为uri的实例
		//(12)
		Object o = cache.remove(uri);
		return !(o == null);
	}
	
	
	/**
	*	Delete all the cached HTTP responses earlier than the given
	*	threshold.
	*	@param delta the period in milliseconds that determine all
	*	the responses ahead of the current time delta milliseconds
	*	would be deleted.
	*/
	public synchronized void purge(long delta) {
		long now = System.currentTimeMillis();//获取当前时间
		
		//(13) //包括Java 8前后不同的实现
		// Java 8+
		
		//如果存在一个资源在缓存时间过长则删除
		//entrySet方法获取的其实就是一个类型为Map.Entery<key, value>的set容器
		//而set容器其实就是一个集合,可以用遍历整个集合或removeif+Lambda表达式删除里面所有符合条件对象
		//java8后可以用Lambda表达式+removeif
		this.cache.entrySet().removeIf(e -> e.getValue().getSince() <= now - delta);
		// Java 8-
		//java8之前只能迭代
		/*
		 //创立迭代器遍历整个set容器,找到满足条件的即可
		 for(Iterator<Map.Entry<String, CacheItem> > iter = cache.entrySet().iterator(); iter.hasNext();) {
			if(iter.next().getValue().getSince() <= now - delta) {
				iter.remove();
			}
		}
		*/
		
	}
	
	//Just for test
	@Override
	public String toString() {
		return this.cache.toString();
	}
	//Just for test, multi-threads not concerned! 
	public static void main(String[] args) {
	//In this case, ‘the HttpCache.’ part is optional 
		HttpCache.getInstance().cache("185080101",/*(14)*/"{no: \"185080101\", name: \"zhangsan\", gender: \"M\"}");
		//一些测试,可以不看
		//HttpCache c = HttpCache.getInstance();
		//System.out.println(c.delete("185080101"));
		//c.cache(, "{no: \"185080101\", name: \"zhangsan\", gender: \"M\"}");
		//System.out.println(c);
		/* (14)*/
	}
}

在这里插入图片描述
在这里插入图片描述

第三题

题目描述

以下是客户端通过数据报同服务器单向通信的代码框架。客户端从控制台上接收⽤户输⼊,按回⻋键后将所输⼊的内容发送给服务器,当⽤户输⼊EOF时,客户端退出;服务器端在本地环回接⼝ 上接收来⾃客户端的数据报并将其内容显示到终端窗⼝的,请根据其中的注释完成编号为(1)、(2)等 的代码。

java代码实现

DatagramServer.java

import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
import java.util.function.Consumer;

public class DatagramServer {
	// Port number
	private static final int SERVER_PORT = 8888;
	// Receiving buffer size, maximum 1KB. For UDP, this is enough 
	private static final int BUF_SIZE = 1024;

	public static void main(String args[]) throws Exception {
		// Used to log the received packet to console 
		//Consumer一个函数式接口,代表一个接收输入参数但是无返回值的操作,相当于一个消费者
		//::在java8之后可以用于获取类的静态方法,对象的成员方法等
		Consumer<String> logger = System.out::println;//(1)
		
		//DatagramPacket表示存放数据的数据报,DatagramSocket表示接受或发送数据报的套接字
		// Create a datagram socket 
		//构造方法
		//DatagramSocket(int port, InetAddress iad): 表示创建一个套接字,绑定到特定的端口号及指定地址
		DatagramSocket server = new DatagramSocket(SERVER_PORT, InetAddress.getLoopbackAddress());//(2)
		
		//数据缓冲池
		// Receiving buffer for datagram packet 
		byte[] buf = new byte[BUF_SIZE];
		
		// Keep running forever 
		for(;;) {
			// Create a new packet 
			DatagramPacket packet = new DatagramPacket(buf, BUF_SIZE);//(3)
			// Try to receive the datagram  packet
			//(4),接收数据
			server.receive(packet);
			// Use logger to write the content of the received packet to the console 
			//(5)
			logger.accept(new String(packet.getData(), 0, packet.getLength()));
		}
	}
}


DatagramServer.java


import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;

//DatagramClient.java
//import omitted
public class DatagramClient {
	//Server port number
	private static final int SERVER_PORT = 8888;
	//Client port
	private static final int CLIENT_PORT = 8889;
	//Size of the message buffer
	private static final int BUF_SIZE = 1024;

	public static void main(String args[]) throws Exception {
		//Create a datagram socket
		//(6)
		DatagramSocket client = new DatagramSocket(CLIENT_PORT, InetAddress.getLoopbackAddress());
		//Data buffer for datagram packet 
		byte[] buf = new byte[BUF_SIZE];
		
		//Read user input from the console. When hit EOF, exist
		//pos - the next position where to write the character. 
		for(int pos = 0, c; (c = System.in.read()) != -1/*(7)*/;) {
			switch(c) {
				case '\r':	// Windows break;
				case '\n':	// Finished a line
					//Send the message contained in the buffer
					//(8)
					client.send(new DatagramPacket(buf, pos, InetAddress.getLoopbackAddress(), SERVER_PORT));
					//Reset the buffer
					//(9)
					pos = 0;
					break;
				default:	
					// Cache the current character
					//assume no more than BUF_SIZE 
					buf[pos++] = (byte)c;
			}
		}
	
		System.out.println("Goodbye!");
		
		//Close the datagram socket (10)
		client.close();
	}
}

第四题

题目描述

根据以下所给定的简单电⼦邮件客户端的截图,以及以下代码⻣架中的注释,完成编号为(1)、(2)等部分的代码。当点击按钮“退出”时,终⽌该客户端的运⾏,要求采⽤Lambda表达式。

java代码

MailPanel.java

import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;

import javax.swing.JButton;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JTextArea;
import javax.swing.JTextField;

//MailPanel.java
//import omitted
public class MailPanel extends JPanel { 
	public MailPanel() {
		//create main panel and set grid bag layout 
		/*(1)*/
		//创建网格包布局
		super(new GridBagLayout());
		//create grid bag contraints 
		//GridBagConstraints是GridBagLayout的约束,即确定了组件的位置
		GridBagConstraints c = new GridBagConstraints();
		//row 0, column 0 -> 主题:
		//(3)
		//标题Label的位置为(0, 0),坐标为gridx->向右递增,girdy向下递增
		c.gridx = 0;
		c.gridy = 0;
		this.add(new JLabel("主题:"), c);
		//row 0, column 1 -> text field for subject, expand horizontally 
		//(4)
		//第一个文本框的位置以及占用的大小
		c.gridx = 1;
		c.fill = GridBagConstraints.HORIZONTAL;
		c.weightx = 1;
		this.add(new JTextField(), c);
		
		//row 0, column 2 -> 收件⼈:
		
		//(5)
		c.gridx = 2;
		c.fill = GridBagConstraints.NONE;
		c.weightx = 0;//窗口改变时增量的大小,为0时不增
		this.add(new JLabel("收件人:"), c);
		//row 0, column 3 -> text field for recipient, expand horizontally 
		//(6)
		c.gridx = 3;
		c.fill = GridBagConstraints.HORIZONTAL;
		c.weightx = 1;
		this.add(new JTextField(), c);
		//row 1, colulmn 0 -> email content 
		//(7)
		c.gridx = 0;
		c.gridy = 1;
		c.gridwidth = 4;
		c.weightx = 0.0;
		c.weighty = 1.0;
		c.fill = GridBagConstraints.BOTH;
		this.add(new JTextArea(), c);
		//row 3, column 1 -> 发送
		//(8)
		c.gridx = 1;
		c.gridy = 3;
		c.weighty = 0;
		c.fill = GridBagConstraints.NONE;
		c.anchor = GridBagConstraints.CENTER;
		c.gridwidth = 1;
		c.ipady = 0;
		this.add(new JButton("发送"), c);
		//row 3, column 3 -> 退出; exit with success code 
		//(9)
		c.gridx = 3;
		c.gridy = 3;
		c.gridwidth = 1;
		JButton bttn = new JButton("退出");
		bttn.addActionListener(e -> System.exit(0));
		this.add(bttn, c);
	}
}

MailClient.java


import java.awt.Container;

import javax.swing.JFrame;
import javax.swing.SwingUtilities;
import javax.swing.WindowConstants;

//MailClient.java
//import omitted
public class MailClient {
	public MailClient() {
		//create the main frame 
		//(10)
		JFrame frame = new JFrame("NJFU Emailer");
		//terminate the JVM when the close icon was clicked 
		//(11)
		frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
		//create and add the mail panel 
		//(12)
		frame.add(new MailPanel());
		//set the initial size of the frame, width: 600, height: 500 
		//(13)
		frame.setSize(600, 500);
		//display the frame 
		//(14)
		frame.setVisible(true);
	}


	public static void main(String[] args) {
		//create the frame on the event dispatching thread instead of the
		//main thread. You should use Lambada 
		//(15)
		//时间派发线程运行图形界面
		SwingUtilities.invokeLater(MailClient::new);
		//等价于SwingUtilities.invokeLater(() -> new MailClient());
	}
}

猜你喜欢

转载自blog.csdn.net/mwl000000/article/details/108453754