一、Java求余%的结果符号取决于除数的符号位;小数也可以求余,余数仍为小数。
1 package com.test; 2 3 public class Test { 4 5 /** 6 * @author 容杰龙 7 */ 8 public static void main(String[] args) { 9 System.out.println(5/3); //1 10 System.out.println(5%3); //2 11 12 System.out.println(-5/3); //-1 13 System.out.println(-5%3); //-2 14 15 System.out.println(-5/-3); //1 16 System.out.println(-5%-3); //-2 17 18 System.out.println(5/-3); //-1 19 System.out.println(5%-3); //2 20 21 //浮点类型 22 System.out.println(20.5%2.5); //0.5 23 System.out.println(20.2%10.1); //0.0 24 System.out.println(10%2.); //0.0 25 System.out.println(-10.8%2); //-0.8000000000000007 26 System.out.println(20.168%-10.111); //10.056999999999999 27 System.out.println(20.168%10.111); //10.056999999999999 28 29 } 30 }
二、String对象的比较问题
A.String是不可变的,不能被继承。String类内部通过char数组来保存字符串,而这个char数组被声明为:final。String类的设计使用了不变模式。
B.String类的声明如下:
public final class String implements java.io.Serializable, Comparable, CharSequence
C.数据区的三个部分:Java 虚拟机栈(可以简称为Java栈)、堆和运行时常量池(简称常量池)
D.常量池
虚拟机必须为每个被装载的类型维护一个常量池。常量池就是该类型所用常量的一个有序集合,包括直接常量(string,integer和floating point常量)和对其他类型、字段和方法的符号引用。字符串字面值会存储在常量池中。
String x = "abc"; String y = new String("abcd");
第一条语句没有在堆中分配内存,而是将“abc”保存在常量池中。对于第二条语句,同样会在常量池中有一个“abcd”的字符串,当new时,会拷贝一份该字符串存放到堆中,于是y指向了堆中的那个“abcd”字符串。
1 package com.test; 2 3 public class Test { 4 /** 5 * @author 容杰龙 6 */ 7 private static String a = "ab"; 8 private static String ab = new String("ab"); 9 public static void main(String[] args) { 10 /** 11 * 当两个字符串字面值连接时(相加), 12 * 得到的新字符串依然是字符串字面值, 13 * 保存在常量池中。 14 */ 15 String a1="abc123"; 16 String a2="ab"+"c"+123; 17 System.out.println(a1==a2); //true 18 /** 19 * 当字符串字面值与String类型变量连接时, 20 * 得到的新字符串不再保存在常量池中, 21 * 而是在堆中新建一个String对象来存放。 22 * 很明显常量池中要求的存放的是常量, 23 * 有String类型变量当然不能存在常量池中了。 24 */ 25 String b1="abc123"; 26 String b2="123"; 27 String b3="abc"+b2; 28 System.out.println(b1==b3); //false 29 /** 30 * 此处是字符串字面值与String类型常量连接, 31 * 得到的新字符串依然保存在常量池中。 32 */ 33 String c1 = "ab"; 34 final String c2 = "b"; 35 String c3 = "a" + c2; 36 System.out.println(c1 == c3); //true 37 /** 38 * final String d2 = get123(); 39 * 其实与final String d2 = new String(“123”);是一样的。 40 * 也就是说return “123”会在堆中创建一个String对象保存”123”, 41 * 虽然d2被定义成了final。可见并非定义为final的就保存在常量池中, 42 * 很明显此处d2常量引用的String对象保存在堆中, 43 * 因为get123()得到的String已经保存在堆中了, 44 * final的String引用并不会改变String已经保存在堆中这个事实。 45 */ 46 String d1 = "abc123"; 47 final String d2 = get123(); 48 String d3 = "abc" + d2; 49 System.out.println(d1 == d3);//false 50 /** 51 * intern()方法 52 * 返回字符串对象的规范化表示形式。 53 * 一个初始为空的字符串池,它由类 String 私有地维护。 54 * 当调用 intern 方法时,如果池已经包含一个等于此 String 对象的字符串 55 * (用 equals(Object) 方法确定),则返回池中的字符串。 56 * 否则,将此 String 对象添加到池中,并返回此 String 对象的引用。 57 * 它遵循以下规则:对于任意两个字符串 s 和 t,当且仅当 s.equals(t) 为 true 时, 58 * s.intern() == t.intern() 才为 true。 59 * 所有字面值字符串和字符串赋值常量表达式都使用 intern 方法进行操作。 60 * 61 */ 62 String s1 = "a"; 63 String s2 = "b"; 64 String s = s1 + s2; 65 System.out.println(s == a);//false 66 System.out.println(s.intern() == a);//true 67 //////////////////////////////// 68 String ss1 = "a"; 69 String ss2 = "b"; 70 String ss = ss1 + ss2; 71 System.out.println(ss == ab);//false 72 System.out.println(ss.intern() == ab);//false 73 System.out.println(ss.intern() == ab.intern());//true 74 } 75 76 private static String get123() { 77 return "abc"; 78 } 79 }