黑马程序员训练营基础测试题十道
代码下载见GitHubs:https://github.com/fairyxingyun/Itheima_exam_10_answer
1、 编写一个函数,函数内输出一个字符串,并在主函数内调用它。
Answer代码:
package com.itheima;
/**
* @author 星云
* 1.编写一个函数,函数内输出一个字符串,并在主函数内调用它。
* */
public class Test1 {
/**
* @param args
*/
//程序的入口点
public static void main(String[] args) {
// TODO Auto-generated method stub
//主函数中调用自定义的OutMyString()函数,输出一句话.
OutMyString();
}
/**
* 自定义OutMyString() 函数
*
* 实现功能:输出一句话.
*
*/
private static void OutMyString()
{
//输出一句话
System.out.println("Dear teacher,I am QingFeng Zhao,I want to be a member of the dark horse. ");
}
}
2、 从键盘接受一个数字,列出该数字的中文表示格式,例如:键盘输入123,打印出一二三;键盘输入3103,打印出三一零三。
Answer代码:
package com.itheima;
import java.util.HashMap;
import java.util.Map;
import java.util.Scanner;
import java.util.regex.Pattern;
/**
* @author 星云
* 2.从键盘接受一个数字,列出该数字的中文表示格式,
* 例如:
* 键盘输入123,打印出一二三;
* 键盘输入3103,打印出三一零三。
* */
public class Test2 {
/**
* 根据题意分析:
*
* 1.需要键盘输入一行不固定的字符串
*
* 解决思路: 定义字符串变量 getReadString来接受键盘输入的一行字符串
*
* 2.输入数据可能非法,因此需要一个容错机制.
*
* 解决思路: 自定义一个专门用来检测输入数据是否合法的函数
*
* 核心方法: 使用正则表达式来检测字符串是否为数字
*
* 4.输入阿拉伯数字输出中文数字 那么感觉用键值对是最好的.
*
* 解决思路: 使用HashMap实现Map接口,将信息存放到HashMap集合中.
*
* 5.需要读取字符串中每一个字符,然后找出对应的键值对.
*
* 解决思路:
*
* 1.使用String类的charAt(int index)方法可返回指定索引处的字符.
* 函数原型:char charAt(int index) 返回指定索引处的 char 值。
* 调用方法: String.charAt(i);
* 2.使用HashMap的 get(Object key)方法放回key所对应的value.
* 函数原型:V get(Object key) 返回指定键所映射的值;如果对于该键来说,此映射不包含任何映射关系,则返回 null。
* 6.需要将获取的字符拼接成字符串进行输出.
*
* 解决思路:
*
* 1.使用StringBuffer.append(char c)方法将获取字符拼接起来
* 2.使用StringBuffer.toString()方法将拼接好的内容转换成字符串
*/
public static void main(String[] args) {
// TODO Auto-generated method stub
System.out.println("请从键盘输入数字,程序将自动列出该数字的中文表示格式");
//1.需要键盘输入一行不固定的字符串
String getReadString= new Scanner(System.in).nextLine();
//2.调用自定义函数检测是否数据合法
if(isNumeric(getReadString))
{
//3.HashMap实现Map接口,然后将键值对信息保存到HashMap集合
Map<String,String> map=new HashMap<String,String>();
map.put("1", "一");
map.put("2", "二");
map.put("3", "三");
map.put("4", "四");
map.put("5", "五");
map.put("6", "六");
map.put("7", "七");
map.put("8", "八");
map.put("9", "九");
map.put("0", "零");
//4.获取字符串每一个字符,去HashMap结合查找key对应的value,然后拼接字符.
StringBuffer stringBuffer=new StringBuffer();
for(int i=0;i<getReadString.length();i++){
stringBuffer.append(map.get(getReadString.charAt(i)+""));
}
//5.StringBuffer.toString()方法转换成字符串输出
System.out.println(stringBuffer.toString());
}
else {//输入数据中含有非数字字符 即数据输入不合法时 友好提示.
System.out.println("对不起,您输入的字符串不是纯数字.");
}
}
//使用正则表达式检测输入字符串是否为数字.
public static boolean isNumeric(String str)
{
//定义正则表达式匹配规则:以数字开头,最少一位
Pattern pattern=Pattern.compile("^[0-9]{1,}");
return pattern.matcher(str).matches();
}
}
3、 什么情况下适合用UDP协议,什么情况下适合用TCP协议?
Answer代码:
package com.itheima;
public class Test3 {
/**
*@author 星云
* 3.什么情况下适合用UDP协议,什么情况下适合用TCP协议?
*/
public static void main(String[] args) {
// TODO Auto-generated method stub
/*****
* UDP:
* 特点:
* 1.将数据及源和目的封装成数据包中,不需要建立连接
* 2.每个数据包的大小限制在64K内
* 3.因无连接,是不可靠协议
* 4.不需要建立连接,速度快
* 6.及时性要求高于可靠性
*
* 经典应用举例:
* 1.实时音视频应该用UDP
* 2.可用于网络穿透如:翻墙
* 3.网络游戏人物移动
* 总结:UDP不在乎可靠性,数据包丢失不需要重传,不可靠但快,发送方不知道接收方是否收到数据
* TCP协议:
* 特点:
* 1.建立连接,形成传输数据的通道。
* 2.在连接中进行大数据量传输。
* 3.通过三次握手完成连接,是可靠协议。
* 4.必须建立连接,可靠但效率会稍低
* 5.可靠性要求高于及时性
* 经典应用举例:
* 1.下载文件。
* 2.打电话。
* 总结:TCP在乎可靠性,数据包丢失需要重传,可靠但慢,要求发送方确定地知道接收方是否收到数据。
*
* */
}
}
4、 编程计算3乘8等于几,什么方法效率更高?
Answer代码:
package com.itheima;
public class Test4 {
/**
* @author 星云
* 4、 编程计算3乘8等于几,什么方法效率更高?
*/
public static void main(String[] args) {
// TODO Auto-generated method stub
/**
* 3*8=24
* 但是在计算机中整数乘法或整数除法所需要的时钟周期远远大于移位操作所需的时钟周期
* 2.指令的基本执行时间
* 移位指令 寄存器移 1 位 时钟周期数为 2
* 整数乘法 IMUL 16位寄存器乘 时钟周期数为 128 ~ 154
* 整数除法 IDIV 16位寄存器 时钟周期数为 165 ~ 184
* 所以想提高效率就用移位方法。
* 移位运算分为左移和右移,左移相当于一个数乘以2的n次方,右移相当于一个数除以2的n次方。
* 左移变大,右移变小。
* 一个数x左移m位相当于即x乘以2的n次方(其中2^n=m)
* 比如3*8=3*(2^3)=3<<3,即数字3转换成二进制再左移3位。
* 而3<<3运算方法:
* 先将3转换成二进制,使用128 64 32 16 8 4 2 1码方法
* 可知数字3用二进制表示为 0 0 0 0 0 0 1 1
* 左移3位后二进制变为24 0 0 0 1 1 0 0 0
* 注意:>>:最高位补什么由原有数据最高位值而定。
* 如果最高位为0,右移后,用0补空位。
* 如果最高位为1,右移后,用1补空位。
* >>>:无论最高位是什么,右移后都用0补。
* */
System.out.println(3<<3);
}
}
5、 定义一个包含私有成员变量和函数的类,再定义一个内部类,在内部类函数中访问外部成员变量,并调用外部函数。在外部类函数中创建内部类对象,调用内部类函数。
Answer代码:
package com.itheima;
public class Test5 {
/**
* @author 星云
* 5、 定义一个包含私有成员变量和函数的类,再定义一个内部类,
* 在内部类函数中访问外部成员变量,并调用外部函数。
* 在外部类函数中创建内部类对象,调用内部类函数。
*
*/
public static void main(String[] args) {
// TODO Auto-generated method stub
GamePlayer player1=new GamePlayer();
player1.startPlayGame();
}
}
//定义一个外部类
class GamePlayer{
//定义私有成员变量
private String name="魔法师";
private int age=500;
//定义包含私有成员变量的函数
private void Introduction(){
System.out.println("我是"+name+","+age+"岁了,我已经进入游戏战场了!");
}
//外部类函数
public void startPlayGame(){
//外部类函数中创建内部类对象
Battle battle=new Battle();
//外部类函数中调用内部类函数
battle.killEnemy();
}
//定义一个内部类
class Battle{
//内部类函数
private void killEnemy(){
//内部类函数中调用外部函数
Introduction();
//内部类函数中访问外部成员变量
System.out.println("警报!!!这位"+age+"岁的"+name+"被BOSS杀死了!");
}
}
}
6、 throw和throws有什么区别? try、catch、finally分别在什么情况下使用?
Answer代码:
package com.itheima;
public class Test6 {
/**
* @author 星云
*
* 6.throw和throws有什么区别? try、catch、finally分别在什么情况下使用?
*/
public static void main(String[] args) {
// TODO Auto-generated method stub
/**
* throw和throws有什么区别?
*
* throw和throws的区别
*
* 1.throw用在函数内,throws用在函数上。
* 2.throw用于抛出异常对象,throws用于抛出异常类。
* 3.throw后面跟的是异常对象,throws后面跟的是异常类名,可以抛出多个,用逗号隔开。
* 4.throw用于抛出一个具体的异常类型,throws用来声明一个方法可能抛出的所有异常信息
* 5.throw则需要用户自己捕获相关的异常,而后在对其进行相关包装,最后在将包装后的异常信息抛.
* throws通常不用显示的捕获异常,可由系统自动将所有捕获的异常信息抛给上级方法;
*
*
* try、catch、finally分别在什么情况下使用?
*
* try{
* 需要被检测的代码
* }
* catch(异常类 变量)
* {
* 处理异常的代码,(处理方式)
* }finally{
* 一定会执行的语句
* 注意:
* 1,finally中定义的通常是 关闭资源代码。因为资源必须释放
* 2,finally只有一种情况不会执行。当执行到System.exit(0);finally不会执行。
* }
*
* 注意:
* 1.当函数内容有throw抛出异常对象,并未进行try处理。必须要在函数上声明,否则编译失败。
* RuntimeException除外。也就说,函数内如果抛出的RuntimeException异常,函数上可以不用声明。
* 2.try块必须和catch块或和finally同在,不能单独存在,二者必须出现一个
* */
}
}
7、 编写一个延迟加载的单例设计模式。
Answer代码:
package com.itheima;
import com.itheima.Single.Singleton;
public class Test7 {
/**
* @author 星云
* 7、 编写一个延迟加载的单例设计模式。
*/
public static void main(String[] args) {
// TODO Auto-generated method stub
/**
* 做此题前,先了解几个概念:
* 1.what is 单例模式?
* 所谓单例模式,简单来说,就是在整个应用中保证只有一个类的实例存在。
* 单例模式确保某一个类只有一个实例,而且自行实例化并向整个系统提供这个实例。这个类就称为单例类。
* 2.单例模式分类?
* 单例的创建一般分为懒汉式,恶汉式,双重锁检查,枚举,静态内部类,
* 3.what is 延迟加载?
* 延迟加载就是把对象的创建延迟到使用的时候创建,而不是对象实例化的时候创建。
* */
Single single1=Single.getInstance();
Single single2=Single.getInstance();
System.out.println(single1==single2);
/**
* 运行结果:true
* 说明:单例模式的类的全部实例都是同一共享实例。
* 在程序中虽然获得了两个类的实例,但是实际只执行了一次构造器。
* 因为对于单例模式的类,不管有多少次创建实例请求,都只执行一次构造器,
* 返回同一个共享实例。
*/
}
}
/**
* 双重校验锁 延迟加载单例设计模式
* 这个其实就叫(double-checked-locking模式)
* 其实这种方法有一个缺点:
* 在一个线程还未完全初始化该对象时,而那个变量已经显示为被初始化,
* 那么其他线程可能去使用这个未被完全初始化的实例,就可能造成系统的崩溃。
* 不过在java1.5以上可以安全运行。
* 1、单例就是该类只能有一个唯一的对象,私有构造函数
* 2、在内部建立对象 提供公共访问方式访问
* 3、双重判断对对象的引用进行判断,加入同步更安全。
*/
/*
class Single{
//静态私有的成员变量
private static Single single=null;
//私有的构造方法
private Single(){}
//共有的静态的类成员方法
public static Single getInstance(){
if(single==null){//如果没有创建就进行同步创建
//锁定代码块
synchronized(Single.class)
{
//再次判断,以防两个线程同时经过第一道判断,
//之后先后进入同步后还是能创建各自的对象的,故需再次判断
if(single==null)
single=new Single();//分3步:1.分配内存 2.调用构造函数 3.给出引用
//如果不按照1 2 3 顺序访问,系统则会崩溃。
}
}
return single;
}
}
*/
/**
* 静态内部类 完美实现既线程安全又延迟加载的单例设计模式
* 优势:
* 1.不受JDK版本的影响。
* 2.这个模式综合使用了Java的类级内部类和多线程缺省同步锁的知识,很巧妙地同时实现了延迟加载和线程安全。
* 3.线程安全,延迟加载。
*/
class Single{
//构造方法私有化
private Single(){};
//静态内部类,只有当有引用时,该类才会被装载
public static class Singleton{
private static final Single instance=new Single();
}
//第一次调用getInstance()方法时,才会去初始化instance实例,而且该实例被定义为static,只会被初始化一次。
public static Single getInstance(){
return Singleton.instance;
}
}
8、 编写程序接收键盘输入的5个数,装入一个数组,并找出其最大数和最小数。
Answer代码:
package com.itheima;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.Scanner;
public class Test8 {
/**
* @author 星云 8.编写程序接收键盘输入的5个数,装入一个数组,并找出其最大数和最小数。
*/
public static void main(String[] args) throws NumberFormatException, IOException {
// TODO Auto-generated method stub
// 定义数组长度为5
int[] arr = new int[5];
//从控制台循环接受5个整型数据并装入一个整型数组中
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
for (int i = 0; i < arr.length; i++) {
try {
//将控制台输入的数据转换成整型
System.out.println("请输入第"+(i+1)+"个整型数据:");
arr[i] = Integer.parseInt(br.readLine());
} catch (NumberFormatException e) {//数据类型转换错误异常
System.out.println("对不起,输入数据非法,请重新运行本程序!");//数据如果输入非法数据
return ;
} catch (IOException e) {
e.printStackTrace();
}
}
// 打印最大值
System.out.println("数组的最大值为:" + getMax(arr));
// 打印最小值
System.out.println("数组的最小值为:" + getMin(arr));
}
// 查找最大值
public static int getMax(int[] arrs) {
int max = arrs[0];
for (int i = 0; i < arrs.length; i++) {
// 如果数组里面有别的数比最大值大,则为最大值
if (arrs[i] > max) {
max = arrs[i];
}
}
return max;
}
// 查找最小值
public static int getMin(int[] arrs) {
int min = arrs[0];
for (int i = 0; i < arrs.length; i++) {
// 如果数组里面有别的数比最小值小,则为最小值
if (arrs[i] < min) {
min = arrs[i];
}
}
return min;
}
}
9、 求1000!的结果中包含多少个0?注:1000! = 1×2×3×4×5×…×999×1000
Answer代码:
package com.itheima;
import java.math.BigInteger;
import java.util.Scanner;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class Test9 {
/**
* @author 星云
* 9、 求1000!的结果中包含多少个0?
* 注:1000! = 1×2×3×4×5×...×999×1000
*/
public static void main(String[] args) {
// TODO Auto-generated method stub
/**
* 调用自定义方法计算1000的阶乘
* BigInteger BigNumFactorial(Integer n);
* n :求几的阶乘n就等于多少。
* resultBigNumber: 1000阶乘的结果
*/
BigInteger resultBigNumber = BigNumFactorial(1000);
/**
* 调用自定义方法统计n的阶乘结果中0的个数。
* void CountNumResultZero(Integer n, BigInteger bigNumber)
* n:n的阶乘
* bigNumber:n的阶乘结果
* 无返回值
*/
CountNumResultZero(1000, resultBigNumber);
}
/**
* @param 方法功能:计算n的阶乘
* */
private static BigInteger BigNumFactorial(Integer n) {
// 将整型数据1强制转换成BigInteger类型
BigInteger number = BigInteger.valueOf(1);
// 循环计算n的阶乘
for (int i = 1; i <= n; i++) {
/**
* 下面这句代码等价于number=number*i; 但是BigInteger不是基本数据类型,不能使用*运算符,用独有的方法
* */
number = number.multiply(BigInteger.valueOf(i));
}
// 输出n的阶乘结果
System.out.println(n + "的阶乘为:\n" + number);
return number;
}
/**
* 方法功能:统计一个n的阶乘中BigInteger变量中0的个数
* void CountNumResultZero(Integer n, BigInteger bigNumber);
* @param n 阶乘数n
* @param bigNumber
* 统计bigNumber中0的个数。
*/
private static void CountNumResultZero(Integer n, BigInteger bigNumber) {
int count = 0;// 计数器,统计计算结果中0的个数
// 将BigInteger类型 number转换成字符串,再转换成字符数组
char[] b = bigNumber.toString().toCharArray();
// 遍历字符数组查找字符'0'
for (char c : b) {
if (c == '0')// 如果查找成功
count++;// 计数器加一
}
System.out.println(n + "的阶乘结果中包含" + count + "个0");
}
}
10、 小明的妈妈每天会给他20元零花钱。平日里,小明先花掉一半,再把一半存起来。每到周日,小明拿到钱后会把所有零花钱花掉一半。请编程计算,从周一开始,小明需要多少天才能存够100元?
Answer代码:
package com.itheima;
public class Test10 {
/**
* @author 星云
* 10.小明的妈妈每天会给他20元零花钱。平日里,小明先花掉一半,再把一半存起来。
* 每到周日,小明拿到钱后会把所有零花钱花掉一半。
* 请编程计算,从周一开始,小明需要多少天才能存够100元?
*/
public static void main(String[] args) {
// TODO Auto-generated method stub
int money=0,j;
for (j=1;;j++) {
if(j%7==0)
{
money=(money+20)-(money+20)/2;
//System.out.println("第"+j+"天共存了"+money+"元\n");
}else{
money=money+20-10;
//System.out.println("第"+j+"天共存了"+money+"元\n");
}
if(money>=100)
{
System.out.println("小明需要"+j+"天才能够存够100元。");
break;
}
}
}
}