Java构造函数的陷阱,从CharArrayReader分析
如题,c++中比如有:
class XXX{ private: int * arr ; int arrLen; public: XXX(YYY & other){ new一块内存,保存到arr中 把other的一块内存里的数据复制到当前的arr里; } }
如果arrLen非常大,那么用这种拷贝构造就执行了很多内存里的拷贝:
Bar y = 内含一个大数组 ; Foo x(y);
但是之后y没用了,我们只想用x进行操作,那就离谱了,明明只需要Foo类实现一些Bar没有的功能,却必须进行内存拷贝!
在c++中解决这个问题的办法可以是强制move(),定义移动构造函数,这样编译器就能匹配到正确的构造函数,在正确的场合做正确的事。
而java呢,就比较简单粗暴了!很多的类构造起来非常简单,根本不考虑那么多,直接让成员变量指向外部的变量,而且不默认外部的变量不可变,也不保证传入该方法后不会修改!这也就默认了你在用char buf【】构造了CharArrayReader以后就不要在用原始的数组了!是个陷阱!
一段有问题的代码:
public class Main { public static void main(String[] args) throws IOException { char[] ret = new char[8]; char[] arr = new char[8]; Arrays.fill(arr, a); CharArrayReader charArrayReader = new CharArrayReader(arr); charArrayReader.read(ret,0,8); for (char c : ret) { System.out.printf("%c", c); } // aaaaaaaa //修改arr Arrays.fill(arr,b); //还原游标! charArrayReader.reset(); System.out.println(); charArrayReader.read(ret,0,8); for (char c : ret) { System.out.printf("%c", c); } // bbbbbbbb } }
总结: java中因为没有明确的规定,所以看清楚构造方法里是执行的拷贝还是直接引用传入的变量十分重要!
上一篇:
IDEA上Java项目控制台中文乱码