目录
前言
选择题
编程题
前言
我们在前面四章已经学习了JavaSE的部分基础知识,以下题目可以帮助你熟练运用这些知识,通过练习加深对Java的理解,欢迎收藏食用。有不懂的或者有歧义的欢迎在评论区讨论。
选择题
T1:Java 的字符类型采用的是 Unicode编码方案,每个 Unicode码占用( )个比特位
A.8 B.16 C.32 D.64
答案:B
解析:Java中,char占2字节,即16位bit,可存放汉字。
范围是0~65535,如何转换成十六进制呢?
1Byte = 8个二进制位
一个十六进制= 4个二进制位(8,4,2,1)
1Byte = 2个十六进制
65535的二进制表达为1111 1111 1111 1111
所以char的十六进制取值范围为0000-FFFF
T2:下列语句哪些是正确的 ( )
A.Java程序经编译后会产生machine code
B.Java程序经编译后会产生byte code
C.Java程序编译使用命令javac,运行则使用 java 命令
D.以上都不正确
答案:BC
解析:machine code是机器码,机器码是电脑的
CPU可直接解读
的数据(计算机只认识0和1)。机器码是要用机器语言编写的,A错误。
byte code是字节码,字节码是一种中间状态的二进制代码,它比机器码更抽象,需要通过直译器转译后才能翻译为机器码。字节码的实现方式是通过编译器和虚拟机器。编译器将源码编译成字节码,特定平台上的虚拟机器将字节码转译为可以直接执行的指令。字节码在运行时通过
JVM(JAVA虚拟机)
做一次转换生成机器指令,因此能够很好的跨平台运行,B正确。在cmd中,javac xxx.java指令可将java源程序编译为字节码class文件,然后通过java xxx指令可在JVM中运行class文件。
T3:下列有关JDK, JRE, JVM三者的叙述,正确的是:( )
A.JDK是Java开发工具包 ,包括了Java运行环境JRE(Java Runtime Envirnment)、一堆Java工具(javac/java/jdb等)和Java基础的类库(即Java API 包括rt.jar)。
B.JRE是运行基于Java语言编写的程序所不可缺少的运行环境。也是通过它,Java的开发者才得以将自己开发的程序发布到用户手中,让用户使用。
C.JVM是整个Java实现跨平台的最核心的部分,所有的Java程序会首先被编译为.class的类文件,这种类文件可以在虚拟机上执行。也就是说class并不直接与机器的操作系统相对应,而是经过虚拟机间接与操作系统交互,由虚拟机将程序解释给本地系统执行
D.JDK中包含了JRE,JRE又包含JVM
答案:ABCD
解析:全部理解记忆,能够基本概括即可。
T4:下面属于java基本类型的有( )
A.String B.byte C.char D.Array
答案:BC
解析:String和Array是引用类型。所以AD错误。
T5.下面属于java包装类的是( )
A.String B.Long C.Character D.Short
答案:BCD
解析:Java有8种基本数据类型:整型(byte、short、int、long)、浮点型(float、double)、布尔型boolean、字符型char,相对应地,Java提供了8种包装类Byte、Short、Integer、Long、Float、Double、Boolean、Character。
T6.在java中,下列标识符不合法的有( )
A.new B.$Usdollars C.1234 D.car.taxi
答案:ACD
解析:标识符中可以包含:字母、数字以及下划线_和 $ 符号等等。标识符不能以数字开头,标识符也不能是关键字,且严格区分大小写。
A是关键字,错误。C以数字开头,错误。D有小数点,不符合规定,错误。
T7.经过强制类型转换以后,变量a,b的值分别为多少( )
short a =128; byte b =(byte) a;
A.128,127 B.128,-128 C.128,128 D.编译错误
答案:B
解析:字面常量128存入short的时候会先发生检查,如果字面常量128在short的范围内,则可以看作short存入short,如果不在short的范围内,则看作int类型存入short类型,不兼容,报错。
128显然在short的范围内,所以可以存入a,所以a=128。
由于byte的取值范围为-128~127,a如果直接存入byte类型的b,显然是会报错的,所以需要将128强制转换为byte类型,所以需要分析128在内存中的存储情况:
128超出了byte的范围,所以看作4字节的int类型,32位bit
128的原码:0000 0000 0000 0000 0000 0000 1000 0000
128的反码:0111 1111 1111 1111 1111 1111 0111 1111
128的补码:0111 1111 1111 1111 1111 1111 1000 0000
数据以补码形式存储,而byte是1个字节,发生截断,保留低位。则存入byte的是1000 0000。
而在计算机中的规定是:1000 0000就是-128,所以b=-128
还有一种理解方式是,将byte的取值范围看作一个循环。
要在byte中存入128,我们首先知道byte能存的最大的整数就是127了,再+1,不就变成了-128了吗?深入理解这个循环对我们理解数据存储有很大的帮助。
T7.如下Java语句 double x=2.0; int y=4; x/=++y; 执行后,x的值是( )
A.0.5 B.2.5 C.0.4 D.2.0
答案:C
解析:++y意为先对y自增,再使用。所以x/=++y即2.0/=5,/=这样的运算符有自动转换的作用,所以答案为0.4
T8.下列说法正确的是( )
A.布尔类型boolean占有一个字节,由于其本身所代码的特殊含义,boolean类型与其他基本类型不能进行类型的转换(既不能进行自动类型的提升,也不能强制类型转换), 否则,将编译出错。
B.byte a = 130; float b = 3.5; 这两行代码会发生编译错误
C.int a = 3; byte b = a; 这句话可以正常通过编译,且运行不会发生错误。
答案:AB
布尔类型是无法和其他基本类型进行转换的,对于boolean占有几个字节,则有以下几种说法:
- 1个bit:理由是boolean类型的值只有true和false两种逻辑值,在编译后会使用1和0来表示,这两个数在内存中只需要1位(bit)即可存储。位是计算机最小的存储单位。
- 1个字节:理由是虽然编译后1和0只需占用1位空间,但计算机处理数据的最小单位是1个字节,1个字节等于8位,实际存储的空间是:用1个字节的最低位存储,其他7位用0填补,如果值是true的话则存储的二进制为:0000 0001,如果是false的话则存储的二进制为:0000 0000
- 4个字节:理由来源是《Java虚拟机规范》一书中的描述:“虽然定义了boolean这种数据类型,但是只对它提供了非常有限的支持。在Java虚拟机中没有任何供boolean值专用的字节码指令,Java语言表达式所操作的boolean值,在编译之后都使用Java虚拟机中的int数据类型来代替,而boolean数组将会被编码成Java虚拟机的byte数组,每个元素boolean元素占8位”。这样我们可以得出boolean类型占了单独使用是4个字节,在数组中又是1个字节。
所以我们能够知道:boolean类型没有给出精确的定义,具体还要看虚拟机实现是否按照规范来,所以1个bit,1个字节,4个字节都是有可能的。所以A正确。
对于B,先检查字面值130在不在byte范围内,显然不在,则看作int类型存入byte类型,范围大类型无法直接存入范围小的类型,不兼容,报错。B正确
对于C,int类型的a存入byte类型的b,不兼容,报错。C错误
T9.基本数据类型均可任意互相转换( )
A.对 B.错
答案:B
解析:是不是忘了boolean类型了?
T10.如果要打印一个字符串,需要使其输出结果为:\"hello\",则以下哪种方式可以正确输出:( )
A.System.out.println("\\\"hello\\\"");
B.System.out.println("\\"hello\\"");
C.System.out.println("/\"hello/\"");
答案:A
解析:本题考查转义字符。\\转义为\,\"转义为",防止内层的"和外层的"结合。所以选A。
T11.以下会产生信息丢失的类型转换是( )
A.float a=10; B.int a =(int)8846.0; C.byte a=10;int b=-a; D.double d=100;
答案:B
解析:A,范围小的int存入范围大的float,完全可行。
B,范围大的double被强转为int,丢掉了小数点后的位,信息发生丢失。
C,当操作数是byte,short,char时,它们参与运算,会自动转化为int类型,byte类型的a加上-号,参与了运算,int类型存入int类型,完全可行。
D,int类型存入double类型,范围小的数据存入范围大的数据,发生隐式(自动)类型转换,完全可行。
T12.以下哪一个不是赋值符号( )
A.+= B.<<= C.<<<= D.>>>=
答案:C
解析:>>>=意为无符号右移后再赋值给本身,右移后左边自动补0。
而<<<=意为无符号左移后再赋值给本身,无论是有符号左移还是无符号左移,都是在右边自动补0,所以<<<的存在是无意义的,所以java中是不存在无符号左移的。
T13.switch(){}结构中,括号中可使用的数据类型不能是( )。
A.long B.int C.short D.float
答案:AD
解析:java中switch()括号中不能放long,float,double,boolean类型的数据,可以使用byte,short,char,int,枚举类型,String类型的数据。
编程题
T1.输出n*n的乘法口诀表,n由用户输入。
参考代码:
public static void Multiplication(int n){ int i=0; int j=0; for(i=1;i<=n;i++) { for (j=1;j<=i;j++) { System.out.print(j+"*"+i+"="+i*j+"\t"); } System.out.println("\n"); } } public static void main(String[] args) { Scanner scan = new Scanner(System.in); System.out.println("请输入n=>"); int n= scan.nextInt(); Multiplication(n); }
T2. 编写代码模拟三次密码输入的场景。 最多能输入三次密码,密码正确,提示“登录成功”,密码错误, 可以重新输 入,最多输入三次。三次均错,则提示退出程序
参考代码:
public static void login() { int count = 3; Scanner scanner = new Scanner(System.in); while (count != 0) { System.out.println("请输入你的密码:"); String password = scanner.nextLine(); if(password.equals("123")) { System.out.println("登录成功!"); return; }else{ count--; System.out.println("你还有 "+count+" 次机会!"); } } }
值得一提的是,Java中判断字符串是否相同,不能直接用==,而是用object.euals(object)。
==比较两个变量本身的值,即两个对象在内存中的首地址。
equals()比较字符串中所包含的内容是否相同
T3.求一个整数,在内存当中存储时,二进制1的个数。
方法1:遍历32个位,一个个取出来和1判断这个位是否为1,用计数器计数。
参考代码如下:
public static void main(String[] args) { Scanner scan =new Scanner(System.in); int i; int count=0;//计数器 System.out.println("请输入n=>"); int n=scan.nextInt(); for(i=0;i<=31;i++){ if(((n>>i)&1)==1){ count++; } } System.out.println(n+"的二进制中有"+count+"个1"); }
方法2:遍历一次就判断一次是否为0,比起方法1更优。
public static void main(String[] args) { Scanner scan =new Scanner(System.in); int count=0; System.out.println("请输入n=>"); int n=scan.nextInt(); int temp=n; while(n!=0){ if((n&1)==1){ count++; } n>>>=1; } System.out.println(temp+"的二进制中有"+count+"个1"); }
方法3:n&(n-1)可以去掉n二进制位中最右边的1!利用这个思路可以写出最优的程序。
参考代码如下:
public static void main(String[] args) { Scanner scan =new Scanner(System.in); int count=0; System.out.println("请输入n=>"); int n=scan.nextInt(); int temp=n; while(n!=0){ n=(n&n-1); count++; } System.out.println(temp+"的二进制中有"+count+"个1"); }
T4. 获取一个数二进制序列中所有的偶数位和奇数位, 分别输出二进制序列
参考代码如下:
public static void main4(String[] args) { Scanner scan =new Scanner(System.in); int i; System.out.println("请输入n=>"); int n=scan.nextInt(); System.out.println("偶数位:"); for(i=31;i>=1;i-=2){//打印偶数位 System.out.print((n>>>i)&1); } System.out.println("\n奇数位:"); for(i=30;i>=0;i-=2){//打印奇数位 System.out.print((n>>>i)&1); } }
T5.输入一个数字k判断它是不是2的n次方
思路:我们根据需求来分析问题,先看这样一组数,找他们共同的规律。
我们一眼就能看出,2的n次方都有一个共同的特点,就是二进制位只有一个1,那么这个题目就可以翻译为:判断某个数的二进制位是否只有一个1。于是很快就能得解,这题就是2015年百度的笔试题。
参考代码如下:
public static void main(String[] args) { Scanner scan =new Scanner(System.in); int k= scan.nextInt(); if((k&(k-1)) ==0){ System.out.println("YES");; }else{ System.out.println("NO"); } }
T5. 求两个正整数的最大公约数
方法1:首先最大公约数是不可能超过较小数本身的,我们就找出较小数,以较小数为起点,进行递减依次试除判断。
参考代码如下:
public static void main5(String[] args) { Scanner scan= new Scanner(System.in); System.out.println("请输入a,b的值=>"); int a= scan.nextInt(); int b= scan.nextInt(); int min=a>b?b:a; for (int i = min; i >= 0 ; i--) { if(a%i==0&&b%i==0){ System.out.println(i+"是最大公约数"); break; } } }
方法2:辗转相除法
其代码实现如下:
public static void main(String[] args) { Scanner scan= new Scanner(System.in); System.out.println("请输入a,b的值=>"); int a= scan.nextInt(); int b= scan.nextInt(); int extra =a%b; while(extra!=0){ a=b; b=extra; extra=a%b; } System.out.println("最大公约数为"+b); }
方法3:辗转相除法(递归版)
public static int gcd(int m,int n) { if(n == 0){ return m; } int r = m%n; return gcd(n,r); } public static void main(String[] args) { Scanner scan= new Scanner(System.in); System.out.println("请输入a,b的值=>"); int a= scan.nextInt(); int b= scan.nextInt(); int max=gcd(a,b); System.out.println("最大公约数为"+max); }
T6.求出0~999999之间的所有“自幂数”并输出。(“自幂数”是指一个n位数,其各位数字的n次方和确好等于该数本身,如;153=1^3+5^3+3^3,则153是一个“自幂数“。)
思路:用计数器求出位数后,利用pow方法进行判断可以很容易得解。参考代码如下:
public static void main(String[] args) { for (int num = 0; num <=999_999; num++) { int count=0;//位数 int temp=num; int sum=0;//累加器 while(temp!=0){ temp/=10; count++; } temp=num; while(temp!=0){ sum+=Math.pow(temp%10,count);//+=具有自动转换的作用,pow的返回值本来是double,但是被+=强转为了int temp/=10; } if(sum==num){ System.out.println(num); } } }
T7.判断一个数是不是素数
方法1:最容易理解的思路就是,根据素数的定义来做,直接拿2-num-1的数去依次试除看看是否会被整除,如果被整除了则说明这个数是合数,如果遍历完以后没被整除,则说明是素数。参考代码如下:
public static boolean isPrime1(int num) { for (int i = 2; i < num; i++) { if(num % i == 0) { //System.out.println("不是素数!"); return false; } } //System.out.println("是素数!"); return true; }
方法2:折半
我们观察,比如判断16是不是素数,发现它有这样几种组合方式:
1*16,2*8,4*4,8*2,16*1,把1的情况排除掉,发现参与运算最大数也就是16的一半8,于是可以优化算法,直接折半:
public static boolean isPrime2(int num) { for (int i = 2; i <= num/2; i++) { if(num % i == 0) { return false; } } return true; }
方法3:Sqrt法
比如判断9是不是素数,有这样几种组合方式,1*9,3*3,3是9的开平方。实际上需要判断一个数是不是素数,只需要判断2~它的开平方即可。
public static boolean isPrime2(int num) { for (int i = 2; i <= Math.sqrt(num); i++) { if(num % i == 0) { return false; } } return true; }
T8.判断输入的年份是不是闰年(要求多组输入!)
思路:判断闰年相信对大家来说不是难事,这里主要介绍多组输入的方法:while(scan.hasNextInt())意为循环输入int,在cmd中ctrl+Z可以结束循环输入,在IDEA中则是ctrl+D结束输入。
public static void main(String[] args) { int year=0; Scanner scan=new Scanner(System.in); while(scan.hasNextInt()){ System.out.println("请输入year=>"); year=scan.nextInt(); if(year%100!=0&&year%4==0||year%400==0){ System.out.println("YES"); }else{ System.out.println("NO"); } } }
到这里就结束了,希望能给你带来帮助。如果再也不能见到你,也祝你早安午安还有晚安。
评论区评论会回访,欢迎一键三连。