Java编程思想——那些易被忽视的关键点(二)

1.Java中赋值操作,在将一个对象赋值给另一对象时,其实是对引用的赋值

class People{}
public static void main(String[] args)
{
   People p1 = new People();
   People p2 = new People();
   p2=p1;//及将p2的引用给p1,使得俩个引用指向同一个对象 

}

2.比较操作“==”比较的是俩个对象的引用是否相等;equals()比较的是对象的内容是否相等,但是不适用于基本类型。

3.逻辑操作中的短路问题:即一旦可以根据部分逻辑判断确定整个结果就不需要继续执行右边的逻辑判断了。这也就是为什么可以通过将较大概率满足的逻辑判断写在if()中左侧来提高代码运行效率的原因。

4.Java中的直接常量,放在变量的前或后边,方便编译器可以一眼认出是什么类型。

long 后缀大小写L
float 后缀大小写F
double 后缀大小写D
十六进制 前缀0X或0x,后续0~9的数字或大小写a~f
八进制 前缀0,后续0~7的数字

5.Java中提供了Integer和Long类的静态方法toBinaryString(),可将各类型转换为二进制输出

{
  short a=1;
  int b=15;
  System.out.println("a="+Integer.toBinaryString(a));//此时short会自动转换为int
  System.out.println("b="+Integer.toBinaryString(b));
}

6.数据的截尾与舍入,当浮点类型转化为int类型时不会出现四舍五入,即:

{
  float fa=0.7;
  float fb=0.4;
  int ia=(int)fa;
  int ib=(int)fb;
  System.out.print("ia="+ia+"  ib="+ib);
}
out:ia=0  ib=0
若要 四舍五入需要使用java.lang.Math中的round();
{
  float fa=0.7;
  float fb=0.4;
  int ia=(int)fa;
  int ib=(int)fb;
  System.out.print("ia="+Math.round(ia)+"  ib="+Math.round(ib));
}
out:ia=1  ib=1

7.Java中的标签,标签一般用在循环结构的前边,在Java中没有goto,但利用标签和continue、break可以做出同样的效果,continue [Lable]效果为结束执行后边的代码而回到标签包含的循环的初始继续执行;break [Lable]效果为结束标签包含的循环。需要注意的是标签在实际开发中比较少用,但是在一些情况使用标签可以得到比较好的体验。

public class LableUse{
  public static void main(String[] args)
 {
      int i=0;
      outer://标签位置
      where(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;
       }
      }
      }
  }
}
out:
Outer while loop
i=1
continue
i=2
i=3
continue outer
Outer while loop
i=4
i=5
break
Outer while loop
i=6
i=7
break outer

8.Java构造器(默认为静态方法),主要的目的是对类中的变量进行初始化。构造器有助于减少错误,并使代码易于阅读。new对象的时候,不但会获取所需的存储空间,也同时调用相应的构造器,在Java中“初始化”和“创建”是捆绑在一起不能分离的。注意的是构造器是不返回任何东西的,包括void。Java中有默认的构造器,即为无参构造器,因为如果没有这个构造器将不能new对象。但是如果在类中创建一个构造器就不会有默认构造器了,所以会出现如下问题:

class People{
    People(int i){
    }
}
class Test{
   public static void main(String[] args){
      People p=new People();//报错,因为现在只有一个带有int类型参数的构造器
      int num=9;
      People p2=new People(num);
   }
}

9.Java的传参:Java方法中的参数如果传的比预设小则会进行自动提升,若大则进行窄化转换,也就是向位数较小的格式转换。

10.this关键字,表示的是当前对象的引用。其在a.调用方法时和一般的引用的用法一样。作为方法的调用者,this也可以b.作为参数使用,另外也可以c.调用类的构造器(但是this只能调用一个构造器,且必须放在最起始处,否则就会报错)d.可以用this调用与参数变量同名的数据变量以区分俩者

class People{
   int i;
   public People(int i){
     this.i=i;//用this区分参数变量与数据成员
   }
}
需要注意的是在static修饰的方法中是不能使用this的。

11.Java垃圾回收,Java中的垃圾回收器只知道释放那些经由new分配的内存,所以它不知如何释放那些特殊的内存区域(即不是通过new获得的内存区域),所以Java提供了finalize()方法(此法主要用在清理通过本地方法获取的内存块,即其他语言写的代码,不建议过多使用),用以在垃圾回收前做一些重要的清理工作(但不同于C++中的析构函数)。在此需要理解三点:

  • 对象可能不被垃圾回收
  • 垃圾回收并不等于“析构”
  • 垃圾回收只与内存有关

垃圾回收器并不能完全代替析构函数

Java虚拟机没有采用其他系统的垃圾回收机制--引用计数器(可能出现对象应该被释放,但由于对象的循环引用导致计数不为0不能释放的现象),而是采用了“自适应的垃圾回收技术”。自适应的垃圾回收技术分为俩个部分:

  • “标记-清除”(通常用于对象稳定,垃圾回收效率低的情况):

      不在后台运行,需要将运行的程序暂停进行。从堆栈和静态存储区开始,遍历所有引用,进而找出所有的存活对象,并对这些存活的对象进行标记,此过程中不会进行回收,而是在将所有对象进行标记后再执行此动作,在清理中会将所有没有被标记的对象释放,过程中不会产生任何的复制操作。

  • “停止-复制”(通常用于堆空间出现大量碎片的情况):

      不在后台运行,需要将运行的程序暂停进行。内存分配是以较大的“块”为单位的(每个块都由对应的代数进行记录,若对象被引用,其代数就被增加),如果对象较大会占用单独的块。此操作要求在释放旧有的对象前,必须将所有存活的对象复制到新堆。大型对象基本不会被复制,而内含许多小的对象的块会被复制整理。

由于俩个部分各有针对性,所以Java虚拟机会对各个引用和内存区域进行监视,以在合适的情况执行合适的操作。

猜你喜欢

转载自blog.csdn.net/goodli199309/article/details/79803025