java细节,你注意到了多少?

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

1,位移运算越界怎么处理

考察下面的代码输出结果是多少?

int a=5;

System.out.println(a<<33);

按照常理推测,把a左移33位应该将a的所有有效位都移出去了,那剩下的都是零啊,所以输出结果应该是0才对啊,可是执行后发现输出结果是10,为什么呢?因为Java语言对位移运算作了优化处理,Java语言对a<转化为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这个值,在IEEE754浮点算术规则里保留了一个特殊的值用来表示一个不是数字的数量。这个值就是NaN("Not aNumber"的缩写),对于所有没有良好定义的浮点计算都将得到这个值,比如:0.0/0.0;其实我们还可以直接使用Double.NaN来得到这个值。在IEEE 754规范里面规定NaN不等于任何值,包括它自己。所以就有了i!=i的代码。职坐标www.zhizuobiao.com

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)浅复制与深复制概念

⑴浅复制(浅克隆)

被复制对象的所有变量都含有与原来的对象相同的值,而所有的对其他对象的引用仍然指向原来的对象。换言之,浅复制仅仅复制所考虑的对象,而不复制它所引用的对象。

⑵深复制(深克隆)

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

时间: 2024-10-10 20:06:13

java细节,你注意到了多少?的相关文章

每日一记--java细节之问01

现在越来越觉得java基础细节的重要性了,这样才有交流的价值. 1.静态变量与非静态变量的区别? ①分配的空间: 静态变量存在于虚拟机的方法区中,并且只有一份这样的内存空间. 非静态变量需要通过new出类实例才能够存在,且分配于堆内存空间中,每new出一份类实例便存在一份变量. ②使用的方法上: 静态变量的使用可以通过类名.变量进行调用. 非静态变量需要先创建类实例,然后通过类实例.变量进行调用. ③生命周期 静态变量的生命周期伴随程序的整个阶段. 非静态变量的生命周期伴随着类实例存在的生命周期

java细节

1. super() 与 this() 的区别? This():当前类的对象,super 父类对象. Super():在子类访问父类的成员和行为,必须受类继承规则的约束 而 this 他代表当前对象,当然所有的资源都可以访问. 在构造函数中,如果第一行没有写super(),编译器会自动插入. 但是如果父类没有不带参数 的构造函数,或这个函数被私有化了(用 private 修饰).此时你必须加入对父类的实例化构 造. 而 this 就没有这个要求,因为它本身就进行实例化的构造. 而在方法中 sup

Java细节1

1 import java.util.Scanner; 2 3 public class Demo01 { 4 public static void main(String[] args) { 5 Scanner sc=new Scanner(System.in);//创建一个扫描器对象,用于接收键盘数据 6 System.out.println("使用next方式接收:"); 7 if(scanner.hasNext()){//判断用户有没有输入字符串,hasNextLine输入字符

java细节笔记(9月16)

1.泛型仅仅是java的语法糖,它不会影响java虚拟机生成的汇编代码,在编译阶段,虚拟机就会把泛型的类型擦除,还原成没有泛型的代码,顶多编译速度稍微慢一些,执行速度是完全没有什么区别的. 2.实现GBK编码字节流到UTF-8编码字节流的转换: 操作步骤就是先解码再编码 用new String(src,"GBK")解码得到字符串 用getBytes("UTF-8")得到UTF8编码字节数组 3.正确计算42度(角度)的余弦值 double d=Math.cos(Ma

java细节问题

保留两位小数:1.234, 1.23, 1.2, 1.0, 1. package test; import java.math.BigDecimal; import java.text.DecimalFormat; import java.text.NumberFormat; public class test { public static float test(float f){ String str=String.valueOf(f); float result = 0f; if(str.

Java细节问题总结

这篇博客是用来记录自己在写代码的过程中遇到的一些问题,以及解决方法,做一个总结,并且会一直更新,算是笔记吧. 1.问题描述: 在byte类型中,为什么0x4a不需要强转类型,而0xc2而必须进行强转,写成(byte) 0xc2 分析解答: 其实在byte类型的强转中远不是一个0xc2.我们要知道byte的最小值是-128,最大值是127.也就是说byte的数值大于0x7f就会溢出,这时就需要对其进行强转. 另一篇总结性博客:Android细节问题总结

Java细节整理——数组与内存控制

重点:使用Java数组之前,必须对数组对象进行初始化. 当数组的所有元素都被分配了合适的内存空间,并指定了初始值时,数组的初始化完成.程序以后将不能重新改变数组对象在内存中的位置和大小. 知识点整理: 1.数组的初始化有以下两种方式: 1)静态初始化:初始化时由程序员显示指定每个数组元素的初始值,由系统决定数组的长度. 2)动态初始化:初始化时程序员只指定数组的长度,由系统为数组元素分配初始值. 不管使用哪种方式初始化Java数组,一旦初始化完成,该数组的长度就不可改变. 代码示例: publi

java细节篇(==和equals的区别)

1)当==两边是对象时(String,Integer...),两边比的都是地址2)当==两边是基本类型时(int,float),两边比的都是值3)默认equals比的是对象的地址,但是重写的话可以改变成比较值,String和Integer的equals就是重写过的 废话少说,Run!!! package test; public class Test { public static void main(String[] args) { System.out.println("##########

Java提高篇(三六)-----java集合细节(二):asList的缺陷

在实际开发过程中我们经常使用asList讲数组转换为List,这个方法使用起来非常方便,但是asList方法存在几个缺陷: 一.避免使用基本数据类型数组转换为列表 使用8个基本类型数组转换为列表时会存在一个比较有味的缺陷.先看如下程序: public static void main(String[] args) { int[] ints = {1,2,3,4,5}; List list = Arrays.asList(ints); System.out.println("list'size:&