1、在C和C++中将一个较大作用域的变量“隐藏”起来的做法,在Java里不允许
{ int x=0; { int x=1;//illegal } }
2、Java语言受lisp语言的启发,设计了一个垃圾回收器,用来监视用new创建的所有对象,并辨别那些不再被引用的对象,随后释放这些对象的内存空间。Java中的一些基本类型(String 不是基本类型)参照了C/C++的做法,也就是说不用new来创建变量,而是创建一个并非是引用的“自动”变量,这个变量直接存储“值”,并置于堆栈中,因此更加高效(堆栈的存储效率仅次于寄存器)。而new出来的对象存放在堆里(堆区存储分配效率不高,但是灵活性大)。
3、在方法(C/C++中称函数)的参数列表中必须指定每个所传递对象的类型及名字。这里的传递实际上也是引用。
4、随机数生成器
import java.util.Random; public class RandomTest { public static void main(String[] args) { //设置了种子(48位),则每次生成相同的伪随机序列 Random r=new Random(23); int j=r.nextInt(100); int i=r.nextInt(); boolean v=r.nextBoolean(); print(j); print(i); print(v); } public static void print(Object obj){ System.out.println(obj); } }
5、equals方法并不是判断两个对象的值相等,对象的值如何相等?equals方法是Object类提供的一个实例方法, 这个方法判断两个对象是否相等的标准和==没有区别(对于基本类型变量,且都是数值型,则只要两个变量的值相等,即返回true;对于引用类型变量,只有指向同一个对象时才返回true)String类已经重写了equals方法。
6、移位运算<<(左移) 将运算数的二进制码(计算机内部运算都是以补码形式,打印出来的值是转换成原码之后的值)整体左移指定位数, 右边空出来的以0补充。
>>(右移) 操作数右移后左边空出来的位以原来的符号位填充。
>>>(无符号右移) 操作数右移后左边空出来的位总是以0填充。
public class Test4 {
public static void main(String[] args) {
int i=-1;
print("i:"+Integer.toBinaryString(i)+" "+i);
i>>>=10;
print("i无符号右移10位:"+Integer.toBinaryString(i)+" "+i);//若计算结果为0001111则会省略前面的所有0
i>>=4;
print("i右移10位:"+Integer.toBinaryString(i)+" "+i);
i<<=4;
print("i左移10位:"+Integer.toBinaryString(i)+" "+i);
}
public static void print(Object obj){
System.out.println(obj);
} }
7、三元操作符
boolean-exp ? value0:value1
如:return i<10 ? i*10:i*100;
public class Test { static String ternary (int i){ return i<10?"i<10":"i>=10"; } static String ifelse (int i){ if(i<10){ return "i<10"; }else{ return "i>=10"; } } static void print(Object obj){ System.out.println(obj); } public static void main(String[] args) { print("ifelse():"+ifelse(11)); print("ternary():"+ternary(11)); } }
8、在执行窄化转换时,必须注意截尾与舍入的问题。float、double转为整型时,总是截尾,要想四舍五入,用java.lang.Math的round()方法。 Math.round(3.4)=3;Math.round(3.5)=4
对于char(16位)、byte(8位)、short(16位),在算术运算中自动提升为int类型,必须显式地将类型转换为原来的类型才能赋值给原来的变量。
9、Java中没有sizeof(),sizeof()告诉你为数据分配的字节数,C/C++中使用sizeof()是为了“移植”,因为不同的数据类型在不同的机器上可能有不同的大小。java中所有的数据类型在所有的机器中的大小都是一样的,不需要考虑移植问题,它已经被设计在语言中了。
10、Character.isLowerCase(c);判断c是否是小写字母。
11、for(int i=1,j=i+10;i<5;i++,j=i*2)//for语句中的初始化部分可以有任意数量的同一类型的定义。
12、Foreach语法(用于数组和容器)
// 例程1: public class Test5 { public static void main(String[] args) { Random rand=new Random(47); float f[]=new float[10]; for(int i=0;i<10;i++){ f[i]=rand.nextFloat(); } int i=0; for(float x:f){ System.out.println("x["+(i++)+"]="+x); } } } //例程2: public class Test { public static void main(String[] args) { for(char x:"niao peng".toCharArray()){ System.out.println(x+" "); } } }
13、Java中的标签(在Java中使用标签的唯一理由就是因为有嵌套循环的存在,而且想从多层嵌套中break或continue),break用于强行退出循环,不执行循环中剩余的语句;continue是停止执行当前的迭代,退回循环起始处开始下一次迭代。
public class Test { public static void main(String[] args) { int i = 0; outer: while (true) { System.out.println("Outer while loop"); while (true) { i++; System.out.println("i=" + i); if (i == 1) { System.out.println("Continue"); continue; } if (i == 3) { System.out.println("continue outer"); continue outer; } if (i == 5) { System.out.println("break"); break; } if(i==7){ System.out.println("break outer"); break outer; } } } } }14、switch()语句中的参数只能是整数值如int、char,每一个执行路径都得加break,否则继续执行下面的语句
switch(integral-selector){ case integral-value1:statement;break; case integral-value1:statement;break; ... default:statement; }15、Java是如何区分重载的方法:每个重载的方法必须有一个独一无二的参数类型列表(甚至参数的顺序不同也能区分两个方法,但是这样做使得代码难以维护),不可以用方法的返回类型不同来区分。基本类型参数传递给重载方法时可以将一个"较小"的类型自动提升至一个"较大"的类型。假如方法接受较小的基本类型参数,而实际传入的参数较大,则必须通过类型转换来窄化,否则编译器报错。
16、如果你没有显式的创建一个构造器,那么Java类会提供一个默认的无参的构造器。一旦你显式创建了构造器,则默认的构造器失效。编译器暗自把“所操作对象的引用”作为第一个参数传递给方法。通过this关键字可以获得对当前对象的引用:谁在调用这个方法,this代表谁。除了构造器外(构造方法),编译器禁止在其它任何方法中调用构造器。在构造器中调用构造器,使用this关键字:this()
17、static
理解了this关键字后,我们可以完整理解static方法的含义。static方法是类所拥有的方法,不属于任何对象,我们不可以从static方法 方法内部发出对非static方法的调用。
18、Java里的对象并非总是被垃圾回收,如果Java虚拟机(JVM)并未面临内存耗尽的情形,它是不会浪费时间去执行垃圾回收以恢复内存的。垃圾回收机制在回收任何对象之前总会调用它的finalize方法进行资源清理,如果系统在调用finalize方法时重新让一个引用变量引用该对象,则这个对象被激活,否则进入死亡状态,等待系统回收其占用的资源。
19、程序无法精确控制Java垃圾回收的时机,但程序员可以强制系统进行垃圾回收-只是建议系统进行垃圾回收,系统未必立即执行垃圾回收。
system.gc()/Runtime.getRuntime().gc();执行这些方法后会调用对象的finalize()方法。
public class TestFinalize { private static TestFinalize tf=null; public static void main(String[] args) throws InterruptedException { new TestFinalize (); System.gc(); Thread.sleep(4000);//这句话不能少,虽然显式调用了System.gc(),但是系统没有立即执行,程序暂停时才执行了垃圾回收 tf.showInfo(); } public void finalize() { tf=this; } public void showInfo(){ System.out.println("showInfo() has been called!"); } }
20、Java尽力保证:所有变量在使用前都能得到恰当的初始化。成员变量有默认初始化值,而局部变量需要显示初始化,否则编译器报错。在类的内部,变量定义的先后顺序决定了初始化的顺序:即使变量定义散布于方法间,它们仍然会在任何方法(包括构造器)被调用之前得到初始化(见例程)。总之,在类加载时,任何方法(包括构造器)被调用之前,类中的成员变量先执行了初始化工作。在成员变量的初始化中又以static变量先行初始化,实例属性(不以static修饰)后初始化,然后才执行构造器(也称构造函数、构造方法)。静态初始化只在Class对象首次加载的时候进行一次。
public class Test { public static void main(String[] args) { House h = new House(); h.print(); } } class Window { Window(int a) { System.out.println("Window(" + a + ")"); } } class House { Window window1 = new Window(1); public House() { System.out.println("House"); window3 = new Window(33); } Window window2 = new Window(2); void print() { System.out.print("zpc"); } Window window3 = new Window(3); }
21、初始化块(当创建Java对象时隐式执行,系统调用该类的初始化块)
static { int i=0; System.out.println("initialized"); }//该块只执行一次,即该类加载时,因此static修饰的初始化块总是普通块先执行 { int i=0; System.out.println("initialized"); }//每次实例化该类都执行
注:如果一段初始化代码对所有对象完全相同,且无需接受任何参数,则可以把这段代码提取到初始化块中。创建一个Java对象时,不仅会该类的普通初始化块和构造器,系统会一直上溯到java.lang.Object类,先依次执行java.lang.Object类的初始化块、构造器,再向下执行其父类的初始化块和构造器...直至最后才执行该类的初始化块和构造器,返回该类的对象。
22、Java系统加载并初始化某个类时,总是保证该类的所有父类(包括直接父类和间接父类)全部加载并初始化。先进行类初始化(静态成员初始化),再进行对象初始化(普通初始化块、实例变量、构造器)。
23、对象数组的定义
Integer[] b=new Integer[]{ new Integer(1),new Integer(2),3, };
24、可变参数(JDK1.5之后的新特性,无需显式地编写数组语法,当你指定参数时,编译器实际上会为你去填充数组,你获得的仍旧是一个数组)
public class Test { static void f(int require,String... args){ System.out.print("require:"+require); for(String s:args){ System.out.print(" "+s); } System.out.println(); } public static void main(String[] args) { f(1,"one"); f(2,"one","two"); f(0); } }注:可变形参只能处于参数列表的最后,一个方法最多包涵一个长度可变的形参。调用一个形参长度可变的方法时,除了可以传入多个参数,也可以直接传入数组,甚至不传参数。
25、枚举类(一个java源文件只能定义一个public访问权限的枚举类,而且该Java源文件必须和该枚举类同名)
注:枚举类的构造器只能使用private修饰(默认即为private,显式指定也只能是private,否则报错),枚举类的所有实例必须在枚举类中显式列出(系统自动添加public static final修饰这些实例),使用EnumClass.variable的形式使用该枚举类的某个实例
public enum SeasonEnum { SPRING,SUMMER,FALL,WINTER; }//enum关键字在某种程度上和class、interface关键字作用大致相似
枚举类也是类,也可以有成员变量、方法(包括构造器)
public enum SeasonEnum { SPRING("春天"),SUMMER("夏天"),FALL("秋天"),WINTER("冬天"); private String season; private SeasonEnum(String season){ this.season=season; } public String getSeason(){ return this.season; } public static void main(String[] args){ SeasonEnum se=Enum.valueOf(SeasonEnum.class, "FALL");//SeasonEnum se=FALL; System.out.println(se.getSeason()); se.season="春天"; System.out.println(se.getSeason()); } }