对象导论
思想的实质:程序可以通过添加新类型的对象使自身适用于某个特定问题。
1.万物皆为对象。
2.程序是对象的集合,它们通过发送消息来告知彼此所要做的。
3.每个对象都有自己的由其他对象所构成的存储。
4.每个对象都拥有其类型。
5.某一特定类型的所有对象都可以接收同样的消息。
一切都是对象
创建一个String引用:
String s;
这里所创建的只是引用,并不是对象。
Java有一个垃圾回收器,用来监视用new创建的所有对象,并辨别哪些不会再被引用的对象。随后,释放这些对象的内存空间,以便供其他新的对象使用。
class关键词:
class ATypeName { /* Class body goes here / }
ATypeName a = new ATypeName();
Java程序:
//HelloDate.java
import java.util.*;
public class HelloDate {
public static void main(String[] args) {
System.out.println("Hello, it's:");
System.out.println(new Date());
}
}
操作符
System.out.println("a = " + a + " b = " + b );
在这种上下文环境中,“+”意味着“字符串连接”,并且如果必要,它还要执行“字符串转换”。
在为对象“赋值”的时候,我们真正操作的是对对象的引用。所以倘若“将一个对象赋值给另一个对象”,实际是将“引用”从一个地方复制到另一个地方。
Integer n1 = new Integer(47);
Integer n2 = new Integer(47);
System.out.println(n1 == n2);
System.out.println(n1 != n2);
Output:
false
true
尽管对象的内容相同,然而对象的引用却是不同的,而==和!=比较的就是对象的引用。
如果想比较两个对象的实际内容是否相同,必须使用所有对象都适用的特殊方法equals()。但这个方法不适用于“基本类型“,基本类型直接使用==和!=即可。
由于equals()的默认行为是比较引用。所以除非在自己的新类中覆盖equals()方法,否则不可能表现出我们希望的行为。
与在C及C++中不同的是:不可将一个非布尔值当作布尔值在逻辑表达式中使用。
当使用逻辑操作符时,我们会遇到一种“短路”现象,即一旦能够明确无误地确定整个表达式的值,就不再计算表达式余下的部分了。
test1(0)&&test2(2)&&test3(2)
第一个测试生成结果为true,所以表达式会继续下去。然而,第二个测试产生了一个false结果。由于这意味着整个表达式肯定为false,所以没必要继续计算剩余的表达式,那样只是浪费。“短路”一词的由来正源于此。事实上,如果所有的逻辑表达式都有一部分不必计算,那将获得潜在的性能提升。
移位操作符:移位操作符只可用来处理整数类型。左移位操作符(<<)能按照操作符右侧制定的位数将操作数向左移动。“有符号”右移位操作符(>>)则按照操作符右侧指定的位数将操作符左边的操作数向右移动。“有符号”右移位操作符使用“符号扩展”:若符号为正,则在高位插入0;若符号为负,则在高位插入1.Java中增加了一种“无符号”右移位操作符(>>>),它使用“零扩展”:无论正负,都在高位插入0。这一操作符是C或C++中所没有的。
控制执行流程
如果想在布尔测试中使用一个非布尔值,比如在if(a)中,那么首先必须用一个条件表达式将其转化成布尔值,例如if(a!=0)
if-else:
if(Boolean-expression)
statement
or
if(Boolean-expression)
statement
else
statement
while:
while(Boolean-expression)
statement
do-while:
do
statement
while(Boolean-expression)
for:
for(initializaiton; Boolean-expression; step)
statement
Foreach:
public class ForEachString {
public static void main(String[] args) {
for(char c : "An African Swallow".toCharArray())
System.out.print(c + " ");
}
}
/* Output:
A n A f r i c a n S w a l l o w
*/
range()使得foreach语法适用于更多的场合,并且这样做似乎可以增加可读性,但是它的效率会稍许降低,因此如果您在做性能调优,也许应该使用仿真器来做评价,它是一种可以度量代码性能的工具。
break和continue关键词通常中断当前循环,但若随同标签一起使用,它们就会中断循环,直到标签所在的地方:
label1:
outer-iteration {
inner-iteration {
//...
break; //
//...
continue; //
//...
continue label1; // (1)
//...
break label1; // (2)
}
}
在(1)中,continue label1同时中断内部迭代以及外部迭代,直接转到label1处;随后它实际上是继续迭代过程,但却从外部迭代开始;在(2)中,break label1也会中断所有迭代,并回到label1处,但并不重新进入迭代。也就是说,它实际是完全终止了两个迭代。
规则:
1)一般的continue会退出最内层循环的开头(顶部),并继续执行。
2)带标签的continue会到达标签的位置,并重新进入紧接在那个标签后面的循环。
3)一般的break会中断并跳出当前循环。
4)带标签的break会中断并跳出标签所指的循环。
在Java里需要使用标签的唯一理由就是因为有循环嵌套存在,而且想从多层嵌套中break或continue。
switch:
switch(integral-selector) {
case integral-value1 : statement; break;
case integral-value2 : statement; break;
case integral-value3 : statement; break;
case integral-value4 : statement; break;
case integral-value5 : statement; break;
//...
default : statement;
}
由于Random.nextInt(26)会产生0到26之间的一个值,所以在其上加上一个偏移量“a”,即可产生小写字母。
import java.util.*;
//...
int c = rand.nextInt(26) + 'a';