1. java中的字符串常量不能跨行,例如以下代码将不会通过编译:
public class MyString{
public static void main(String[] args){
System.out.println("Hello
World");
}
}
这也就是为什么要使用“+”运算符进行字符串的连接。
2. java中的浮点数都不是精确存储的,例如:
System.out.println(1.0 - 0.9); //运行结果0.09999999999999998而不是0.1
3. Unix时间戳(Unix epoch),因为Unix操作系统是在1970年正式发布的。
利用乘法和取余我们可以很方便地得到格林尼治时间:
long toalMilliseconds = System.currentTimeMillis();
long totalSeconds = toalMilliseconds / 1000;
long totalMinutes = totalSeconds / 60;
long totalHours = totalMinutes / 60;
int currentSeconds = (int) (totalSeconds % 60);
int currentMinutes = (int) (totalMinutes % 60);
int currentHours = (int) (totalHours %24);
System.out.println("格林尼治时间"+currentHours + ":" + currentMinutes + ":"
+ currentSeconds);
4. 自增和自减也可以用在char类型的数据上,例如:
char c = 'A';
System.out.println(++c);
将打印出B
5. 所有的数值运算符都可以用在char型操作数上,如果其中一个操作数是数字或者字符的话,那么char型操作数会自动转化成一个数字;如果其中一个操作数是一个字符串,该字符就会与字符串进行连接。
System.out.println('A'+'0'); //结果是113=65+48
System.out.println('A'+1.2); //结果是66.2=65+1.2
System.out.println('A'+"字符串"); //结果A字符串,与字符串进行了连接
Tips:关于小写字母ch转化成大写字母可以采用以下的算法:
(char) ('A' + ch - 'a')——ch表示需要转化成大写字母的小写字母。
6. Scanner的next()方法和nextLine()方法的区别:
- next()方法读取以空白字符结尾的字符串(如:' '、'\f'、'\r'、'\n'、'\t')
- nextLine()方法可以读取一整行文本。
System.out.println("输入3个字符串");
Scanner scanner = new Scanner(System.in);
String s1 = scanner.next();
String s2 = scanner.next();
String s3 = scanner.next();
System.out.println("s1 = " + s1 + " ,s2 = " + s2 + " ,s3 = " + s3);
运行结果:
System.out.println("输入字符串:");
Scanner scanner = new Scanner(System.in);
String s = scanner.nextLine(); // 读取一行
System.out.println("s = " + s);
运行结果:
特别警告:为了避免输入错误,不要在nextByte()、nextShort()、nextInt()、nextLong()、nextFloat()、nextDouble()和next()之后使用nextLine()。将会抛出java.util.InputMismatchException。
7. 异或运算符^不仅仅可以用于位运算也可以用于逻辑运算:
System.out.println(false^false); //异或运算也能够用于逻辑运算
System.out.println(false^true);
System.out.println(true^false);
System.out.println(true^true);
运行结果:
利用异或的真值表可以进行以下的判定(一个数能够被2整除但是不能被3整除,或者能够被3整除但是不能被2整除——也就是说该数当且仅能被2和2其中的一个整除,利用异或可以简化两个判断为一个)
System.out.println("#");
Scanner scanner = new Scanner(System.in);
int number = scanner.nextInt();
if (number % 2 == 0 ^ number % 3 == 0) { //异或运算简化编程
System.out.println(number + "能够被2和3中的一个整除!");
}
8. 在循环控制当中不要使用浮点值来比较是否相等。因为浮点值都是某些类的近似值,使用它们很可能导致不精确的循环次数和不准确的结果。考虑下面计算1+0.9+0.8+……+0.1的代码:
double item = 1, sum = 0;
while (item != 0) { // 死循环
sum += item;
item -= 0.1;
}
System.out.println("sum = " + sum);
变量item从1开始,每执行一次循环体就减去0.1.当item变为0的时候循环就应当终止。但是,因为浮点数在算术上是近似的,所以不能确保item会变成真正的0.从表面来看,这个循环似乎没有问题,但是实际上他是一个无限循环!
9. 如果省略for循环中的循环等待条件,则隐含地认为循环继续条件为true。因此,下面的a、b2个语句是等价的,他们都是无限循环。但是为了避免混淆,最好还是使用c中的等价循环。
a:
for (;;) {
// Do something
}
b:
for (; true;) {
// Do something
}
c:
while (true) {
// Do something
}
最小化数值误差
涉及浮点数的数值误差总是不可避免的,以下实例将讲解如何最小化这种误差。
计算0.01+0.02+0.03+……+1的数列的和。
public class TestSum {
public static void main(String[] args) {
System.out.println("该程序将计算0.01+0.02+0.03+……+1的和");
float sum = 0;
for (float i = 0.01f; i <= 1.0f; i += 0.01f) {
sum += i;
}
System.out.println("sum = " + sum); // 用数学公式应该得到50.5但是实际结果是50.499985
}
}
sum的精确结果应该是50.50,但是以上程序计算的结果是50.499985。这个结果是不精确的,因为计算机使用的固定位数表示的浮点数,因此不能够精确地表示某些浮点数。如以下程序所示,将程序中的float类型改变成double类型,可以看到精度有一点点的改善(因为double类型采用的是64位而float类型采用的是32位)。
public class TestSum {
public static void main(String[] args) {
System.out.println("该程序将计算0.01+0.02+0.03+……+1的和");
double sum = 0;
for (double i = 0.01; i < 1.0; i += 0.01) {
sum += i;
}
System.out.println("sum = " + sum); // 用数学公式应该得到50.5但是实际结果是49.50000000000003
}
}
为了解决这个问题,使用整数计数器以确保所有的数字都被加入到sum中,下面是一个新的循环:
public class TestSum {
public static void main(String[] args) {
System.out.println("该程序将计算0.01+0.02+0.03+……+1的和");
double sum = 0;
int count = 1;
double currentValue = 0.01;
for (int i = 0; i < 100; i++) {
sum += currentValue;
currentValue += 0.01;
System.out.print(currentValue + "\t"); // 打印i值
if (count++ % 5 == 0) {
System.out.println();
}
}
System.out.println("sum = " + sum); // 用数学公式应该得到50.5但是实际结果是49.50000000000003
}
}
运行结果:
这个循环结束后,sum的值是50.50000000000003,这个循环从小到大添加数字。如果使用下面的方法从大到小添加(即:1.0+0.99+0.98+……+0.02+0.01)会发生什么情况?
public class TestSum {
public static void main(String[] args) {
System.out.println("该程序将计算0.01+0.02+0.03+……+1的和");
double sum = 0;
int count = 1;
double currentValue = 1.0;
for (int i = 0; i < 100; i++) {
sum += currentValue;
currentValue -= 0.01;
System.out.print(currentValue + "\t"); // 打印i值
if (count++ % 5 == 0) {
System.out.println();
}
}
System.out.println("sum = " + sum); // 用数学公式应该得到50.5但是实际结果是50.49999999999995
}
}
运行结果:
在这个循环结束之后,sum的值是50.49999999999995。从大到小添加数字没有从小到大添加数字得到的值精确——这种现象是有限精度算术的产物。如果结果值要比变量所能存储的容量更高的精度,那么添加一个非常小的数给一个非常大的数可能没有什么影响。例如:
public class TestSum {
public static void main(String[] args) {
System.out.println(100000000.0 + 0.000000001); // 结果是:1.0E8
}
}
使用确认对话框控制循环
int option = JOptionPane.YES_OPTION;
while (option == JOptionPane.YES_OPTION) {
System.out.println("继续循环");
option = JOptionPane.showConfirmDialog(null, "继续?");
}
下面是一个计算和的GUI程序:import javax.swing.JOptionPane;
public class SentinelvalueUsingConfirmDialog {
public static void main(String[] args) {
int sum = 0;
// 一直读取数据直到用户选择否
int option = JOptionPane.YES_OPTION;
while (option == JOptionPane.YES_OPTION) {
// 读下一个数据
String dataString = JOptionPane.showInputDialog("输入值:");
int data = Integer.parseInt(dataString);
sum += data;
option = JOptionPane.showConfirmDialog(null, "继续?");
}
JOptionPane.showMessageDialog(null, "sum = " + sum);
}
}
运行结果:11. 解释一下下面的程序为什么能够运行?
public static void main(String[] args) {
int x = 1;
while (x > 0) {// 不是死循环
x++;
}
System.out.println("x = " + x);
}
程序刚开始看1>0应该是恒成立,所以循环应该是死循环,但是x有增量,整数是有范围的,一旦超出范围就会产生溢出,所以正数相加最后会变成负数从而满足循环的终止条件(这一点要特别注意)。以上程序的运行结果是Integer.MIN_VALUE = -2147483648,因为程序一直会加到整数的最大值,然后整数溢出就变成了最小值。