s1是用直接量赋值, s2是两个字符串连接赋值;
由于编译器编译阶段就确定了s2的值 = “疯狂 Java”;所以会让s2指向常量池缓存中的“疯狂 Java”字符串,故s2 == s1;
而st3 是不能再编译阶段确定的,故st3不指向缓存中的“疯狂 Java”字符串,故不相等;
而定义常量st4,st5时,运行st6 = st4 + st5,st6效果和s2一样,编译器已经让st4和st5执行了宏替换;
public class Test {
public static void main(String[] args){
String s1 = "疯狂 Java";
String s2 = "疯狂" + " Java";
System.out.println(s1 == s2);
String st1 = "疯狂";
String st2 = " Java";
String st3 = st1 + st2;
System.out.println(s1 == st3);
final String st4 = "疯狂";
final String st5 = " Java";
String st6 = st4 + st5;
System.out.println(s1 == st6);
}
}
final修饰的类,不能有子类即不能被继承;final修饰的方法,不能被重写;
如果父类是private修饰的方法,因为子类不能继承,也访问不到,所以即便子类定义一个与父类有相同的方法名,形参列表,返回值类型的方法也不是重写,是定义的新方法;
故private final的方法,子类可以写一个相同的方法,因为那是,定义的新方法;
不可变类:
1:成员变量全部为private final 修饰;
2:只能有getter方法,不能有setter方法;
3:提供构造器,初始化成员变量;
4:必要时重写Object类的hashCode()和equals()方法;并且equals()判断相等的对象,haseCode()必须相等;
不可变类的状态不能改变,如程序经常使用相同的不可变类实例,应创捷缓存;下用数组模拟;
package Study;
public class Cache {
private static int MAX_SIZE = 10; //缓存大小
private static Cache[] cache = new Cache[MAX_SIZE];
private static int pos = 0;//记录缓存位置
private final String name;
private Cache(String name) {//提供构造器,初始化成员变量
this.name = name;
}
public String getName() {//只能getter,不能setter;
return this.name;
}
public static Cache valueOf(String name) {//用.valueOf返回实例;
for(int i = 0; i < MAX_SIZE; i++) {//如果找到相同实例,则返回;
if(cache[i] != null && cache[i].getName() == name) {
return cache[i];
}
}
if(pos == MAX_SIZE) {//如果满了,覆盖第一个
cache[0] = new Cache(name);
pos = 1;
}
else {//否则创建
cache[pos++] = new Cache(name);
}
return cache[pos - 1]; //返回pos -1 位置的实例
}
public boolean equals(Object obj) { //重写equals
if(obj == null)return false;
if(this == obj) return true;
if(obj.getClass() == Cache.class) {
Cache ci = (Cache)obj;
return name.equals(ci.getName());
}
return false;
}
public int hashCode() {
return name.hashCode();
}
public static void main(String[] args) {
Cache c1 = Cache.valueOf("hello");
Cache c2 = Cache.valueOf("hello");
System.out.println(c1 == c2);
}
}
静态代码块主要用于为静态程序进行初始化;