大小和占用空间不一样
大小和占用空间不一样是很正常的,硬盘分区的最小是以4k为计算单位的。就是说好像一个一个格子一样,这些格子比较大。 即使是一个文件写了一个字,它的大小不足1k,但是显示占用空间为4k
强转超出范围
byte b = 10;
b += 120; //130 -128,-127,-126
System.out.println(b);
b = -126
byte的最小值是-128,最大值是127,就好像一杯水的容量是有限的,当你杯子的水装满了,自然也就会溢出,127就好像是杯子最上面的那一层水,你只要加上一滴,就会溢出,流到杯子底部,而杯子的最底部就是-128。按照这种逻辑,你的120+10,也就是有3流到了底部,最底部是-128,被3覆盖了3,所以最后自然也就是-126了
Timer和TimerTask
打印结果
添加线程休眠后的代码打印结果
为什么两次执行结果不同,因为timer执行定时器中的任务时,是另外开辟了一条新的线程,主线程会继续往下面执行,这时常量xx的值还没有被改变,因此打印的都是red,而5秒后TimerTask任务执行完毕,这时xx的值才成为green,因此加上休眠时间,就可以让任务执行完成,修改常量的值,打印出green.(休眠的时间可以尽量比任务的时间长点.)
Timer和TimerTask
Timer是jdk中提供的一个定时器工具,使用的时候会在主线程之外起一个单独的线程执行指定的计划任务,可以指定执行一次或者反复执行多次。
TimerTask是一个实现了Runnable接口的抽象类,代表一个可以被Timer执行的任务。
文章参考
https://www.cnblogs.com/lingiu/p/3782813.html
https://www.cnblogs.com/xiaotaoqi/p/6874713.html
英文字母和中文汉字在不同字符集编码下的字节数
编码 | 英文字母/字节数 | 中文汉字/字节数 |
GB2312 | 1 | 2 |
GBK | 1 | 2 |
GB18030 | 1 | 2 |
ISO-8859-1 | 1 | 1 |
UTF-8 | 1 | 3 |
UTF-16 | 4 | 4 |
UTF-16BE | 2 | 2 |
UTF-16LE | 2 | 2 |
父类和子类的初始化关系(类的初始化顺序)
http://blog.51cto.com/zangweiren/94400
下面的程序会什么输出?
答案:
为什么:
首先,如果单纯的在一个类中运行main方法,那么并没有去初始化这个类, 所以只有这个类中的静态变量和静态代码块会执行(也就是初始化),其他的变量,构造代码块和构造方法都不会执行.
上面输出
但是一旦通过 new 关键字进行该对象的创建,那么所有的变量和代码块和构造方法都会按照类的执行顺序进行执行
在上面的基础上在类的里边再次 new 一个该对象,并且这个 对象是静态变量接收,这时就会对这个变量进行初始化,按照加载顺序再去家在这个类就应该先进行静态代码块的加载,但因为这个对象是静态的,所以就会先去加载变量,构造代码块和构造方法,等把这个对象创建完成,才会进行后边静态代码块的加载.
Another Example
根据上面的结论,初始化该类的时候因为有static的对象初始化,所以会先调用构造方法,a的默认值是0,b初始值设为0,自++后都为1,构造方法执行完成后,会对a和b两个变量重新加载,因为b再次赋值为0,所以输出结果为下图
可变参数
在JDK1.5之后,如果我们定义一个方法需要接受多个参数,并且多个参数类型一致,我们可以对其简化成如下格式:
修饰符 返回值类型 方法名(参数类型... 形参名){ }
其实这个书写完全等价与
修饰符 返回值类型 方法名(参数类型[] 形参名){ }
只是后面这种定义,在调用时必须传递数组,而前者可以直接传递数据即可。
jdk1.5以后。出现了简化操作。... 用在参数上,称之为可变参数。
同样是代表数组,但是在调用这个带有可变参数的方法时,不用创建数组(这就是简单之处),直接将数组中的元素作为实际参数进行传递,其实编译成的class文件,将这些元素先封装到一个数组中,在进行传递。这些动作都在编译.class文件时,自动完成了。
上述add方法在同一个类中,只能存在一个。因为会发生调用的不确定性
注意:如果在方法书写时,这个方法拥有多参数,参数中包含可变参数,可变参数一定要写在参数列表的末尾位置。
ArrayList
https://www.cnblogs.com/zhaojinxin/p/6748009.html
初始化有三种方式
1.默认的构造器,将会以默认的大小来初始化内部的数组:public ArrayList();
2.用一个Collection对象来构造,并将该集合的元素添加到ArrayList: public ArrayList(Collection<? extends E> c)
3.用指定的大小来初始化内部的数组: public ArrayList(int initialCapacity)
初始容量:
在jdk1.6之前容量为10,在jdk1.7之后容量为0
发生扩容的条件:
根据传入的最小需要容量minCapacity来和数组的容量长度对比,若minCapactity大于或等于数组容量,则需要进行扩容。(如果实际存储数组是空数组,则最小需要容量就是默认容量)
这就是jdk定义的默认容量,为10个
实现扩容:
jdk7中采用>>位运算,右移动一位。 容量相当于扩大了1.5倍(1.5倍的说法是有道理的);
举例说明:添加20个元素到ArrayList中
当第一次插入元素时才分配10(默认)个对象空间。之后扩容会按照1.5倍增长。也就是当添加第11个数据的时候,Arraylist继续扩容变为10*1.5=15;当添加第16个数据时,继续扩容变为15 * 1.5 =22个;(讲解: 因为采用右移位运算,所以数组底层会创建一个新的集合,长度为 15+15>>1==22.5,但是因为接受类型是int类型,会丢失精度,所以扩容后的长度应该为22)
总结:
在JDK1.7中,如果通过无参构造的话,初始数组容量为0,当真正对数组进行添加时,才真正分配容量。每次按照1.5倍(位运算)的比率通过copeOf的方式扩容。 有参构造的话,会按照 初始容量的1.5倍(位运算)的比率通过copeOf的方式扩容.用一个Collection对象来构造的话,会按照Collection对象长度的1.5倍(位运算)的比率通过copeOf的方式扩容.
在JKD1.6中,如果通过无参构造的话,初始数组容量为10.每次通过copeOf的方式扩容后容量为原来的1.5倍加1.(有参构造未测试)
https://blog.csdn.net/yang1464657625/article/details/59109133/
ArrayList:本质通过内部维护的数组对象进行数据存储,elementData:ArrayList真正用于存储元素的数组
关于ArrayList在循环时对元素进行删除
http://www.cnblogs.com/flotang/p/9216098.html
1.CopyOnWriteArrayList线程安全删除(移除完毕后可以使用Arraylist通过Collection对象构造的方法把数组赋值给原来的数组对象)
CopyOnWriteArrayList既可以在遍历的时候进行删除操作,也可以进行添加操作!
2.迭代器remove方法删除(推荐)注意使用迭代器的移除方法,不是ArrayList的移除方法
Java中equals和==的区别
java中的数据类型,可分为两类:
1.基本数据类型,也称原始数据类型。byte,short,char,int,long,float,double,boolean
他们之间的比较,应用双等号(==),比较的是他们的值。
2.复合数据类型(类)
当他们用(==)进行比较的时候,比较的是他们在内存中的存放地址,所以,除非是同一个new出来的对象,他们的比较后的结果为true,否则比较后结果为false。 JAVA当中所有的类都是继承于Object这个基类的,在Object中的基类中定义了一个equals的方法,这个方法的初始行为是比较对象的内存地 址,但在一些类库当中这个方法被覆盖掉了,如String,Integer,Date在这些类当中equals有其自身的实现,而不再是比较类在堆内存中的存放地址了。
对于复合数据类型之间进行equals比较,在没有覆写equals方法的情况下,他们之间的比较还是基于他们在内存中的存放位置的地址值的,因为Object的equals方法也是用双等号(==)进行比较的,所以比较后的结果跟双等号(==)的结果相同。
超类Object类中的equals方法
String类中重写的equals方法
Object类的equals和==初始时都是比较对象在内存中的地址值的,如果地址值不相同直接返回false,但是String会重写equals方法,使用equals时首先判断两者的地址值是否相同,不相同就判断传递的对象是为字符串,不是返回false,如果是字符串就对象该对象进行强转为字符串类型,然后判断两者的长度是否相同,不相同就返回false,相同就判断两者的值(内容)是否相同,然后根据结果返回true或者false.