当前位置导航:炫浪网>>网络学院>>编程开发>>JAVA教程>>Java入门

java中值得注意的问题

  Java作为一门优秀的面向对象的程序设计语言,正在被越来越多的人使用。本文试图列出作者在实际开发中碰到的一些Java语言的容易被人忽视的细节,希望能给正在学习Java语言的人有所帮助。

  1,位移运算越界怎么处理考察下面的代码输出结果是多少?

  int a=5;System.out.println(a < <33);按照常理推测,把a左移33位应该将a的所有有效位都移出去了,那剩下的都是零啊,所以输出结果应该是0才对啊,可是执行后发现输出结果是10,为什么呢?因为Java语言对位移运算作了优化处理,Java语言对a < <b转化为a < <(b%32)来处理,所以当要移位的位数b超过32时,实际上移位的位数是b%32的值,那么上面的代码中a < <33相当于a < <1,所以输出结果是10。

  2,可以让i!=i吗?

  当你看到这个命题的时候一定会以为我疯了,或者Java语言疯了。这看起来是绝对不可能的,一个数怎么可能不等于它自己呢?或许就真的是Java语言疯了,不信看下面的代码输出什么?

  double i=0.0/0.0;if(i==i){System.out.println("Yes i==i");}else{System.out.println("No i!=i");}

  上面的代码输出"No i!=i",为什么会这样呢?关键在0.0/0.0这个值,在IEEE 754浮点算术规则里保留了一个特殊的值用来表示一个不是数字的数量。这个值就是NaN("Not a Number"的缩写),对于所有没有良好定义的浮点计算都将得到这个值,比如:0.0/0.0;其实我们还可以直接使用Double.NaN来得到这个值。在IEEE 754规范里面规定NaN不等于任何值,包括它自己。所以就有了i!=i的代码。

  3,怎样的equals才安全?

  我们都知道在Java规范里定义了equals方法覆盖的5大原则:reflexive(反身性),symmetric(对称性),transitive(传递性),consistent(一致性),non-null(非空性)。那么考察下面的代码:

  public class Student{private String name;private int age;public Student(String name,int age){this.name=name;this.age=age;}

  public boolean equals(Object obj){if(obj instanceof Student){Student s=(Student)obj;if(s.name.equals(this.name) && s.age==this.age){return true;}

  }

  return super.equals(obj);}

  }

  你认为上面的代码equals方法的覆盖安全吗?表面看起来好像没什么问题,这样写也确实满足了以上的五大原则。但其实这样的覆盖并不很安全,假如Student类还有一个子类CollegeStudent,如果我拿一个Student对象和一个CollegeStudent对象equals,只要这两个对象有相同的name和age,它们就会被认为相等,但实际上它们是两个不同类型的对象啊。问题就出在instanceof这个运算符上,因为这个运算符是向下兼容的,也就是说一个CollegeStudent对象也被认为是一个Student的实例。怎样去解决这个问题呢?那就只有不用instanceof运算符,而使用对象的getClass()方法来判断两个对象是否属于同一种类型,例如,将上面的equals()方法修改为:

  public boolean equals(Object obj){if(obj.getClass()==Student.class){Student s=(Student)obj;if(s.name.equals(this.name) && s.age==this.age){return true;}

  }

  return super.equals(obj);}

  这样才能保证obj对象一定是Student的实例,而不会是Student的任何子类的实例。

  4,浅复制与深复制1)浅复制与深复制概念⑴浅复制(浅克隆)被复制对象的所有变量都含有与原来的对象相同的值,而所有的对其他对象的引用仍然指向原来的对象。换言之,浅复制仅仅复制所考虑的对象,而不复制它所引用的对象。

  ⑵深复制(深克隆)被复制对象的所有变量都含有与原来的对象相同的值,除去那些引用其他对象的变量。那些引用其他对象的变量将指向被复制过的新对象,而不再是原有的那些被引用的对象。换言之,深复制把要复制的对象所引用的对象都复制了一遍。

  2)Java的clone()方法⑴clone方法将对象复制了一份并返回给调用者。一般而言,clone()方法满足:

  ①对任何的对象x,都有x.clone() !=x//克隆对象与原对象不是同一个对象②对任何的对象x,都有x.clone().getClass()= =x.getClass()//克隆对象与原对象的类型一样③如果对象x的equals()方法定义恰当,那么x.clone().equals(x)应该成立。

  ⑵Java中对象的克隆①为了获取对象的一份拷贝,我们可以利用Object类的clone()方法。

  ②在派生类中覆盖基类的clone()方法,并声明为public。

  ③在派生类的clone()方法中,调用super.clone()。

  ④在派生类中实现Cloneable接口。

  请看如下代码:

  class Student implements Cloneable{String name;int age;Student(String name,int age){this.name=name;this.age=age;}

  public Object clone(){Object obj=null;try{obj=(Student)super.clone();//Object中的clone()识别出你要复制的是哪一个对象。

  }

  catch(CloneNotSupportedException e){e.printStackTrace();}

  return obj;}

  }

  public static void main(String[] args){Student s1=new Student("zhangsan",18);Student s2=(Student)s1.clone();s2.name="lisi";s2.age=20;System.out.println("name="+s1.name+","+"age="+s1.age);//修改学生2//后,不影响学生1的值。

  }

  说明:

  ①为什么我们在派生类中覆盖Object的clone()方法时,一定要调用super.clone()呢?在运行时刻,Object中的clone()识别出你要复制的是哪一个对象,然后为此对象分配空间,并进行对象的复制,将原始对象的内容一一复制到新对象的存储空间中。

  ②继承自java.lang.Object类的clone()方法是浅复制。以下代码可以证明之。

  class Teacher{String name;int age;Teacher(String name,int age){this.name=name;this.age=age;}

  }

  class Student implements Cloneable{String name;int age;Teacher t;//学生1和学生2的引用值都是一样的。

  Student(String name,int age,Teacher t){this.name=name;this.age=age;this.t=t;}

  public Object clone(){Student stu=null;try{stu=(Student)super.clone();}catch(CloneNotSupportedException e){e.printStackTrace();}

  stu.t=(Teacher)t.clone();return stu;}

  public static void main(String[] args){Teacher t=new Teacher("tangliang",30);Student s1=new Student("zhangsan",18,t);Student s2=(Student)s1.clone();s2.t.name="tony";s2.t.age=40;System.out.println("name="+s1.t.name+","+"age="+s1.t.age);//学生1的老师成为tony,age为40。

  }

  }

  那应该如何实现深层次的克隆,即修改s2的老师不会影响s1的老师?代码改进如下。

  class Teacher implements Cloneable{String name;int age;Teacher(String name,int age){this.name=name;this.age=age;}

  public Object clone(){Object obj=null;try{obj=super.clone();}catch(CloneNotSupportedException e){e.printStackTrace();}

  return obj;}

  }

  

共2页 首页 上一页 1 2 下一页 尾页 跳转到
相关内容
赞助商链接