一、基础
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:同包类可以访问,非同包不可以访问
8万+

被折叠的 条评论
为什么被折叠?



