Thinking In Java琐碎知识点摘要(一)

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());
}
}

你可能感兴趣的:(java)