一、基础题
1)用最有效的的方法算出2称以8等于几
答案:2<<3
2)两个对象a和b,请问a==b和a.equals(b)有什么区别?
a==b:比较对象地址
a.equals(b):如果a对象没有重写过equals方法,效果和==相同,如果重写了就按照重写的规则比较。
3)数组有没有length()方法?String有没有length()方法?File有没有length()方法?ArrayList有没有length()方法?
数组没有length()方法,但是有length属性。
String和File有length()方法。
ArrayList没有length()方法,有size()方法获取有效元素个数。
4)String str = new String(“hello”);创建了哪些对象?
字符串常量池中有一个对象,堆中有一个字符串对象。
5)如何将String类型转化Number(Integer,Float,Long,Double等类的父类)类型?举例说明String str = “123”;
答任意一个都对:
Integer num1 = new Integer(str);
或
int num2 = Integer.parseInt(str);
或
Integer num3 = Integer.valueOf(str);
6)Java的数据类型有哪些?String是基本数据类型吗?
Java的数据类型有:
(1)基本数据类型:byte,short,int,long,float,double,char,boolean
(2)空类型:void
(3)引用数据类型:数组、类、接口、枚举、注解等
String是引用数据类型,不是基本数据类型
7)编写代码实现2个变量值的交换,int m=3,n=5;
8)以下代码的执行结果
9)(15)和Math.round(-15)的值是多少?
10)switch是否能作用在byte上,是否能作用在long上,是否能作用在String上?
二、基础编程题
1)用循环控制语句打印输出:1+3+5+...+99=?的结果
2)编写方法实现:求某年某月某日是这一年的第几天
提示:闰年(1)能被4整除不能被100整除(2)能被400整除
//答案一:public static int daysOfYear(int year, int month, int day){int[] daysOfMonth = {31,28,31,30,31,30,31,31,30,31,30,31};int sum = day;for(int i=0;i< month-1; i++){sum += daysOfMonth[i];}if(month2){if(year%4==0 && year%100!=0 || year%400==0){sum++;}}return sum;}//答案二:public static int daysOfYear(int year, int month, int day){int[] daysOfMonth = {31,28,31,30,31,30,31,31,30,31,30,31};int sum = day;for(int i=0;i< month-1; i++){sum += daysOfMonth[i];if(i==1){if(year%4==0 && year%100!=0 || year%400==0){sum++;}}}return sum;}
3)输出以下图形,一共有n行,第n行有2n-1个*,完成方法public void printStar(int n)的方法体?
public void printStar(int n) {for (int i = 1; i <= n; i++) {for (int j = 0; j < n - i; j++) {System.out.print(" ");}for (int j = 0; j < 2 * i - 1; j++) {System.out.print("*");}System.out.println();}}
4)请写一个冒泡排序,实现{5,7,3,9,2}从小到大排序
//答案一:int[] arr = { 5, 7, 3, 9, 2 };for (int i = 1; i < arr.length; i++) {for (int j = 0; j < arr.length - i; j++) {if (arr[j] > arr[j + 1]) {int temp = arr[j];arr[j] = arr[j + 1];arr[j + 1] = temp;}}}
//答案二:int[] arr = { 5, 7, 3, 9, 2 };for (int i = 1; i < arr.length; i++) {for (int j = arr.length-1; j >= i; j--) {if (arr[j] < arr[j - 1]) {int temp = arr[j];arr[j] = arr[j - 1];arr[j - 1] = temp;}}}
5)求1+2!+3!+...+20!的和
public static void main(String[] args) {long sum = 0;for (int i = 1; i <= 20; i++) {long temp = 1;for (int j = 1; j <=i; j++) {temp *= j;}sum += temp;}System.out.println("sum = " + sum);}
6)请编写代码使用把一个字符串反转,例如:hello1234,反转后:4321olleh。
//答案一:
public class Test {public static void main(String[] args) {String str = "hello1234";StringBuilder s = new StringBuilder(str);s.reverse();str = s.toString();System.out.println(str);}
}
//答案二:
public class Test {public static void main(String[] args) {String str = "hello1234";char[] array = str.toCharArray();for (int i = 0; i < array.length / 2; i++) {char temp = array[i];array[i] = array[array.length - 1 - i];array[array.length - 1 - i] = temp;}str = new String(array);System.out.println(str);}
}
7)通项公式如下:f(n)=n + (n-1) + (n-2) + .... + 1,其中n是大于等于5并且小于10000的整数,例如:f(5) = 5 + 4 + 3 + 2 + 1,f(10) = 10 + 9 + 8 + 7+ 6 + 5 + 4 + 3 + 2 + 1,请用非递归的方式完成方法long f( int n)的方法体。
答案一:非递归public static long f(int n) {long sum = 0;for (int i = 1; i <= n; i++) {sum += i;}return sum;}
8)有一个字符串String abc = “342567891”,请写程序将字符串abc进行升序,可以使用JDK API中的现有的功能方法。
public class Test {public static void main(String[] args) {String str = "342567891";char[] arr = str.toCharArray();Arrays.sort(arr);str = new String(arr);System.out.println(str);}
}
9)把如下信息添加到Map中,并遍历显示
浙江省
绍兴市
温州市
湖州市
嘉兴市
台州市
金华市
舟山市
衢州市
丽水市
海南省
海口市
三亚市
北京市
北京市
//参考答案一:
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map.Entry;
import java.util.Set;public class Test {public static void main(String[] args) throws Exception {HashMap<String,List<String>> map = new HashMap<String,List<String>>();map.put("北京市", Arrays.asList("北京市"));map.put("海南省", Arrays.asList("海口市","三亚市"));map.put("浙江省", Arrays.asList("绍兴市","温州市","湖州市","嘉兴市","台州市","金华市","舟山市","衢州市","丽水市"));Set<Entry<String, List<String>>> entrySet = map.entrySet();for (Entry<String, List<String>> entry : entrySet) {System.out.println(entry.getKey());List<String> value = entry.getValue();for (String string : value) {System.out.println("\t" + string);}}}
}
//参考答案二:
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map.Entry;
import java.util.Set;public class Test {public static void main(String[] args) throws Exception {HashMap<String,ArrayList<String>> map = new HashMap<String,ArrayList<String>>();ArrayList<String> bj = new ArrayList<String>();bj.add("北京市");map.put("北京市", bj);ArrayList<String> hn = new ArrayList<String>();hn.add("海口市");hn.add("三亚市");map.put("海南省", hn);ArrayList<String> zj = new ArrayList<String>();zj.add("绍兴市");zj.add("温州市");zj.add("湖州市");zj.add("嘉兴市");zj.add("台州市");zj.add("金华市");zj.add("舟山市");zj.add("衢州市");zj.add("丽水市");map.put("浙江省", zj);Set<Entry<String, ArrayList<String>>> entrySet = map.entrySet();for (Entry<String, ArrayList<String>> entry : entrySet) {System.out.println(entry.getKey());ArrayList<String> value = entry.getValue();for (String string : value) {System.out.println("\t" + string);}}}
}
//参考答案三:
import java.util.HashSet;
import java.util.HashMap;
import java.util.Map.Entry;
import java.util.Set;public class Test {public static void main(String[] args) throws Exception {HashMap<String,HashSet<String>> map = new HashMap<String,HashSet<String>>();HashSet<String> bj = new HashSet<String>();bj.add("北京市");map.put("北京市", bj);HashSet<String> hn = new HashSet<String>();hn.add("海口市");hn.add("三亚市");map.put("海南省", hn);HashSet<String> zj = new HashSet<String>();zj.add("绍兴市");zj.add("温州市");zj.add("湖州市");zj.add("嘉兴市");zj.add("台州市");zj.add("金华市");zj.add("舟山市");zj.add("衢州市");zj.add("丽水市");map.put("浙江省", zj);Set<Entry<String, HashSet<String>>> entrySet = map.entrySet();for (Entry<String, HashSet<String>> entry : entrySet) {System.out.println(entry.getKey());HashSet<String> value = entry.getValue();for (String string : value) {System.out.println("\t" + string);}}}
}
10)补充如下枚举类型的代码,使得如下代码达到运行效果
单词提示:monday,tuesday,wednesday,thursday,friday,saturday,sunday
import java.util.Scanner;public class TestWeek {public static void main(String[] args) {Scanner input = new Scanner(System.in);System.out.print("今天是星期几(1-7):");int number = input.nextInt();//假设输入的是2Week w = Week.getByNumber(number);System.out.println("今天是:" + w);//今天是:TUESDAY(2,星期二)}}
enum Week{(1) private int number;private String decription;private Week(int number, String decription) {this.number = number;this.decription = decription;}public static Week getByNumber(int number){(2) }@Overridepublic String toString() {return super.toString()+"(" + number + ","+ decription + ")";}
}
答案:
enum Week{MONDAY(1,"星期一"),TUESDAY(2,"星期二"),WEDNESDAY(3,"星期三"),THURSDAY(4,"星期四"),FRIDAY(5,"星期五"),SATURDAY(6,"星期六"),SUNDAY(7,"星期日");private int number;private String decription;private Week(int number, String decription) {this.number = number;this.decription = decription;}public static Week getByNumber(int number){switch(number){case 1:return MONDAY;case 2:return TUESDAY;case 3:return WEDNESDAY;case 4:return THURSDAY;case 5:return FRIDAY;case 6:return SATURDAY;case 7:return SUNDAY;default:return null;}}@Overridepublic String toString() {return super.toString()+"(" + number + ","+ decription + ")";}
}
11)写一段代码实现在遍历ArrayList时移除一个元素,例如:”java”?
import java.util.ArrayList;
import java.util.Iterator;public class Test {public static void main(String[] args) {ArrayList<String> list = new ArrayList<String>();list.add("hello");list.add("java");list.add("world");补充代码 }
}
//答案:
import java.util.ArrayList;
import java.util.Iterator;public class Test {public static void main(String[] args) {ArrayList<String> list = new ArrayList<String>();list.add("hello");list.add("java");list.add("world");Iterator<String> iterator = list.iterator();while (iterator.hasNext()) {String next = iterator.next();if ("java".equals(next)) {iterator.remove();}}}
}
三、基础简答题
1)break、continue、return的区别?
break用于switch和循环,用于结束switch,和当前循环
continue用于循环,用于结束本次循环
return用于结束当前方法,还可以用于return 返回值;返回结果
2)请解释String、StringBuilder、StringBuffer的区别?
String是不可变的字符序列,因此字符串常量存储在常量池中,而StringBuilder和StringBuffer是可变的字符序列。
String对象是常量对象,因此一旦拼接和修改就会产生新的String对象。
SringBuffer和StringBuilder可以在原对象上进行append,insert,delete,replace等修改。
StringBuilder和StringBuffer是完全兼容的API,但是StringBuilder是线程不安全的、StringBuffer是线程安全的。
3)如下关于String比较的代码的运行结果是什么?
public static void main(String[] args) { String str1 = "1"; String str2 = "2"; String str3 = new String("1"); final String str4 = "2"; final String str5 = new String("2"); String str6 = "12";
String str7 = "1" + "2"; String str8 = str1 + "2"; String str9 = str1 + str2; String str10 = str3 + str4; String str11 = "1" + str4; String str12 = "1" + str5; String str13 = (str1 + str2).intern();
System.out.println("(1)"+ (str1 == str3));//false System.out.println("(2)"+ (str2 == str4));//true System.out.println("(3)"+ (str4 == str5));//false System.out.println("(4)"+ (str6 == str7));//true System.out.println("(5)"+ (str6 == str8));//false System.out.println("(6)"+ (str6 == str9));//true System.out.println("(7)"+ (str6 == str10));//false System.out.println("(8)"+ (str6 == str11));//false System.out.println("(9)"+ (str6 == str12)); System.out.println("(10)"+ (str6 == str13));//true } |
答案:一个0.5分 (1)false (2)true (3)false (4)true (5)false (6)false (7)false (8)true (9)false (10)true |
4)请解释Collection 和 Collections 的区别?List、Set、Map是否继承Collection
Collection是接口,是List和Set系列接口的父接口。是Collection系列接口的根接口。
Collections是工具类,其中提供了很多静态方法来操作各种集合。
List和Set实现Collection,Map不实现Collection。
5)List、Map、Set 三个接口,存取元素时,各有什么特点?
List:是有序的,可重复的,添加元素的方法是add,可以根据索引获取元素。
Set:是无序的,不可重复的,添加元素的方式是add,HashSet和LinkedHashSet的元素是依据hashCode和equals区别元素是否相等,而TreeSet是依据compareTo或compare区别元素是否相等。
Map:是存储键值对的,添加的方法是put(key,value),可以根据key获取value。
6)Hashtable与HashMap的区别?如何解决那个线程不安全的问题?
Hashtable是线程安全的哈希表,底层结构是数组+链表。方法synchronized的,
HashMap是线程不安全的哈希表,底层结构是JDK1.7时数组+链表,JDK1.8时数组+链表/红黑树。 Null null
HashMap的线程安全问题可以使用Collections的synchronizedMap(Map<K,V> m) 方法解决。
7)列出一些常见的异常或错误类型(至少五个)
运行时异常:
数组下标越界异常:ArrayIndexOutOfBoundsException
类型转换异常:ClassCastException
算术异常:ArithmeticException
空指针异常:NullPointerException
编译时异常:
IO操作异常:IOException
文件找不到异常:FileNotFoundException
已到达文件流末尾异常:EOFException
类找不到异常:ClassNotFoundException
没有对应的方法异常:NoSuchMethodException
错误:
堆内存溢出:OutOfMemoryError
栈内存溢出:StackOverflowError
8)访问修饰符的作用范围由大到小,及各自的范围是什么?可以修饰什么?
9)请解释Overload与Override的区别?
Overload是方法重载,指的是在同一个类中,方法名称相同,形参列表不同的两个或者多个方法,和返回值类型无关。
Override是方法的重写,指的是子类在继承父类时,当父类的方法体不适用于子类时,子类可重写父类的方法。重写必须遵守方法名和形参列表与父类的被重写的方法相同,而返回值类型可以小于等于父类被重写的方法(如果是基本数据类型和void必须相同),权限修饰符可以大于等于父类被重写的方法,抛出的异常列表可以小于等于父类被重写的方法。
10)Java反射机制的作用
反射就是动态加载对象,并对对象进行剖析。Java反射机制的作用:
(1)在运行时创建任意类型的对象
(2)在运行时获取任意类型的信息
(3)在运行时获取和设置任意属性值
(4)在运行时调用任意对象的方法
11)ArrayList和LinkedList的底层实现(存储结构、扩容机制)
1.ArrayList是实现了基于动态数组的数据结构,LinkedList基于链表的数据结构。
2.对于随机访问get和set,ArrayList觉得优于LinkedList,因为LinkedList要移动指针。
3.对于新增和删除操作add和remove,LinedList比较占优势,因为ArrayList要移动数据。 这一点要看实际情况的。若只对单条数据插入或删除,ArrayList的速度反而优于LinkedList。但若是批量随机的插入删除数据,LinkedList的速度大大优于ArrayList. 因为ArrayList每插入一条数据,要移动插入点及之后的所有数据。
12)Java中的IO流的四大基类是什么(2分),请列出常用的IO流类型(至少5个)(3分)
所有的IO流都是从以下四个抽象基类,超级父类中分出来的:
(1)字节输入流:InputStream
(2)字节输出流:OutputStream
(3)字符输入流:Reader
(4)字符输出流:Writer
可以延伸出很多IO流,例如:和文件相关
(1)文件字节输入流:FileInputStream
(2)文件字节输出流:FileOutputStream
(3)文件字符输入流:FileReader
(4)文件字符输出流:FileWriter
例如:缓冲流
(1)字节输入缓冲流:BufferedInputStream
(2)字节输出缓冲流:BufferedOutputStream
(3)字符输入缓冲流:BufferedReader
(4)字符输出缓冲流:BufferedWriter
例如:转换流
(1)InputStreamReader:把字节输入流转为字符输入流,解码
(2)OutputStreamWriter:把字符输出流转为字节输出流,编码
例如:数据流
(1)字节输入数据流:DataInputStream
(2)字节输出数据流:DataOutputStream
例如:对象流
(1)对象输入流:ObjectInputStream,用于对象的序列化
(2)对象输出流:ObjectOutputStream,用于对象的反序列化
例如:打印流
(1)字节打印流:PrintStream
(2)字符打印流:PrintWriter
13) 如何获取Class的对象?4种方式
获取Class对象的四种方式:
(1)类型名.class
(2)对象.getClass()
(3)Class.forName("类型的全名称")
(4)ClassLoader对象.loadClass("类型的全名称")
14)编写多线程程序有几种实现方式?
JavaSE阶段考试答出两种即对: 1、继承Thread类,可以直接调用start()启动,有单继承限制,共享数据时需要使用static方式,只能选择当前类.class对象或其他共享对象当锁。 2、实现Runnable接口,必须借助Thread对象的start()启动,实现接口可以解决单继承限制问题,需要共享数据时,共享同一个Runnable对象即可,线程安全锁可以直接选择this对象。 |
企业面试阶段答案一如下: 1、继承Thread类,可以直接调用start()启动,有单继承的限制。 2、实现Runnable接口,必须借助Thread对象的start()启动,实现接口可以解决单继承限制问题。 3、使用ExecutorService、Callable、Future实现有返回结果的多线程 |
企业面试阶段答案二如下: Java多线程实现方式主要有四种:继承Thread类、实现Runnable接口、实现Callable接口通过FutureTask包装器来创建Thread线程、使用ExecutorService、Callable、Future实现有返回结果的多线程。 其中前两种方式线程执行完后都没有返回值,后两种是带返回值的。 |
15)请列出一些常用的类、接口、包,各至少5个
注意答案不固定
常用类:String,Math,,ArrayList,HashMap,System
常用接口:Comparable,Comparator,Runnable,Serializable,Collection
常用包:java.lang, java.util,java.io,java.net,java.text,java.lang.reflect
16)对public static void main(String[] args)的每一个单词做解释?
public:公共的,用它修改的类或成员在任意位置可见
static:静态的,用它修改的方法,可以不用创建对象就可以调用
void:表示该方法没有返回值
main:Java的主方法名,JavaSE的程序入口
String[]:字符串数组,这是main方法的形参类型,可以通过命令行参数传值
args:这是main方法的形参名,如果要在main中使用命令行参数,可以遍历该args数组。
17)关键字class、interface、enum的区别?
class:
声明类
interface:
声明接口
@interface:声明注解(这个可选)
enum:
声明枚举类
18)面向对象的基本特征有哪些?并作出解释
答出三个基本特征给3分
面向对象的基本特征有:
(1)封装:封装的好处就是安全,方便。封装隐藏了对象的具体实现,当要操纵对象时,只需调用其中的方法,而不用管方法的具体实现。属性的封装就是属性私有化并提供get/set方法,这样外界只能通过get/set方法来操作属性,行为变得可控。
(2)继承:继承的好处就是代码的复用和扩展。继承可以保留父类的属性和方法,同时子类又可以扩展自己的属性和方法。
(3)多态:目的是实现代码的灵活性,多态体现在重载和重写方法,更多的时候指的是对象的多态性,即当父类的变量指向子类的对象时,那么调用子类重写的方法时,运行的是子类重写过的代码,从而实现同一个父类的变量,因为赋值的子类对象不同而体现出不同的功能。应用主要体现在多态参数和多态数组中
19)java.lang.Comparable与java.util.Comparator有什么区别?
20)请解释Java异常处理机制相关的5个关键字
try:尝试执行可能发生异常的代码。
catch:尝试捕获try部分发生的异常。可以存在多个catch,如果多个catch的异常类型有继承关系,那么遵循子上父下。
finally:不管是否发生异常都要执行的代码放在finally块中。
throws:方法声明时显示抛出异常,指定该方法可能抛出的异常类型列表。
throw:手动抛出异常,可以抛出系统预定异常,也可以抛出用户自定异常,而且用户自定义异常必须用throw语句抛出,可以代替return语句结束方法运行。
21)InputStream里的read()返回的是什么值,read(byte[] data)是什么意思,返回的是什么值。Reader里的read()返回的是什么值,read(char[] data)是什么意思,返回的是什么值。如果想要一次读取一行怎么办?
InputStream:
read()方法,返回的是所读取的字节的int型(范围0-255)
read(byte[] data)将读取的字节储存在这个数组,返回的是实际读取的字节数。
Reader:
read()方法,返回的是所读取的字符的int型(范围0-65535)
read(char[] data)将读取的字符存储在这个数组中,返回的是实际读取的字符数。
如何读取一行:
BufferedReader类中有readLine()方法。Scanner类中也有nextLine()方法。
22)sleep() 和 wait() 有什么区别?
sleep和wait都会导致当前线程进入阻塞状态,被挂起。
sleep不释放锁,睡眠时间到自动醒来,回到就绪状态
wait是会释放锁,要通过notify()或notifyAll()唤醒,回到就绪状态
sleep是在Thread类中声明的一个静态方法,Thread.sleep(毫秒)
wait是在Object类中声明的非静态的方法,必须锁对象调用
23)final 在 java 中有什么作用?
(1)用来修饰一个引用
如果引用为基本数据类型,则该引用为常量,该值无法修改;
如果引用为引用数据类型,比如对象、数组,则该对象、数组本身可以修改,但指向该对象或数组的地址的引用不能修改。
如果引用时类的成员变量,则必须当场赋值,否则编译会报错。
(2)用来修饰一个方法
当使用final修饰方法时,这个方法将成为最终方法,无法被子类重写。但是,该方法仍然可以被继承。
(3)用来修饰类
当用final修改类时,该类成为最终类,无法被继承。
比如常用的String类就是最终类。
24)final、finally、finalize的区别?
final:修饰符
final修饰类,表示不能被继承
final修饰方法,表示不能被重写
final修饰变量,表示不能修改值
finally:
和try...catch结构一起使用,
表示无论是否有异常,是否可以捕获异常,是否有return语句,都要执行的finally块。
finalize:
finalize是Object类的一个方法,由GC调用,在对象被回收时调用,适用于释放JVM之外的内存。
25)对Java 的基本数据类型与包装类做解释?
Java的八种基本数据类型与包装类:
byte <--> Byte
short <-->Short
int <--> Integer
long <--> Long
float <--> Float
double <--> Double
char <--> Character
boolean <--> Boolean
八种基本数据类型只与自己的包装类之间进行装箱与拆箱。JDK1.5之后支持自动装箱与自动拆箱。
26)什么是基本数据的自动类型转换和强制类型转换?
当把数据类型小的数据赋值给数据类型大的变量时,就会发生自动类型提升。
byte->short->int->long->float->double
char->
当byte、short、char三个类型在计算时,就会自动升级为int。当数据类型小的数据与数据类型大的数据混合计算时,数据类型小的数据会自动类型提升。
当把数据类型大的数据赋值给数据类型小的变量时,就要强制类型转换。
double->float->long->int->short->byte
->char
当希望某个数据类型小的数据按照某个大的类型计算时,也可以使用强制类型转换。
27)向上转型和向下转型?
向上转型:
把子类对象赋值给父类的变量。
把实现类的对象赋值给父接口的变量。
向下转型:
把父类变量赋值给子类的变量。
可能发生ClassCastException,最好向下转型之前加instanceof判断
28)int,Integer,BigInteger的区别?
int:基本数据类型
Integer:包装类
BigInteger:任意大小的整数
29)Java异常的处理过程?
Java的异常处理过程如下:
(1)当程序运行到某一句代码,如果发生了异常(可能是JVM判定的异常,也可能是遇到throw的),程序都会停下来,然后把异常信息封装到异常的对象中,并且“抛”出
(2)JVM会检测在这段程序代码的外围,是否有try...catch,如果有try...catch,就判断是否有catch可以捕获它,如果捕获了,程序就进入对应的catch块进行异常处理,处理后程序继续运行try..cath之后的代码。
(3)JVM会检测在这段程序代码的外围,根本就没有try...catch或者是有try...catch但是捕获不住,即类型对不上,JVM都会把这个异常对象抛出“上级,方法的调用者”
(4)上级一旦接到异常对象,处理过程还是1,2,3
(5)如果一直抛,一路上都没有可以捕获它,程序就崩溃了。
30)阐述什么是线程安全问题?怎么解决?
JavaSE阶段的答案:
当满足以下条件时,会出现线程安全问题:
(1)有多个线程
(2)使用共享数据
(3)有多句代码操作共享数据
如何解决?同步,即加锁
31)String 类的常用方法都有那些?
(1)常见String类的获取功能
length:获取字符串长度;
charAt(int index):获取指定索引位置的字符;
indexOf(int ch):返回指定字符在此字符串中第一次出现处的索引;
substring(int start):从指定位置开始截取字符串,默认到末尾;
substring(int start,int end):从指定位置开始到指定位置结束截取字符串;
(2)常见String类的判断功能
equals(Object obj): 比较字符串的内容是否相同,区分大小写;
contains(String str): 判断字符串中是否包含传递进来的字符串;
startsWith(String str): 判断字符串是否以传递进来的字符串开头;
endsWith(String str): 判断字符串是否以传递进来的字符串结尾;
isEmpty(): 判断字符串的内容是否为空串"";
(3)常见String类的转换功能
byte[] getBytes(): 把字符串转换为字节数组;
char[] toCharArray(): 把字符串转换为字符数组;
String valueOf(char[] chs): 把字符数组转成字符串。valueOf可以将任意类型转为字符串;
toLowerCase(): 把字符串转成小写;
toUpperCase(): 把字符串转成大写;
concat(String str): 把字符串拼接;
(4)常见String类的其他常用功能
replace(char old,char new) 将指定字符进行互换
replace(String old,String new) 将指定字符串进行互换
trim() 去除两端空格
int compareTo(String str) 会对照ASCII 码表 从第一个字母进行减法运算 返回的就是这个减法的结果,如果前面几个字母一样会根据两个字符串的长度进行减法运算返回的就是这个减法的结果,如果连个字符串一摸一样 返回的就是0。
32)Java的自增、自减运算符在自增变量前后有什么区别?
首先,
自增运算符++,表示自增变量自增1,
自减运算符--,表示自增变量自减1。
其次,以自增为例
(1)如果自增表达式直接加;构成语句,自增运算符在自增变量前后没有区别
a++; 和 ++a; 没区别
(2)如果自增表达式 和其他运算符一起运算,或者自增表达式作为实参使用时,则有区别。
自增运算符在前:表示先自增,再取自增变量的值运算,
自增运算符在后:表示先取自增变量的值,然后自增变量再自增1,计算用的是自增之前取的值。
33)普通类和抽象类有哪些区别?
抽象类不能被实例化;
抽象类可以有抽象方法,只需申明,无须实现;
有抽象方法的类一定是抽象类;
抽象类的子类必须实现抽象类中的所有抽象方法,否则子类仍然是抽象类;
抽象方法不能声明为静态、不能被static、final修饰。
四、简答题进阶
1)Java虚拟机中内存分为哪些区域?每个区域的作用?哪些区域是线程共享的?
1、程序计数器(寄存器):当前线程所执行的字节码行号指示器
2、本地方法栈:同虚拟机栈,只不过本地方法栈为虚拟机使用到的native方法服务。
3、虚拟机栈:每个方法在执行的同时都会创建一个栈帧用来存放存储局部变量表、操作数表、动态连接、方法出口等信息,每一个方法从调用直至执行完成的过程,就对应着一个栈帧在虚拟机栈中入栈到出栈的过程。
4、堆:所有线程共享的一块内存区域。Java虚拟机所管理的内存中最大的一块,因为该内存区域的唯一目的就是存放对象实例。几乎所有的对象实例度在这里分配内存,也就是通常我们说的new对象,同时堆也是垃圾收集器管理的主要区域。
5、方法区:和堆一样,是各个线程共享的内存区域,用于存储已被虚拟机加载的类信息、常量、静态变量、和编译器即时编译后的代码等
2)请解释抽象类与接口的区别
3)TCP和UDP协议有什么区别?
TCP:面向连接的可靠的基于字节流的传输控制协议
UDP:非面向连接的不可靠的基于用户数据报的协议
4)HashMap的底层实现及扩容机制?
简单回答:
HashMap在JDK1.8之前:底层实现是数组+链表,扩容机制是当table中元素的个数已经达到阈值(table.length*0.75)时并且新添加[index]桶已经是非空,那么table.length需要扩容为2倍。
HashMap在JDK1.8之后:底层实现是数组+链表/红黑树,扩容机制(1)是当table中元素的个数已经达到阈值(table.length*0.75)时,那么table需要扩容为2倍。(2)当添加到[index]下时,发现[index]下的链表结点个数已经达到8个,而table的长度未达到64,此时table.length也会扩容为2倍。
当table[index]下的结点个数达到8个但是table.length已经达到64时会树化,因为当table[index]下的结点个数超过8个后,查询效率就低下了,修改为红黑树的话,可以提高查询效率。
5)Hashtable和HashMap、TreeMap的底层结构
Hashtable:
数组+链表
HashMap:
JDK1.8之前:数组+链表
JDK1.8及之后:数组+链表/红黑树
TreeMap:
红黑树
6)哈希表要用链表或红黑树?
为了解决hash和[index]冲突问题
(1)两个不相同的key的hashCode值本身可能相同
(2)两个不相同的key的hashCode值不同,但是经过hash()运算,结果相同
(3)两个hashCode不相同的key,经过hash()运算,结果也不相同,但是通过 hash & table.length-1运算得到的[index]可能相同
那么意味着table[index]下可能需要存储多个Entry的映射关系对象,所以需要链表或红黑树
7)运行时异常与编译时异常有何异同?请列举一些运行时异常和编译时异常的类型。
运行时异常是非受检异常,是RuntimeException的子类,即编译器无法检测,因此也不会强制要求程序员处理。 编译时异常是受检异常,编译器检测到代码抛出编译时异常时,会要求程序员必须对该异常做处理(throws或try...catch)否则,编译不通过。 |
运行时异常: 数组下标越界异常:ArrayIndexOutOfBoundsException 类型转换异常:ClassCastException 算术异常:ArithmeticException 空指针异常:NullPointerException 编译时异常: IO操作异常:IOException 文件找不到异常:FileNotFoundException 已到达文件流末尾异常:EOFException 类找不到异常:ClassNotFoundException 没有对应的方法异常:NoSuchMethodException |
8)Object类中有哪些常用的方法?
(1)protected Object clone()--->创建并返回此对象的一个副本。
(2)boolean equals(Object obj)--->指示某个其他对象是否与此对象“相等”。
(3)protected void finalize()--->当垃圾回收器确定不存在对该对象的更多引用时,由对象的垃圾回收器调用此方法。
(4)Class<? extendsObject> getClass()--->返回一个对象的运行时类型。
(5)int hashCode()--->返回该对象的哈希码值。
(6)void notify()--->唤醒在此对象监视器上等待的单个线程。
(7)void notifyAll()--->唤醒在此对象监视器上等待的所有线程。
(8)String toString()--->返回该对象的字符串表示。
(9)void wait()--->导致当前的线程等待,直到其他线程调用此对象的 notify() 方法或 notifyAll() 方法。
void wait(long timeout)--->导致当前的线程等待,直到其他线程调用此对象的 notify() 方法或 notifyAll()方法,或者超过指定的时间量。
void wait(long timeout, int nanos)--->导致当前的线程等待,直到其他线程调用此对象的 notify()
9)如何实现序列化,有什么意义?
如何实现序列化(5分):
(1)实现Serializable接口或Externalizable接口,并且视情况而定指定一个序列化版本ID(serialVersionUID)值;而且要保留公共的无参构造。
(2)如果某个对象的属性也是引用数据类型,那么该数据类型也要实现Serializable接口或Externalizable接口;
(3)如果要序列化,则使用一个输出流来构造一个对象输出流ObjectOutputStream并通过writeObject(Object obj)方法就可以将实现对象写出(即保存其状态);如果需要反序列化则可以用一个输入流建立对象输入流ObjectInputStream,然后通过readObject方法从流中读取对象。
(4)如果某些属性不参与序列化,如果是实现Serializable接口的,直接在属性前面加transient修饰,注意:static修饰的属性也不会被序列化,如果是实现Externalizable接口,那么只要在重写writeExternal()和readExternal()方法时,不处理该属性即可。
10)Object类中equals方法的实现是什么?重写一个equals方法有什么注意事项?
Object类中的equals方法,对于任何非空引用值 x 和 y,当且仅当 x 和 y 引用同一个对象时,此方法才返回 true(x == y 具有值 true)。 |
在重写equals方法时,要注意满足离散数学上的特性 (1)自反性:对任意引用值x,x.equals(x)的返回值一定为true. (2)对称性:对于任何引用值x,y,当且仅当y.equals(x)返回值为true时,x.equals(y)的返回值一定为true; (3)传递性:如果x.equals(y)=true, y.equals(z)=true,则x.equals(z)=true (4)一致性:如果参与比较的对象没任何改变,则对象比较的结果也不应该有任何改变 (5)非空性:任何非空的引用值x,x.equals(null)的返回值一定为false 注意:当此方法被重写时,通常有必要重写 hashCode 方法,以维护 hashCode 方法的常规协定,该协定声明:
两个对象的哈希码相等,那么equals结果可能相等也可能不相等 |
11)HashMap的相关常量
DEFAULT_LOAD_FACTOR:默认加载因子,值为0.75
TREEIFY_THRESHOLD:链表树化阈值,值为8
MIN_TREEIFY_CAPACITY:最小树化容量,值为64
UNTREEIFY_THRESHOLD:反树化阈值,值为6
12)synchronized关键字的用法?
synchronized关键字是解决线程安全问题的方式之一。共有两种用法:
1、同步代码块
语法格式:
synchronized(锁对象){
需要加锁的代码
}
注意锁:
(1)任意类型的对象都可以当做锁
(2)多个线程之间共用一把锁,即多个线程之间共用同一个锁对象
(3)同步代码块的范围:不能太大,太小
2、同步方法
语法结构:
synchronized 【修饰符】 返回值类型 方法名(【形参列表】)【抛出异常列表】
同步方法的锁对象:
静态方法:当前类的Class对象,即当前类名.class
非静态方法:当前对象this(需要谨慎,确保是同一个this)
13)为什么我们调用 start() 方法时会执行 run() 方法,为什么我们不能直接调用 run() 方法?
这是另一个非常经典的 java 多线程面试问题,而且在面试中会经常被问到。很简单,但是很多人都会答不上来!
new 一个 Thread,线程进入了新建状态。调用 start() 方法,会启动一个线程并使线程进入了就绪状态,当分配到时间片后就可以开始运行了。 start() 会执行线程的相应准备工作,然后自动执行 run() 方法的内容,这是真正的多线程工作。
而直接执行 run() 方法,会把 run 方法当成一个 main 线程下的普通方法去执行,并不会在某个线程中执行它,所以这并不是多线程工作。
总结: 调用 start 方法方可启动线程并使线程进入就绪状态,而 run 方法只是 thread 的一个普通方法调用,还是在主线程里执行。
14)集合跟数组的区别?
数组是固定长度的;集合可变长度的。
数组可以存储基本数据类型,也可以存储引用数据类型;集合只能存储引用数据类型。
数组存储的元素必须是同一个数据类型;集合存储的对象可以是不同数据类型。
五、编程题进阶
1)判断101~200之间有多少个素数,并输出所有素数
public static void main(String[] args) {System.out.println("101-200之间的素数有:");for (int i = 101; i <= 200; i++) {boolean flag = true;for (int j = 2; j < i; j++) {if (i % j == 0) {flag = false;break;}}if (flag) {System.out.println(i);}}}
2)消除下面集合中重复元素?
import java.util.Arrays;
import java.util.HashSet;
import java.util.List;public class Test {public static void main(String[] args) {List<Integer> list = Arrays.asList(1, 2, 3, 3, 4, 4, 5, 5, 6, 1, 9, 3, 25, 4);HashSet<Integer> set = new HashSet<Integer>();set.addAll(list);for (Integer integer : set) {System.out.println(integer);}}
}
3)问题:某班30个学生的学号为20070301-20070330,,给出所有同学的成绩(可用随机数产生,范围60-100),请编写程序将本班各位同学的成绩按照从低到高排序打印输出,如果成绩相同,则按照学号升序排列。
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.TreeMap;public class Test2{public static void main(String[] args){/* 此处用ArrayList实现* * ArrayList<Student>al=new ArrayList<Student>();for(int i=20070301,j=10;i<=20070330;i++,j++){al.add(new Student(i,(int) (40*Math.random()+60), "同学"+j));}//ArrayList排序借助Collections中的sort()方法实现。Collections.sort(al, new Sortbygrade());for(Student sd:al)System.out.println(sd);*/LinkedList<Student> lt=new LinkedList<Student>();for(int i=20070301,j=10;i<=20070330;i++,j++){lt.add(new Student(i,(int) (40*Math.random()+60), "同学"+j));}//对链表排序Collections.sort(lt, new Sortbygrade());//输出链表for(Student sd:lt)System.out.println(sd);}}//学生类
class Student{private Integer num,grade;private String name;public Integer getNum() {return num;}public void setNum(Integer num) {this.num = num;}public Integer getGrade() {return grade;}public void setGrade(Integer grade) {this.grade = grade;}public String getName() {return name;}public void setName(String name) {this.name = name;}//构造函数public Student(Integer num,int grade,String name){this.num=num;this.name=name;this.grade=grade;}//此处必须覆写public String toString(){
// System.out.println("hi");return "学号:"+this.num+"\t"+"姓名:"+this.name+" "+"成绩:"+this.grade;}}//创建一个比较器类
class Sortbygrade implements Comparator<Student>{@Overridepublic int compare(Student s1, Student s2) {if(s1.getGrade()>s2.getGrade())return 1;if(s1.getGrade()<s2.getGrade())return -1;if(s1.getGrade()==s2.getGrade())return s1.getNum().compareTo(s2.getNum());return 0; }}
4)有一个字符串,其中包含中文字符、英文字符和数字字符,请统计和打印出各个字符的字数。
举例说明: String content = “中中国55kkfff”;
统计出:
中:2
国:1
5:2
k:2
f:3
public static void main(String[] args) {String content = "中中国55kkfff";HashMap<Character, Integer> map = new HashMap<Character, Integer>();while (content.length() > 0) {Character c = content.charAt(0);content = content.substring(1);Integer count = map.get(c);if (count == null) {map.put(c, 1);} else {map.put(c, count + 1);}}Set<Entry<Character, Integer>> entrySet = map.entrySet();for (Entry<Character, Integer> entry : entrySet) {System.out.println(entry);}}
5)请使用二分查找算法查找字符数组{“a”,”b”,”c”,”d”,”e”,”f”,”g”,”h”}中”g”元素的位置?
public static void main(String[] args) {char[] arr = { 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h' };char findValue = 'g';int findIndex = -1;int leftIndex = 0;// 最开始,左边的边界是0int midIndex = arr.length / 2;// 最开始的中间:arr.length/2int rightIndex = arr.length - 1;// 最开始,右边的边界是arr.length-1while (true) {if (arr[midIndex] == findValue) {findIndex = midIndex;break;} else {// 判断是否已经到达边界,如果是就结束查找过程// 如果不是,继续往左边或右边查找if (midIndex == 0 || midIndex == arr.length - 1) {break;}// 判断是往左还是往右if (findValue < arr[midIndex]) {// 往左边查找rightIndex = midIndex;midIndex = leftIndex + (rightIndex - leftIndex) / 2;} else {// 往右边查找leftIndex = midIndex;midIndex = leftIndex + (rightIndex + 1 - leftIndex) / 2;}}}if (findIndex == -1) {System.out.println(findValue + "在数组中不存在");} else {System.out.println(findValue + "在数组中的位置就是" + findIndex);}}
6) 题目描述:统计1~100之间出现了几次数字9
public class Exercise {public static void main(String[] args) {int count = 0;//记录9的个数for (int i = 1; i <= 100 ; i++) {if (i % 10 == 9) {//看个位是不是9count++;}else if (i / 10 == 9) {//看十位是不是9count++;}}System.out.println(count);}
}
7)第一个人10,第2个比第1个人大2岁,以此类推,请用递归方式计算出第8个人多大?
public static void main(String[] args) {int count = 8;int age = getAge(count);System.out.println("第" + count +"个人的年龄:" + age);}public static int getAge(int count){if(count == 1){return 10;}else{return getAge(count-1) + 2;}}
六、附加题
1.编写代码完成如下功能
public static String replace(String text, String target, String replace){
....
}
1). 示例:replace(“aabbccbb”, “bb”, “dd”); 结果:aaddccdd
注意:不能使用String及StringBuffer等类的replace等现成的替换API方法。
public class Test01 {public static void main(String[] args) {String str = "aabbccbb";String target = "bb";String replacement = "dd";String replace = replace(str,target,replacement);System.out.println("结果为:"+replace); }public static String replace(String str, String target, String replacement) {// 通常情况这里需要对str,target,replacement做输入校验,这里省略了, 比如str比target短的时候可以直接返回空字符串StringBuilder res = new StringBuilder();for (int i = 0; i < str.length(); ) {if (isMatch(str, i, target)) {i += target.length(); // 如果匹配,需要直接向前跳target.lengthres.append(replacement);continue;}res.append(str.charAt(i++));}return res.toString();}// 单纯确认从str的pos位置开始,是否和target相匹配private static boolean isMatch(String str, int pos, String target) {for (int i = 0; i < target.length() && i + pos < str.length(); i++) {if (str.charAt(i + pos) != target.charAt(i)) {return false;}}return true;}
}
2)1个字符串中可能包含a-z中的多个字符,字符也可能重复,例如:String data = “aabcexmkduyruieiopxzkkkkasdfjxjdsds”;写一个程序,对于给定一个这样的字符串求出字符串出现次数最多的那个字母以及出现的次数(若次数最多的字母有多个,则全部求出)
【第一种】
package com.ignorance;import java.util.*;
import java.util.stream.Collectors;public class Statistics {public static void main(String[] args) {Map<String,Object> returnMap = progress("aaabbccddeeeffgg");System.out.println("最大的次数:" + returnMap.get("maxCount"));System.out.println("maxEleSet:" + returnMap.get("maxEleSet"));}public static Map<String,Object> progress(String resourceStr){char[] chars = resourceStr.toCharArray();Map<Character,Integer> calcMap = new TreeMap<>();for (char c : chars){if (!calcMap.containsKey(c)){calcMap.put(c,1);continue;}Integer prevCount = calcMap.get(c);calcMap.put(c,++prevCount);}Set<Map.Entry<Character,Integer>> resultSet = calcMap.entrySet().stream().filter(o -> compare(o,calcMap.values().stream().max(Integer::compareTo).get())).collect(Collectors.toSet());Integer maxCount = resultSet.stream().findFirst().get().getValue();Set<Character> maxEleSet = resultSet.stream().map(o -> o.getKey()).collect(Collectors.toSet());Map<String,Object> returnMap = new HashMap<>();returnMap.put("maxCount",maxCount);returnMap.put("maxEleSet",maxEleSet);return returnMap;}private static boolean compare(Map.Entry<Character,Integer> o,Integer maxCount){return Integer.compare(o.getValue(),maxCount) == 0;}
}
【第二种】
public static void stringssss() {String data = "aaaaaaaaaaabcexmkduyruieiopxzkkkkasdfjxjdsdsccccczzzzz";char[] chars = data.toCharArray();List list = new ArrayList();Set<String> set = new TreeSet();for (char aChar : chars) {list.add(aChar);set.add(String.valueOf(aChar));}System.out.println("set=" + set);Collections.sort(list);System.out.println("list=" + list);StringBuilder stringBuilder = new StringBuilder();for (Object o : list) {stringBuilder.append(o);}String s = stringBuilder.toString();System.out.println("s=" + s);List listMax = new ArrayList<>();int max = 0;String maxString = "";for (String o : set) {int start = s.indexOf(o);int end = s.lastIndexOf(o);int count = end - start + 1;if (count > max) {listMax.clear();max = count;maxString = o;listMax.add(o);} else if (count == max) {listMax.add(o);}}int index = 0;for (int i = 0; i < listMax.size(); i++) {if (maxString.equals(listMax.get(i))) {index = i;}}for (int i = index; i < listMax.size(); i++) {System.out.println("maxAll=" + listMax.get(i));}System.out.println("max=" + max);System.out.println("listMax=" + listMax);// System.out.println("count="+count);}
2. 找出数组中一个值,使其左侧值的加和等于右侧值的加和,例如:1,2,5,3,2,4,2,结果为:第4个值
public class Test06 {public static void main(String[] args) {int[] arr = {1, 2, 5, 3, 2, 4, 2};int i = stuFind(arr);System.out.println(i);}public static int stuFind(int[] array) {for (int i = 1; i < array.length; i++) {int totalLeft = 0;for (int le = 0; le < i; le++) {totalLeft += array[le];}int totalRight = 0;for (int ri = i + 1; ri < array.length; ri++) {totalRight += array[ri];}if (totalLeft == totalRight) {return i;}}return -1;}
}
3.写一个排序算法1-100随机数字,进行排序,要求效率(例如:冒泡、选择、快排.....等)
public class Test08 {public static void main(String[] args) {int[] num = new int[100];int[] arr = new int[100];for(int i=0;i<num.length;i++){num[i] = i+1;}select(num,arr);System.out.println("数组排序前顺序:");for(int i=0;i<arr.length;i++){if(i % 10 == 0 && i > 0){System.out.println();}System.out.print(arr[i]+"\t");}int lower = 0;int upper = arr.length-1;quickSort(arr,lower,upper);System.out.println();System.out.println("数组排序后顺序:");for(int i=0;i<arr.length;i++){if(i % 10 == 0 && i > 0){System.out.println();}System.out.print(arr[i]+"\t");}}private static void select(int[] num, int[] arr) {for(int i=0;i<arr.length;i++){while (true) {int index = (int) (Math.random()*num.length);if(num[index] != 0){arr[i] = num[index];num[index] = 0;break;}}}}private static void quickSort(int[] arr, int lower, int upper) {if(lower < upper){int middle = getMiddle(arr,lower,upper);quickSort(arr, lower, middle);quickSort(arr, middle+1, upper);}}private static int getMiddle(int[] arr, int lower, int upper) {while (lower < upper) {while (lower < upper && arr[lower] <= arr[upper]) {upper--;}if(lower < upper){int temp = arr[lower];arr[lower] = arr[upper];arr[upper] = temp;}while (lower < upper && arr[lower] <= arr[upper]) {lower++;}if(lower < upper){int temp = arr[lower];arr[lower] = arr[upper];arr[upper] = temp;}}return lower;}
}
4. 题目描述:统计十个同学的最高分,最低分以及平均分。
import java.util.Scanner;
public class Exercise {public static void main(String[] args) {double mean = 0.0;//平均值double sum = 0.0;//求和double[] score = {77.1, 88.1, 76.1, 56.1, 87.1, 98.1, 55.1, 94.1, 39.1, 96.1};double max = score[0];double min = score[0];//最低分//求和for (int i = 0; i <= score.length - 1 ; i++) {sum += score[i];//求数组元素值的和}for (int i = 1; i <= score.length - 1 ; i++) {if (score[i] > max) {//此时i下标大于此时的max,i下标的值就是此时的最高分max = score[i];}if (score[i] < min) {//此时i下标小于此时的max,i下标的值就是此时的最低分min = score[i];}}mean = sum / score.length;//计算平均数System.out.println(max);System.out.println(min);System.out.println(mean);}
}
5. 题目:有一个无序数组,要求对其进行排序并输出,现输入一个数,要求按原来的规律将它插入数组中。
import java.util.Scanner;
public class Prog30{public static void main(String[] args){int[] A = new int[]{0,8,7,5,9,1,2,4,3,12};int[] B = sort(A);print(B);System.out.println();System.out.print("请输入新插入的元素:");Scanner scan = new Scanner(System.in); int a = scan.nextInt();scan.close();int[] C = insert(a,B);print(C);}//选择排序private static int[] sort(int[] A){int[] B = new int[A.length];for(int i=0;i<A.length-1;i++){int min = A[i];for(int j=i+1;j<A.length;j++){if(min>A[j]){int temp = min;min = A[j];A[j] = temp;}B[i] = min;}}B[A.length-1] = A[A.length-1];return B;}//打印private static void print(int[] A){for(int i=0;i<A.length;i++)System.out.print(A[i]+" ");}//插入数字private static int[] insert(int a,int[] A){int[] B = new int[A.length+1];for(int i=A.length-1;i>0;i--)if(a>A[i]){B[i+1] = a;for(int j=0;j<=i;j++)B[j] = A[j];for(int k=i+2;k<B.length;k++)B[k] = A[k-1];break;}return B;}
}