Java笔试面试总结——基础篇


一、 接口

传送点:深入浅出,理解Java接口


二、 反射

传送点:Java基础反射原理(去年小米面试问到过)


三、 String

1.Java的String类型为什么是不可变的(百度)

String类中的成员变量:

private final char value[];
private final int offset;
private final int count;

执行完String s="ABCabc"这句代码之后,真正的内存布局应该是这样的:
在这里插入图片描述
value,offset和count这三个变量都是private的,并且没有提供setValue,setOffset和setCount等公共方法来修改这些值,所以在String类的外部无法修改String。
因为字符串是不可变的,所以多线程是安全的,同一个字符串实例可以被多个线程共享。这样便不用因为线程安全问题而使用同步。字符串自己便是线程安全的,在大量使用字符串的情况下,可以节省内存空间,提高效率。

2.获取www.baidu.com最后一个点的内容“com”(蘑菇街)

String str="www.baidu.com";
int i=str.lastIndexOf('.');//返回指定字符在此字符串中最后一次出现处的索引
String str1=str.substring(i+1,str.length());//返回一个str的子字符串。
System.out.println(str1);

3.String a=“abc” ;String b=“a”+“bc”;a==b?(网易)

String a="abc";String b="a"+"bc";
if(a==b){
      System.out.println("true");
}
else{
      System.out.println("false");
}//输出为:true     只生成一个字符串,保存在字符串常量池中

四、 String和byte[]之间的转化

Java如何把byte类型转换成字符串

  1. 常规的String转byte[]
public static byte[] strToByteArray(String str){
       if(str==null){
              return null;
       }
       byte[] byteArray=str.getBytes();
       return byteArray;
}
  1. 常规的byte[]转String
public static String byteArrayToStr(byte[] byteArray){
       if(byteArray==null){
             return null;
       }
       String str=new String(byteArray);
       return str;
}
  1. byte[]转化为十六进制的String
private static final String hexDigits[]={"0", "1", "2", "3", "4", "5","6", "7", "8", "9", "a", "b", "c", "d", "e", "f"};//单个字节转换成16进制的字符串
private static String byteToHexString(byte b){
       int n=b;
       if(n<0) n+=256;
       int d1=n/16;//取出高4位
       int d2=n%16;//取出低4位
       return hexDigits[d1]+hexDigits[d2];
}//将字节数组转换成16进制的字符串
private static String byteArrayToHexString(byte b[]){
       StringBuffer resultSb=new StringBuffer();
       for(int i=0;i<b.length;i++)
             resultSb.append(byteToHexString(b[i]));
       return resultSb.toString();
}//测试代码
public static void main(String[] args){
       byte[] b={10,11};
       String s=MD5Util.byteArrayToHexString(b);
       System.out.println(s);
}//运行结果:0a0b
  1. MD5工具类
public class MD5Util{
private static String byteArrayToHexString(byte b[]){
        StringBuffer resultSb=new StringBuffer();
        for(int i=0;i<b.lenth;i++)
              resultSb.append(byteToHexString(b[i]));
        return resultSb.toString();
}
private static String byteToHexString(byte b){
        int n=b;
        if(n<0)
              n+=256;
        int d1=n/16;
        int d2=n%16;
        return hexDigits[d1]+hexDigits[d2];
}
public static void main(String[] args){
        byte[] b={10,11};
        String s=MD5Util.byteArrayToHexString(b);
        String s1=MD5Util.MD5EncodeUtf8("101112a");
        System.out.println(s1.length());
}//返回大写MD5
private static String MD5Encode(String origin,String charsetname){
        String resultString=null;
        try{
              resultString =new String(origin);
              MessageDigest md=MessageDigest.getInstance("MD5");
              if(charsetname==null||" ".equals(charsetname))
                    resultString=byteArrayToHexString(md.digest(resultString.getBytes()));
              else
                    resultString=byteArrayToHexString(md.digest(resultString.getBytes(charsetname)));
              
        }catch(Exception exception){}
        return resultString.toUpperCase();
}
public static String MD5EncodeUtf8(String origin){
        origin=origin+ProperiesUtil.getProperty("password.salt"," ");
        return MD5Encode(origin,"utf-8");
}
private static final String hexDigits[]={"0", "1", "2", "3", "4", "5",
        "6", "7", "8", "9", "a", "b", "c", "d", "e", "f"};
}

五、 ClassNotFoundException

意思就是找不到指定的class,遇到的场景:

  1. 调用class的forName方法时,找不到指定的类。
  2. ClassLoader中的findSystemClass()方法时,找不到指定的类。
  3. ClassLoader中的loadClass()方法时,找不到指定的类
package test;
public class test{
       public static void main(String[] args){
             try{
                  Class.forName("test666.hello");
             }catch(ClassNotFoundException e){
                  e.printStackTrace();
             }
       }
}

解决办法:检查类名是否正确、或是否存在该类。
补充:NoClassDefFoundError 常见的场景就是:

  1. 类依赖的class或者jar不存在。
  2. 类文件存在,但是存在不同的域中
  3. 大小写问题,Javac编译的时候是无视大小的,很有可能你编译出来的class文件就与想要的不一样!这个没有做验证。

六、 HashCode

面试题:
hashCode的作用是什么?如果要重写需要注意哪些点?(腾讯面试)
使用HashMap时重写哪两个方法,为什么要重写?(百度面试)

hashCode简介

public int hashCode():hashCode是根类Object中的方法。默认情况下,Object中的hashCode()返回对象的32位jvm内存地址。也就是说如果对象不重写该方法,则返回相应对象的32位JVM内存地址。

hashCode注意点

关于hashCode方法,一致的约定:

  1. 重写了equals方法的对象必须同时重写hashCode()方法。
  2. 如果两个对象equals相等,那么这两个对象的HashCode一定也相同。
  3. 如果两个对象的HashCode相同,不代表两个对象就相同,只能说明这两个对象在散列存储结构中,存放于同一个位置。

hashCode作用

从Object角度看,JVM每new一个Object,它都会将这个Object丢到一个Hash表中去,这样的话,下次做Object的比较或者取这个对象的时候(读取过程),它会根据对象的HashCode再从Hash表中取出这个对象。这样做的目的是提高取对象的效率,若HashCode相同再去调用equals。

为什么重写hashCode

实际开发中在HashMap或者HashSet中如果不重写hashCode和equals方法的话会导致我们存对象的时候,把对象存进去了,取的时候却取不到想要的对象。重写了hashCode和equals方法可以迅速的在HashMap中找到键的位置。

  1. 重写hashCode是为了保证相同的对象会有相同的hashCode。
  2. 重写equals是为了保证在发生冲突的情况下取得到Entry对象(也可以理解是key或是元素)

七、 线程的生命周期状态

线程有几种状态(招银网络科技)

线程从创建、运行到结束总是处于下面五个状态之一:新建状态、就绪状态、运行状态、阻塞状态以及死亡状态。

  • 新建状态: 新建一个线程的对象,实现Runnable接口和继承Thread可以得到一个线程类,new一个实例出来,线程就进入了初始状态。
  • 就绪状态: 当线程有资格运行,但调度程序还没有把它选定为运行线程时线程所处的状态。
  • 运行状态: 可运行的程序获取了CPU的使用权,执行程序代码。
  • 阻塞状态: 阻塞状态是正在运行的线程还没有运行结束,暂时让出CPU,这时其他处于就绪状态的线程就可以获得CPU时间,进入运行状态。
    • 线程通过调用sleep方法进入睡眠状态。
    • 线程调用一个在I/O上被阻塞的操作,即该操作在输入输出操作完成之前不会返回到它的调用者。
    • 线程试图得到一个锁,而该锁正被其他线程持有。
    • 线程在等待某个触发条件。
  • 死亡状态: 有几个原因会导致线程死亡:
    • run方法正常退出而自然死亡;
    • 一个未捕获的异常终止了run方法而使线程猝亡;
    • 线程调用sleep()、destroy()、run()方法
      为了确定线程当前是否存活(要么可运行,要么被阻塞),需要使用isAlive方法,如果是可运行或被阻塞则返回true,如果线程依旧是new状态且不是可运行的,或线程已死亡,则返回false。
      如图:
      在这里插入图片描述

八、 线程创建

一、 接口

一、 接口

一、 接口

一、 接口

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值