面试

一、基础

1.接口和抽象类有什么区别?
接口(interface)代表一种能力,接口中的方法都用public来修饰,没有构造方法,不可实例化,接口中只有常量,且是public static final(共有静态常量)
接口的继承类必须实现接口中的所有方法。
一个接口可以继承多个接口,但不允许多重继承。接口直接的继承使用extends,普通类继承接口implements。
抽象类(abstract)可看作是一模板,可根据其格式来创建和修改新的类。
抽象类无法被实例化,类中可以有抽象方法,也可以有普通方法,可以有常量和变量。
一个类可以实现多个接口,但是只能继承一个抽象类。

2.equals()和==
这两个都是用来判断对象是否相等的。    
==:对于基本数据类型,比较的是数值,对于引用数据类型(string),比较的是内存地址是否相同。
在Object中定义的equals()方法是用==来比较对象的,但是在其他类中的equals()方法,都有自己不同的实现。
但都是首先用==来比较,如果是ture的话,equals()直接返回true,如果是false,则继续比较。
通过以上的说明,可以知道equals()与==的含义是否相同,要看比较的对象类型,如果都是Object类型,二者无差别,如果是String的话,二者有差别,equals()在进行==比较的基础上,还会建立一个char[],将字符串存入char[],然后逐一比对字符是否相同。如果都相同,即便==返回的结果为false,那么equals()返回的也还是true。

可以看Object,String,HashSet类中equals()的源码,String,HashSet覆写了equals()方法。

//Object
 public boolean equals(Object obj) {
        return (this == obj);
    }

//String
public boolean equals(Object anObject) {
        if (this == anObject) {
            return true;
        }
        if (anObject instanceof String) {
            String anotherString = (String)anObject;
            int n = value.length;
            if (n == anotherString.value.length) {
                //建立字符数组,一个一个进行比较,如果都相同返回true
                char v1[] = value;
                char v2[] = anotherString.value;
                int i = 0;
                while (n-- != 0) {
                    if (v1[i] != v2[i])
                        return false;
                    i++;
                }
                return true;
            }
        }
        return false;
    }

tip:就着上面的源码,可以多说一点,假设一个apple对象,有一个colour属性,在进行比较的时候:

apple.getColour().equals("red"),这样写不妥,如果apple的colour属性为null的话,会报空指针异常,因为null无法比较地址,应该改写成"red".equals(apple.getColour),这样就是用string的equals()方法来判断了。

另外:在集合(hashSet,hashMap)中,equals()与hashCode有关,在比较存入的元素是否重复时,还需要比较hashCode。

mark一篇文章,关于==,equals(),hashcode讲的超级全面:https://www.cnblogs.com/skywang12345/p/3324958.html

3.为什么java不允许多重继承。
可以说说diamond模型中,出现的继承歧义问题。
另外,最实际的原因,为什么java这样流行,不就是因为摒弃了c和c++的指针,并且gc可以自动回收垃圾释放内存等等原因,让java更简单了吗?允许多重继承,除了增加java的复杂性,还有什么呢。

4.String不可变?
String str = "abc";
str = "123";
简单理解,栈内存(str)中存的是对堆内存("abc"、"123")地址的引用。
String不可变,指的是"abc"不可变,str只是abc的引用,可以将其引用到其他的字符串。
奇思妙想的一个点:站在java设计者的角度来看,Map常常用String做key,Map的源码中说明如果mutable obj来做key的话,map就会乱套了,那么从这一点出发,String的值当然不可以随便改变。
int indexOf(str) 返回第一个出现的str所在index,-1
int lastIndexOf(str)
String[] spilt(String regex) 分割字符串
String substring(int begin,int end)
String trim() 去空格
String toUpperCase()
String toLowerCase()
String concat(str) 字符串拼接

5.String str = new String("abc")和String str = "abc"的区别
对象池:为了节约内存空间,"abc"会存入字符串池中,当新建一个字符串时,会首先到对象池中查找有无此字符串,如果有则取出,与str关联,如果没有则开辟新的内存空间,存储字符串。这样就达到了多个引用指向同一内存空间。
直接new一个sting字符串,无法自动入池。
"abc".equals(),只有对象可以调用方法,所以字符串是一个对象

6.String,StringBuffer,StringBuilder
StringBuffer:
    方法都是synchronized,线程安全(thread-safe),字符串长度和内容可以改变。
    StringBuffer有一个capacity
    StringBuffer append(String str) 字符串拼接,如果str为Null,则拼接的str为"null"

StringBuilder:
    方法与StringBuffer兼容,但是非线程安全
    可以看作对StringBuffer的替代,二者的差别只在与是否线程安全

StringBuffer和StringBuilder在用于拼接大量字符串时有优势,这个拼接指的是特定情况的拼接:

for (int i = 0; i < 100000; i++) {
    String str = "a";
    //进行100000次拼接,相当于str->"b"的连接,断开又连接100000次
    str+="b";
}

比如这样,就要断开又连接100000次,非常消耗性能。
使用StringBuffer则性能要高。
但应当注意,StringBuffer方法都加了synchronized方法,这肯定比String的方法要消耗性能,所以StringBuffer应当在特殊情况下使用,比如上述或是多线程。


7.重载和覆写
重载(OverLoad):方法名称相同,参数类型或个数不同,与返回值无关。在一个类之中,存在多个方法名相同的方法。
覆写(Override):是子类对父类方法的重新,通常是实现父类的抽象方法,子类的方法不能够比父类更严。

8.类和对象
类是抽象概念,可看作模板,对象才是在程序中占用内存。

9.final关键字
修饰类:此类成为太监类,不可有子类
修饰变量:此变量为常量,且必须在声明常量时赋值(initialized),一旦声明值不可改变
引用变量被final修饰后,此引用变量不能再指向其他值


10.private public protected default

private:通常修饰属性,只有当前类可以访问
public:都可访问
protected:为继承而设计,子类可以访问,同包类可以访问
default:同包类可以访问,非同包不可以访问

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值