您的位置 首页 java

菜鸟面试:就java基础知识而谈

基础也是 java 面试里最基本的考查~ 下面就以我遇到的较为常见的点来整理,比较零散,仅供参考。

1、switch……case

要注意case之间要用 break 来分隔,否则将会一直执行下去直到有break的地方:

Java代码

  1. public static void switch test (int i) {

  2. switch(i) {

  3. case 1:

  4. System.out.println(“============1”);

  5. break;

  6. case 2:

  7. System.out.println(“============2”);

  8. // break;

  9. case 3:

  10. System.out.println(“============3”);

  11. break;

  12. default:

  13. System.out.println(“==========more”);

  14. }

  15. }

case 2的时候,break是注释的,此时调用:

Java代码

  1. for(int i=0; i<5; i++) {

  2. switchTest(i);

  3. }

打印结果为:

==========more

============1

============2

============3

============3

==========more

default为所有case都不满足的时候走的逻辑;因为case 2的时候没有break,所以case 2的时候走完2的逻辑也会走case 3的逻辑。而如果把注释的break放开,打印结果将会是:

==========more

============1

============2

============3

==========more

注意:在jdk1.7+后,case里不仅支持整型,也支持 字符串 。当case判断条件为整型且为变量时,需注意该变量一定是final int的~

2、Java异常处理机制

1)异常的分类

Java中用Throwable类代表异常,而Throwable类会派生出 Exception 和Error两个子类。

Error(错误):是程序无法处理的错误,表示运行应用程序中较严重问题。大多数错误与代码编写者执行的操作无关,而表示代码运行时 JVM(Java 虚拟机)出现的问题;

Exception(异常):是程序本身可以处理的异常。

运行时异常:都是RuntimeException类及其子类异常,也称非检查异常,是指在编译期间,不检查这类异常是否捕获。如NullPointerException(空指针异常)、IndexOutOfBoundsException(下标越界异常)等,这些异常是不检查异常,程序中可以选择捕获处理,也可以不处理。这些异常一般是由程序逻辑错误引起的,程序应该从逻辑角度尽可能避免这类异常的发生。

运行时异常的特点是Java编译器不会检查它,也就是说,当程序中可能出现这类异常,即使没有用try-catch语句捕获它,也没有用throws子句声明抛出它,也会编译通过。

非运行时异常 (编译异常):是RuntimeException以外的异常,类型上都属于Exception类及其子类。从程序语法角度讲是必须进行处理的异常,如果不处理,程序就不能编译通过。如IOException、SQLException等以及用户自定义的Exception异常,一般情况下不自定义检查异常。

throw主动抛出异常;throws声明异常(在方法定义上),则调用此方法的地方必须捕获或者继续throws~

2)需要注意的点

2.1:如果一段代码用try{} catch(){} 包围起来,就算发生了异常,但catch后面的代码还是会执行;如果在for循环中,try catch把整个for都包起来,那么循环到某次发生异常时,整个循环就会中断;如果把try catch写在for里面包围每次循环的内容,那么本次如果发生异常将不会影响整个循环的继续进行。

2.2:try后面可以跟多个catch,最好在所有特殊异常最后写一个顶级的父类异常:Exception必须写在最后,其子类写在前面。当所有子类异常都没有catch到它时,就会进入Exception的分支。

2.3:当try catch finally遇上return

原则:任何执行try 或者catch中的return语句之前(无论try或catch里面有没有被return掉),都会执行finally语句,如果finally存在的话。 如果finally中有return语句,那么程序就以finally里的return为准,否则以try或catch里的return为准。

Java代码

  1. public static void main(String[] args) {

  2. System.out.println(“调用结果:” + test());

  3. }

  4. static int test()

  5. {

  6. int x = 1;

  7. try

  8. {

  9. x++;

  10. System.out.println(“x:” + x);

  11. System.out.println(x/0);

  12. return x;

  13. } catch(Exception e) {

  14. e.printStackTrace();

  15. return 0;

  16. }

  17. finally

  18. {

  19. ++x;

  20. System.out.println(“x:” + x);

  21. // return x;

  22. }

  23. }

打印结果为:

x:2

java.lang.ArithmeticException: / by zero

at com.nineclient.Test5.test(Test5.java:17)

at com.nineclient.Test5.main(Test5.java:6)

x:3

调用结果:0

而把finally的注释放开,结果为:

x:2

java.lang.ArithmeticException: / by zero

at com.nineclient.Test5.test(Test5.java:17)

at com.nineclient.Test5.main(Test5.java:6)

x:3

调用结果:3

说明以finally的return为准了。而如果这样:

Java代码

  1. static int test()

  2. {

  3. int x = 1;

  4. try

  5. {

  6. x++;

  7. System.out.println(“x:” + x);

  8. return x;

  9. } catch(Exception e) {

  10. e.printStackTrace();

  11. return 0;

  12. }

  13. finally

  14. {

  15. ++x;

  16. System.out.println(“x:” + x);

  17. }

  18. }

打印结果为:

x:2

x:3

调用结果:2

说明即时try里已经return了。finally里的代码还是会继续执行的~但是finally里的++x并不会影响最终return的值,虽然x此时变成3了,但是return的时候还是try里第一次x++后的值。

3、String

1)基本

java.lang.String类的实例用于封装一个字符序列,字符串对象为“不变对象”,一旦对字符串进行修改操作,会创建新的对象。Java中允许我们将一个字面量赋值给字符串引用类型变量,处于性能的考虑,Java对字面量产生的字符串进行了缓存,将他们缓存在字符串的常量池中,对于重复出现的字面量赋值,JVM会先查找常量池中是否存在这个字符串,悠久直接引用,减少字符串对象的创建,节省内存资源。

Java代码

  1. String s = new String(“abc”);//创建了2个对象,内容都是”abc”:一个在字符串常量池,一个在堆里。s只是对象的引用,下同

  2. String s1 = “abc”;//s1指向字符串常量池里内容为”abc”

  3. String s2 = new String(“abc”);//创建了1个对象,在堆里,内容指向堆里的”abc”

  4. String s3 = “abc”;//s3指向了字符串常量池里内容为”abc”,跟s1一样都指向池里的相同内容

  5. System.out.println(s == s1);// false

  6. System.out.println(s == s2);//false

  7. System.out.println(s1 == s2);//false

  8. System.out.println(s1 == s3);//true

  9. System.out.println();

  10. String o = “o”;

  11. String k = “k”;

  12. String ok = “ok”;

  13. System.out.println(ok == “o” + k);//false, “o”+k会在堆里新生成一个对象

  14. System.out.println(ok == “o” + “k”);//true, 都是在常量池里,相加也是返回池里的”ok”

2)String的封装类

StringBuilder和StringBuffer都是String的封装类,对于字符串的操作建议用这个

StringUtils.countMatch(String str, String subStr);//统计subStr在str里出现的次数

StringBuilder:线程非安全的

StringBuffer:线程安全的

Java代码

  1. String test = “Today” + ” is ” + ” sunny”;

  2. String test2 = “Today is sunny”;

  3. String t1 = “Today”;

  4. String t2 = ” is”;

  5. String t3 = ” sunny”;

  6. System.out.println(test == test2);//false

  7. System.out.println(test == (t1+t2+t3));//false

4、基本类型的包装类

数值型:整型—— byte(8位)<short(16位)<int(32位)<long(64位)(按所占字节数从小到大排列,数值范围-2n~2n-1 n为幂) 1字节=8位

浮点型: float (32位)<double(64位) 定义float类型时,如果值是非整数,则需加f后缀。可以将float类型的值赋给double型的变量,反之则不行~

文本型:char——字符常量为单引号括起来的单个字符

布尔型:boolean——true/false

Java代码

  1. public static void main(String[] args) {

  2. Integer a = 1;

  3. int b = 1;

  4. Integer c = 1;

  5. Integer d1 = new Integer(1);

  6. System.out.println(a == b);//true, a会自动”拆箱”变成int

  7. System.out.println(a ==c);//true

  8. System.out.println(a ==d1);//false,因为d1指向的是通过new出来的值

  9. //需注意:在通过valueOf方法创建Integer对象的时候,如果数值在[-128,127]之间,

  10. //便返回指向IntegerCache.cache中已经存在的对象的引用;否则创建一个新的Integer对象

  11. //所有整型都同理(Byte,Short,Long),有自己的cache范围~

  12. Integer a1 = 200;

  13. Integer b1 = 200;

  14. System.out.println(a1 == b1);//false

  15. System.out.println();

  16. //在某个范围内的整型数值的个数是有限的,而浮点数却不是。所以每次都会创建一个新的Float对象

  17. //所有浮点类型都同理(Double)

  18. Float f = 1.0f;

  19. float f1 = 1.0f;

  20. Float f2 = 1.0f;

  21. double d = 1.0;

  22. System.out.println(f == f1);//true

  23. System.out.println(f == f2);//false,两个对象 都是Float

  24. System.out.println(f1 ==d);//true,double自动转型成float

  25. System.out.println();

  26. Boolean bool1 = true;

  27. Boolean bool2 = true;

  28. System.out.println(bool1 == bool2);//true

  29. }

double/float在计算时会有舍入误差,想要得到更加精确的结果,可以使用java.math.Bidecimal

add(), subtract(), multiply(), divide()

5、集合

1)接口

Java的集合框架用Collection顶级接口来表示,该接口又派生出List和Set两个接口。

List:规定了子类实现的特征为有序且元素可重复,常用实现类有ArrayList和LinkedList。ArrayList使用数组实现,所以更适合读取存储的数据;LinkedList使用链表实现,所以更适合插入、删除元素。

Set:规定了子类实现的特征为无序且元素不可重复。常用实现类有HashSet和TreeSet。HashSet使用散列算法实现的Set集合,而TreeSet则使用二叉树算法实现。

2)集合转为数组

Java代码

  1. Set<String> set = new HashSet<String>();

  2. set.add(“3”);

  3. set.add(“1”);

  4. set.add(“1”);

  5. set.add(“2”);

  6. //集合转为数组,list和set都有这个语法

  7. String[] arr = (String[]) set.toArray(new String[0]);

  8. System.out.println(Arrays. toString (arr));//[3, 2, 1]

数组转为集合:Arrays.asList(数组);

3)排序

Collections.sort(list);//一般用于数值排序

Collections.sort(Collection c, Comparator cc);//new Comparator 则必须实现方法compare(T o1, T o2)

4)Map

key不能为空且不能重复。

containsKey(Object key)——查看当前Map中是否包含给定的key

containsValue(Object value)——查看当前Map中是否包含给定的value

遍历Map的3种方式:遍历所有key,遍历所有键值对Entry,遍历所有value

Java代码

  1. //遍历key

  2. for(String key : map.keySet()) {

  3. System.out.println(“key:” + key + “, value:” + map.get(key));

  4. }

  5. //遍历键值对

  6. for(Entry<String, String> entry : map.entrySet()) {

  7. System.out.println(“key:” + entry.getKey() + “, value:” + entry.getValue());

  8. }

  9. //遍历value

  10. for(String value : map.values()) {

  11. System.out.println(“value:” + value);

  12. }

6、数组

主要是注意一些数组的语法~

Java代码

  1. int[] a = {1,2,3,4,5,6};

  2. int[] b = {4,5,6,7,8};

  3. int[] c = {11,9,10,13,7};

  4. //打印

  5. System.out.println(Arrays.toString(a));

  6. //排序

  7. Arrays.sort(c);

  8. System.out.println(Arrays.toString(c));

  9. //复制

  10. int[] a2 = a;

  11. a2[1]++;

  12. System.out.println(“a:” + Arrays.toString(a) + “, a2:” + Arrays.toString(a2));//相互影响

  13. int[] d = new int[a.length];

  14. System.arraycopy(a, 0, d, 0, a.length);//src, srcPos, dest, destPos, length

  15. System.out.println(Arrays.toString(d));

  16. int[] d2 = Arrays.copyOf(a, a.length);

  17. System.out.println(Arrays.toString(d2));

  18. //扩容

  19. int[] e = new int[a.length + b.length];

  20. System.arraycopy(a, 0, e, 0, a.length);

  21. System.arraycopy(b, 0, e, a.length, b.length);

  22. System.out.println(“e:” + Arrays.toString(e));

还有二维数组等~

7、面向对象

几大特性:封装、继承、多态

8、常见设计模式

1)工厂模式

这里直接从拓展性最好的抽象工厂模式说起~

Java代码

  1. public interface Sender {

  2. public void Send();

  3. }

  4. //两个实现类:

  5. public class MailSender implements Sender {

  6. @ Override

  7. public void Send() {

  8. System.out.println(“this is mailsender!”);

  9. }

  10. }

  11. public class SmsSender implements Sender {

  12. @Override

  13. public void Send() {

  14. System.out.println(“this is sms sender!”);

  15. }

  16. }

  17. //两个工厂类:

  18. public class SendMailFactory implements Provider {

  19. @Override

  20. public Sender produce(){

  21. return new MailSender();

  22. }

  23. }

  24. public class SendSmsFactory implements Provider{

  25. @Override

  26. public Sender produce() {

  27. return new SmsSender();

  28. }

  29. }

  30. //再提供一个接口:

  31. public interface Provider {

  32. public Sender produce();

  33. }

测试类:

Java代码

  1. public class Test {

  2. public static void main(String[] args) {

  3. Provider provider = new SendMailFactory();

  4. Sender sender = provider.produce();

  5. sender.Send();

  6. }

  7. }

2)单例模式

超常见,这里以线程安全的单例模式为例:

Java代码

  1. public class Singleton {

  2. private static Singleton instance = null;

  3. private Singleton() {

  4. }

  5. private static synchronized void syncInit() {

  6. if (instance == null) {

  7. instance = new Singleton();

  8. }

  9. }

  10. public static Singleton getInstance() {

  11. if (instance == null) {

  12. syncInit();

  13. }

  14. return instance;

  15. }

  16. }

3)代理模式

代理:类似专业的中介,代替我们去做某些事。

Java代码

  1. public interface Sourceable {

  2. public void method();

  3. }

  4. public class Source implements Sourceable {

  5. @Override

  6. public void method() {

  7. System.out.println(“the original method!”);

  8. }

  9. }

  10. public class Proxy implements Sourceable {

  11. private Source source;

  12. public Proxy(){

  13. super();

  14. this.source = new Source();

  15. }

  16. @Override

  17. public void method() {

  18. before();

  19. source.method();

  20. atfer();

  21. }

  22. private void atfer() {

  23. System.out.println(“after proxy!”);

  24. }

  25. private void before() {

  26. System.out.println(“before proxy!”);

  27. }

  28. }

测试类:

Java代码

  1. public class ProxyTest {

  2. public static void main(String[] args) {

  3. Sourceable source = new Proxy();

  4. source.method();

  5. }

  6. }

结果:

before proxy!

the original method!

after proxy!

代理模式的应用场景:

如果已有的方法在使用的时候需要对原有的方法进行改进,此时有两种办法:

1、修改原有的方法来适应。这样违反了“对扩展开放,对修改关闭”的原则。

2、就是采用一个代理类调用原有的方法,且对产生的结果进行控制。这种方法就是代理模式。

使用代理模式,可以将功能划分的更加清晰,有助于后期维护!

4)桥接模式

把事物和其具体实现分开,使他们可以各自独立的变化。桥接的用意是:将抽象化与实现化解耦,使得二者可以独立变化,像我们常用的JDBC桥DriverManager一样,JDBC进行连接数据库的时候,在各个数据库之间进行切换,基本不需要动太多的代码,甚至丝毫不用动,原因就是JDBC提供统一接口,每个数据库提供各自的实现,用一个叫做数据库驱动的程序来桥接就行了。

Java代码

  1. public interface Sourceable {

  2. public void method();

  3. }

  4. //分别定义两个实现类:

  5. public class SourceSub1 implements Sourceable {

  6. @Override

  7. public void method() {

  8. System.out.println(“this is the first sub!”);

  9. }

  10. }

  11. public class SourceSub2 implements Sourceable {

  12. @Override

  13. public void method() {

  14. System.out.println(“this is the second sub!”);

  15. }

  16. }

  17. //定义一个桥,持有Sourceable的一个实例:

  18. public abstract class bridge {

  19. private Sourceable source;

  20. public void method(){

  21. source.method();

  22. }

  23. public Sourceable getSource() {

  24. return source;

  25. }

  26. public void setSource(Sourceable source) {

  27. this.source = source;

  28. }

  29. }

  30. public class MyBridge extends Bridge {

  31. public void method(){

  32. getSource().method();

  33. }

  34. }

测试类:

Java代码

  1. public class BridgeTest {

  2. public static void main(String[] args) {

  3. Bridge bridge = new MyBridge();

  4. /*调用第一个对象*/

  5. Sourceable source1 = new SourceSub1();

  6. bridge.setSource(source1);

  7. bridge.method();

  8. /*调用第二个对象*/

  9. Sourceable source2 = new SourceSub2();

  10. bridge.setSource(source2);

  11. bridge.method();

  12. }

  13. }

打印结果:

this is the first sub!

this is the second sub!

5)享元模式(参考数据库连接池)

享元模式的主要目的是实现对象的共享,即共享池,当系统中对象多的时候可以减少内存的开销,通常与工厂模式一起使用

6)策略模式

策略模式定义了一系列算法,并将每个算法封装起来,使他们可以相互替换,且算法的变化不会影响到使用算法的客户。

策略模式的决定权在用户,系统本身提供不同算法的实现,新增或者删除算法,对各种算法做封装。因此,策略模式多用在算法决策系统中,外部用户只需要决定用哪个算法即可。

Java代码

  1. public interface MemberStrategy {

  2. /**

  3. * 计算图书的价格

  4. * @param booksPrice 图书的原价

  5. * @return 计算出打折后的价格

  6. */

  7. public double calcPrice(double booksPrice);

  8. }

  9.   //初级会员折扣类

  10. public class PrimaryMemberStrategy implements MemberStrategy {

  11. @Override

  12. public double calcPrice(double booksPrice) {

  13. System.out.println(“对于初级会员的没有折扣”);

  14. return booksPrice;

  15. }

  16. }

  17.   //中级会员折扣类

  18. public class IntermediateMemberStrategy implements MemberStrategy {

  19. @Override

  20. public double calcPrice(double booksPrice) {

  21. System.out.println(“对于中级会员的折扣为10%”);

  22. return booksPrice * 0.9;

  23. }

  24. }

  25.   //高级会员折扣类

  26. public class AdvancedMemberStrategy implements MemberStrategy {

  27. @Override

  28. public double calcPrice(double booksPrice) {

  29. System.out.println(“对于高级会员的折扣为20%”);

  30. return booksPrice * 0.8;

  31. }

  32. }

  33.   //价格类

  34. public class Price {

  35. //持有一个具体的策略对象

  36. private MemberStrategy strategy;

  37. /**

  38. * 构造函数,传入一个具体的策略对象

  39. * @param strategy 具体的策略对象

  40. */

  41. public Price(MemberStrategy strategy){

  42. this.strategy = strategy;

  43. }

  44. /**

  45. * 计算图书的价格

  46. * @param booksPrice 图书的原价

  47. * @return 计算出打折后的价格

  48. */

  49. public double quote(double booksPrice){

  50. return this.strategy.calcPrice(booksPrice);

  51. }

  52. }

测试类:

Java代码

  1. public class StrategyTest{

  2. public static void main(String[] args) {

  3. //选择并创建需要使用的策略对象

  4. MemberStrategy strategy = new AdvancedMemberStrategy();

  5. //创建环境

  6. Price price = new Price(strategy);

  7. //计算价格

  8. double quote = price.quote(300);

  9. System.out.println(“图书的最终价格为:” + quote);

  10. }

  11. }

打印结果:

对于高级会员的折扣为20%

图书的最终价格为:240.0

………………

策略模式基本上答了这些就够了~

不知道读者满不满意,别喷谢谢。

文章来源:智云一二三科技

文章标题:菜鸟面试:就java基础知识而谈

文章地址:https://www.zhihuclub.com/197718.shtml

关于作者: 智云科技

热门文章

网站地图