java中请java 写出文件一个使i>jlli<=j 不成立的数

"java 中通用的方法和准则 1. 不要让常量和变量中出现易混淆的字母 比如: long i = 1l; 别人很难一下子看清楚是 11 还是 1l,所以应该这样写 1L。 命名规范: 1. 包名全部小写 2. 类名首字母大写 3. 方法名称,首字母小写,后面单词首字母大写 4. 常量要用大写,并且用 ...."
黑客派 9280 号会员
编写高质量代码: 改善 Java 程序的 151 个建议 - 学习笔记
java 中通用的方法和准则
1. 不要让常量和变量中出现易混淆的字母
比如: long i = 1l;
别人很难一下子看清楚是 11 还是 1l,所以应该这样写 1L。
命名规范: 1. 包名全部小写 2. 类名首字母大写 3. 方法名称,首字母小写,后面单词首字母大写 4. 常量要用大写,并且用下划线隔开 5. 变量要用小写
2. 莫让常量蜕变成变量
interface Const {public static final int RANDOM_NUM = new Random().nextInt(10);}
&span class="hljs-keyword"&for&/span& (&span class="hljs-keyword"&int&/span& j = &span class="hljs-number"&0&/span&; j & &span class="hljs-number"&5&/span&; j++) {
Log.i(&span class="hljs-string"&"clp"&/span&, &span class="hljs-string"&"num ="&/span& + Const.RANDOM_NUM);
}&/code&&/pre&
上面的代码,每次运行值都会不一样。RE: 只有在值固定的时候,才考虑用 final。否则轻易不要用。 static 有时候在临时保存数据的时候会用到。3. 三元操作符的类型务必一致 int i = 80;String s1 = String.valueOf(i & 100 ? 90 : 100);String s2 = String.valueOf(i & 100 ? 90 : 100.0);Log.i("clp", "s1=" + s1);Log.i("clp", "s2=" + s2); I/clp: s1=90I/clp: s2=90.0规则: 1. 如果 2 个类型不能相互转换,就返回 Object 类型 2. 如果是明确类型的表达式 (比如变量),则 int 类型转为 long,long 类型转为 float …还有其他规则4. 避免带有边长参数的方法重载
public int getCount(int type, int i, int j) {return i +}
&span class="hljs-keyword"&public&/span& &span class="hljs-keyword"&int&/span& &span class="hljs-title"&getCount&/span&(&span class="hljs-keyword"&int&/span& type, &span class="hljs-keyword"&int&/span&... &span class="hljs-keyword"&value&/span&) {
&span class="hljs-keyword"&int&/span& count = &span class="hljs-number"&0&/span&;
&span class="hljs-keyword"&for&/span& (&span class="hljs-keyword"&int&/span& i : &span class="hljs-keyword"&value&/span&) {
&span class="hljs-keyword"&return&/span&
Log.i(&span class="hljs-string"&"clp"&/span&, &span class="hljs-string"&"count="&/span& + getCount(&span class="hljs-number"&1&/span&, &span class="hljs-number"&3&/span&, &span class="hljs-number"&4&/span&));&/code&&/pre&
上面的代码,很容易搞混,可能不分析具体原因,不知道会调用那个。 RE: 其实会调用 int 参数的那个,因为编译器从最简单的开始。I/clp: count=75. 不要让 null 或者空值影响到边长方法
public void methodA(String name, Integer... value) {
&span class="hljs-keyword"&public&/span& &span class="hljs-keyword"&void&/span& &span class="hljs-title"&methodA&/span&(String name, String... &span class="hljs-keyword"&value&/span&) {
methodA(&span class="hljs-string"&"a"&/span&, &span class="hljs-number"&1&/span&, &span class="hljs-number"&2&/span&);
methodA(&span class="hljs-string"&"b"&/span&, &span class="hljs-string"&"e"&/span&, &span class="hljs-string"&"e"&/span&);
methodA(&span class="hljs-string"&"c"&/span&);&span class="hljs-comment"&//编译器报错&/span&
methodA(&span class="hljs-string"&"c"&/span&, &span class="hljs-keyword"&null&/span&);&span class="hljs-comment"&//编译器报错&/span&&/code&&/pre&
上面解决的办法是传入空的 String。 RE: 我感觉最好的办法是,避免这种写法,遇到这种情况,不要去重载。基本类型27. 谨慎包装类型的大小比较Integer i = new Integer(2);Integer j = new Integer(2);28. 优先使用整形池
int input = 127;Integer ii = new Integer(input);Integer jj = new Integer(input);Log.i("clp", "new 产生的对象:" + (ii == jj));ii =jj =Log.i("clp", "基本类型产生的对象" + (ii == jj));ii = Integer.valueOf(input);jj = Integer.valueOf(input);Log.i("clp", "valueOf 产生的对象" + (ii == jj));1.new 产生的对象比较,肯定为 false 2. 自动装箱和 Integer.valueOf 一样 (装箱时通过 valueOf 实现) 3.valueOf 的实现方式,在 -128 和 127 之间,使用的是缓冲。超过的话,直接 new
public static Integer valueOf(int i) {final int offset = 128;if (i & -128 && i & 127) {return IntegerCache.cache[i + offset];}return new Integer(i);}29. 优先使用基本类型 int i = 14;f(i);f(Integer.valueOf(i)); &span class="hljs-keyword"&public&/span& &span class="hljs-keyword"&static&/span& &span class="hljs-keyword"&void&/span& &span class="hljs-title"&f&/span&(&span class="hljs-keyword"&long&/span& i) {
Log.i(&span class="hljs-string"&"clp"&/span&, &span class="hljs-string"&"基本类型的方法被调用"&/span&);
&span class="hljs-keyword"&public&/span& &span class="hljs-keyword"&static&/span& &span class="hljs-keyword"&void&/span& &span class="hljs-title"&f&/span&(Long i) {
Log.i(&span class="hljs-string"&"clp"&/span&, &span class="hljs-string"&"包装的方法被调用"&/span&);
}&/code&&/pre&
输出结果: Log.i(“clp”, “基本类型的方法被调用”); Log.i(“clp”, “基本类型的方法被调用”);解析:1. 自动装箱只有在赋值时才有关系,重载可以编译通过 2.f(i) 不会报错,因为编辑器会自动把 i 加宽,变为 long 3.f(Integer.valueOf(i)) 不会报错: 基本类型,可以先加宽在包装。但是不能直接包装。所以 1. 先转变为 Integer 对象,然后调用方法的时候发现没有,自动转换为 int 基本类型 3. 发现没有,自动加宽变为 long 4. 如果把 f(long i) 方法给注释掉,代码是编译不通过的30. 不要随便设置随机种子Random random = new Random(1000);for (int i = 0; i & 4; i++) {CldLog.i("clp", "第" + i + "次的随机数为:" + random.nextInt());}RE: 按照上面的代码写,每次运行都会得到想通的随机数。通过 Random random = new Random(),则不能固定范围 04-15 11:35:44.565 /cld.navi.mainframe I/clp: 第 0 次的随机数为:- @initControls:CldModeA.java(72) 04-15 11:35:44.565 /cld.navi.mainframe I/clp: 第 1 次的随机数为: @initControls:CldModeA.java(72) 04-15 11:35:44.565 /cld.navi.mainframe I/clp: 第 2 次的随机数为:- @initControls:CldModeA.java(72) 04-15 11:35:44.565 /cld.navi.mainframe I/clp: 第 3 次的随机数为: @initControls:CldModeA.java(72)正确写法如下:
Random random = new Random();for (int i = 0; i & 4; i++) {CldLog.i("clp", "第" + i + "次的随机数为:" + random.nextInt(20));}类、对象及方法31. 接口中不要存在实现代码RE: 这个都知道32. 静态变量一定要先声明后赋值
static {i = 100;}public static int i = 1;public static int i = 1;static {i = 100;}1. 静态变量是类加载的时候分配到存储区的 2. 静态变量在类初始化的时候首先被加载,分配地址空间,还没赋值 3. 按照静态类和静态块的先后顺序赋值,所以谁的位置在后面,谁有最终的决定权33. 不要复写静态方法public class Base { &span class="hljs-keyword"&public&/span& &span class="hljs-keyword"&static&/span& &span class="hljs-keyword"&void&/span& &span class="hljs-title"&doBaseStatic&/span&() {
Log.i(&span class="hljs-string"&"clp"&/span&, &span class="hljs-string"&"doBaseStatic"&/span&);
&span class="hljs-keyword"&public&/span& &span class="hljs-keyword"&void&/span& &span class="hljs-title"&doBase&/span&() {
Log.i(&span class="hljs-string"&"clp"&/span&, &span class="hljs-string"&"doBase No Static"&/span&);
}public class Sub extends Base {
&span class="hljs-keyword"&public&/span& &span class="hljs-keyword"&static&/span& &span class="hljs-keyword"&void&/span& &span class="hljs-title"&doBaseStatic&/span&() {
Log.i(&span class="hljs-string"&"clp"&/span&, &span class="hljs-string"&"do Sub Static"&/span&);
&span class="hljs-keyword"&public&/span& &span class="hljs-keyword"&void&/span& &span class="hljs-title"&doBase&/span&() {
Log.i(&span class="hljs-string"&"clp"&/span&, &span class="hljs-string"&"do Sub No Static"&/span&);
Base mBase = new Sub();mBase.doBase();Base.doBaseStatic();mBase.doBaseStatic();Sub.doBaseStatic();1.mBase.doBaseStatic() 实际上调用的是父类的方法。因为静态方法不依赖实例对象,是通过类名访问的34. 构造函数尽量简化public abstract class Server {
&span class="hljs-keyword"&public&/span& &span class="hljs-keyword"&static&/span& &span class="hljs-keyword"&int&/span& DEFAULT_PORT = &span class="hljs-number"&4000&/span&;
&span class="hljs-keyword"&public&/span& &span class="hljs-title"&Server&/span&() {
Log.i(&span class="hljs-string"&"clp"&/span&, &span class="hljs-string"&"Server"&/span&);
&span class="hljs-keyword"&int&/span& port = getPort();
Log.i(&span class="hljs-string"&"clp"&/span&, &span class="hljs-string"&"port="&/span& + port);
&span class="hljs-keyword"&protected&/span& &span class="hljs-keyword"&abstract&/span& &span class="hljs-keyword"&int&/span& &span class="hljs-title"&getPort&/span&();
}public class ServerIml extends Server {
&span class="hljs-keyword"&public&/span& &span class="hljs-keyword"&int&/span& port = &span class="hljs-number"&100&/span&;
&span class="hljs-keyword"&public&/span& &span class="hljs-title"&ServerIml&/span&(&span class="hljs-keyword"&int&/span& port) {
Log.i(&span class="hljs-string"&"clp"&/span&, &span class="hljs-string"&"ServerIml"&/span&);
&span class="hljs-keyword"&this&/span&.port =
&span class="hljs-annotation"&@Override&/span&
&span class="hljs-keyword"&protected&/span& &span class="hljs-keyword"&int&/span& &span class="hljs-title"&getPort&/span&() {
return DEFAULT_PORT;}}ServerIml serverIml = new ServerIml(80);这个跟构造方法的执行顺序有关。 04-15 14:35:54.027 /com.example.demo I/clp: Server 04-15 14:35:54.027 /com.example.demo I/clp: port=4000 04-15 14:35:54.027 /com.example.demo I/clp: ServerIml执行顺序如下: 1. 子类的构造函数接收 int 类型的参数 (没有赋值) 2. 父类初始化常量,也就是 DEFAULT_PORT,并赋值为 4000 3. 执行父类无参的构造方法 4. 调用 int port = getPort(); 获取端口号 ,调用子类端口号的实现方法。此时 DEFAULT_PORT 已经有值,但是 port 子类的 构造函数还没有执行,所以没有赋值,返回 0 5. 父类初始化完毕,开始初始化子类 6. 子类被赋值为 100 7. 执行子类的构造函数,重新赋值为 8035. 避免在构造函数中初始化其他类public class Son extends Father {
&span class="hljs-keyword"&public&/span& &span class="hljs-keyword"&void&/span& &span class="hljs-title"&doSomeThing&/span&() {
Log.i(&span class="hljs-string"&"clp"&/span&, &span class="hljs-string"&"doSomeThing"&/span&);
}public class Father {
Father() {
&span class="hljs-keyword"&new&/span& Other();
}public class Other {
&span class="hljs-keyword"&new&/span& Son();
}Son son = new Son(); son.doSomeThing();上面的代码,直接回导致程序死掉。陷入死循环。36. 使用构造代码块精炼程序代码块: 1. 使用 static{} 的静态代码块。类创建的时候加载 2. 方法后面 {} 的普通代码块,必须通过调用方法名称使用 3.synchronize 修饰的同步代码块 4. 构造代码块,在类中没有任何修饰,直接使用 {}public class CldGouzaoUtil {{Log.i("clp", "构造代码块");}
&span class="hljs-keyword"&public&/span& &span class="hljs-title"&CldGouzaoUtil&/span&() {
Log.i(&span class="hljs-string"&"clp"&/span&, &span class="hljs-string"&"构造方法"&/span&);
}04-15 14:59:55.597 /com.example.demo I/clp: 构造代码块 04-15 14:59:55.597 /com.example.demo I/clp: 构造方法构造代码块,不同于 static 代码块,它是依赖于构造方法执行。所以用途主要为 1. 初始化实例变量 2. 初始化实例环境 RE:2 个都是在构造方法执行前执行一些初始化、检测的操作。37. 构造代码块会想你所想public class CldGouzaoUtil {
&span class="hljs-keyword"&protected&/span& &span class="hljs-keyword"&static&/span& &span class="hljs-keyword"&int&/span& numOfNew = &span class="hljs-number"&0&/span&;
numOfNew++;
&span class="hljs-keyword"&public&/span& &span class="hljs-title"&CldGouzaoUtil&/span&() {
&span class="hljs-keyword"&public&/span& &span class="hljs-title"&CldGouzaoUtil&/span&(String mDes) {
&span class="hljs-keyword"&this&/span&();
&span class="hljs-keyword"&public&/span& &span class="hljs-keyword"&static&/span& &span class="hljs-keyword"&int&/span& &span class="hljs-title"&getNumOfNew&/span&() {
&span class="hljs-keyword"&return&/span& numOfN
new CldGouzaoUtil();new CldGouzaoUtil("haha");new CldGouzaoUtil("haha");Log.i("clp", "初始化的次数为:" + CldGouzaoUtil.getNumOfNew());04-15 15:31:37.737 /com.example.demo I/clp: 初始化的次数为:3new CldGouzaoUtil(“haha”) 这种构造函数调用 this 的,构造代码块也只会执行一次。而且只要不杀死程序,次数会一直保留。38. 使用静态内部类提高封装性public class CldInnerStatic {Spublic H
&span class="hljs-keyword"&private&/span& &span class="hljs-keyword"&static&/span& &span class="hljs-keyword"&int&/span& outer = &span class="hljs-number"&100&/span&;
&span class="hljs-keyword"&public&/span& &span class="hljs-title"&CldInnerStatic&/span&(String name) {
&span class="hljs-keyword"&this&/span&.name =
&span class="hljs-keyword"&public&/span& &span class="hljs-keyword"&void&/span& &span class="hljs-title"&setHome&/span&(Home home) {
&span class="hljs-keyword"&this&/span&.home =
&span class="hljs-comment"&//不持有外部类的引用&/span&
&span class="hljs-comment"&//静态内部类不依赖外部类&/span&
&span class="hljs-keyword"&public&/span& &span class="hljs-keyword"&static&/span& &span class="hljs-keyword"&class&/span& Home {&span class="hljs-comment"&//静态内部类&/span&
&span class="hljs-keyword"&public&/span& S&span class="hljs-comment"&//地址&/span&
&span class="hljs-keyword"&public&/span& &span class="hljs-keyword"&int&/span&&span class="hljs-comment"&//家庭电话&/span&
&span class="hljs-keyword"&public&/span& &span class="hljs-title"&Home&/span&(String addr, &span class="hljs-keyword"&int&/span& tel) {
&span class="hljs-keyword"&this&/span&.addr =
&span class="hljs-keyword"&this&/span&.tel =
outer = 80;}}
&span class="hljs-keyword"&public&/span& &span class="hljs-keyword"&class&/span& Company {
&span class="hljs-comment"&//报错&/span&
CldInnerStatic innerStatic = new CldInnerStatic("张三");innerStatic.setHome(new CldInnerStatic.Home("上海", ));39. 使用匿名内部类的构造函数 List&String& mList = new ArrayList&&();List&String& mList2 = new ArrayList&&() {};
&span class="hljs-built_in"&List&/span&&span class="hljs-subst"&&&/span&&span class="hljs-built_in"&String&/span&&span class="hljs-subst"&&&/span& mList3 &span class="hljs-subst"&=&/span& &span class="hljs-literal"&new&/span& ArrayList&span class="hljs-subst"&&&&/span&() {
{&span class="hljs-comment"&//代码块&/span&
};&/code&&/pre&
第二种和第三种都是相当于匿名内部类 List mlist2 = new Sub();40. 匿名类的构造函数很特殊public class CldCalculator { {&span class="hljs-comment"&//在这里,计算出来的值就为0,在使用的地方就是正确的&/span&
setOperator();
Log.i(&span class="hljs-string"&"clp"&/span&, &span class="hljs-string"&"setOperator"&/span&);
&span class="hljs-keyword"&private&/span& &span class="hljs-keyword"&int&/span& i, j,
&span class="hljs-keyword"&public&/span& &span class="hljs-title"&CldCalculator&/span&() {
&span class="hljs-keyword"&public&/span& &span class="hljs-title"&CldCalculator&/span&(&span class="hljs-keyword"&int&/span& i, &span class="hljs-keyword"&int&/span& j) {
Log.i(&span class="hljs-string"&"clp"&/span&, &span class="hljs-string"&"CldCalculator"&/span&);
&span class="hljs-keyword"&this&/span&.i =
&span class="hljs-keyword"&this&/span&.j =
&span class="hljs-keyword"&protected&/span& &span class="hljs-keyword"&void&/span& &span class="hljs-title"&setOperator&/span&() {
result = i +
&span class="hljs-keyword"&public&/span& &span class="hljs-keyword"&int&/span& &span class="hljs-title"&getResult&/span&() {
&span class="hljs-keyword"&return&/span&
}public class SubCal extends CldCalculator {
{&span class="hljs-comment"&//在这里,计算出来的值就为0,在使用的地方就是正确的&/span&
setOperator();
Log.i(&span class="hljs-string"&"clp"&/span&, &span class="hljs-string"&"setOperator"&/span&);
&span class="hljs-keyword"&public&/span& &span class="hljs-title"&SubCal&/span&(&span class="hljs-keyword"&int&/span& i, &span class="hljs-keyword"&int&/span& j) {
} CldCalculator calculator = new CldCalculator(1, 2) {};Log.i("clp", "result=" + calculator.getResult());
CldCalculator calculator1 &span class="hljs-subst"&=&/span& &span class="hljs-literal"&new&/span& SubCal(&span class="hljs-number"&1&/span&, &span class="hljs-number"&2&/span&);
&span class="hljs-keyword"&Log&/span&&span class="hljs-built_in"&.&/span&i(&span class="hljs-string"&"clp"&/span&, &span class="hljs-string"&"calculator1="&/span& &span class="hljs-subst"&+&/span& calculator&span class="hljs-built_in"&.&/span&getResult());&span class="hljs-comment"&//结果为0&/span&&/code&&/pre&
两个结果不一样,因为匿名内部类的特殊处理机制。一般的类都是默认调用父类的无参构造。但是匿名类没有名字,直接由 构造代码块代替,直接调用了父类的同参构造方法。然后再调用自己的构造代码块。41. 让多继承成为现实使用内部类,巧妙的实现多继承public interface Father {int Strong();} public interface Mother {int kind();}public class FatherIml implements Father {@Overridepublic int Strong() {return 8;}}
public class MotherIml implements Mother {@Overridepublic int kind() {return 8;}}public class Son extends FatherIml implements Mother {@Overridepublic int Strong() {return super.Strong() + 2;}
&span class="hljs-annotation"&@Override&/span&
&span class="hljs-keyword"&public&/span& &span class="hljs-keyword"&int&/span& &span class="hljs-title"&kind&/span&() {
&span class="hljs-keyword"&return&/span& &span class="hljs-keyword"&new&/span& MotherIml() {
&span class="hljs-annotation"&@Override&/span&
&span class="hljs-keyword"&public&/span& &span class="hljs-keyword"&int&/span& &span class="hljs-title"&kind&/span&() {
&span class="hljs-keyword"&return&/span& &span class="hljs-keyword"&super&/span&.kind() - &span class="hljs-number"&2&/span&;&span class="hljs-comment"&//温柔比母亲少了2个点&/span&
Son son = new Son()Log.i("clp", "strong =" + son.Strong() + ";kind=" + son.kind())//结果:04-15 17:32:13.267 14610-14610/? I/clp: strong =1042. 让工具类不可实例化工具类的正确构建方式:1. 不能实例化 2. 不能继承public final class CldUtil {
&span class="hljs-keyword"&private&/span& &span class="hljs-title"&CldUtil&/span&() {
&span class="hljs-keyword"&throw&/span& &span class="hljs-keyword"&new&/span& Error(&span class="hljs-string"&"不要实例化我"&/span&);
}43. 避免对象的浅拷贝public class Person implements Cloneable {private Sprivate P
&span class="hljs-keyword"&public&/span& &span class="hljs-title"&Person&/span&(String name) {
&span class="hljs-keyword"&this&/span&.name =
&span class="hljs-keyword"&public&/span& &span class="hljs-title"&Person&/span&(String name, Person father) {
&span class="hljs-keyword"&this&/span&.name =
&span class="hljs-keyword"&this&/span&.father =
&span class="hljs-keyword"&public&/span& &span class="hljs-keyword"&void&/span& &span class="hljs-title"&setName&/span&(String name) {
&span class="hljs-keyword"&this&/span&.name =
&span class="hljs-keyword"&public&/span& &span class="hljs-keyword"&void&/span& &span class="hljs-title"&setFather&/span&(Person father) {
&span class="hljs-keyword"&this&/span&.father =
&span class="hljs-keyword"&public&/span& String &span class="hljs-title"&getName&/span&() {
&span class="hljs-keyword"&return&/span&
&span class="hljs-keyword"&public&/span& Person &span class="hljs-title"&getFather&/span&() {
&span class="hljs-keyword"&return&/span&
&span class="hljs-annotation"&@Override&/span&
&span class="hljs-keyword"&public&/span& Person &span class="hljs-title"&clone&/span&() {&span class="hljs-comment"&//对象的拷贝&/span&
Person p = &span class="hljs-keyword"&null&/span&;
&span class="hljs-keyword"&try&/span& {
p = (Person) &span class="hljs-keyword"&super&/span&.clone();
p.setFather(&span class="hljs-keyword"&new&/span& Person(p.getFather().getName()));&span class="hljs-comment"&//如果没有这句话,就是浅拷贝,加了这句话,就是深拷贝&/span&
} &span class="hljs-keyword"&catch&/span& (CloneNotSupportedException e) {
e.printStackTrace();
&span class="hljs-keyword"&return&/span&
Person father = new Person("父亲")Person p1 = new Person("大儿子", father)Person p2 = p1.clone()p2.setName("小儿子")//
p2.setFather(new Person("干爹"))p2.getFather().setName("干爹")Log.i("clp", "fist name=" + p1.getName() + ";father =" + p1.getFather().getName())Log.i("clp", "sec name=" + p2.getName() + ";father =" + p2.getFather().getName())使用浅拷贝 04-15 17:55:30.827 /com.example.demo I/clp: fist name= 大儿子;father = 干爹 04-15 17:55:30.827 /com.example.demo I/clp: sec name= 小儿子;father = 干爹 使用 p2.setFather(new Person(“干爹”)); 或者深拷贝 04-15 17:58:27.197 /com.example.demo I/clp: fist name= 大儿子;father = 父亲 04-15 17:58:27.197 /com.example.demo I/clp: sec name= 小儿子;father = 干爹44. 推荐使用序列化实现对象的拷贝public class Person implements Serializable {private static final long serialVersionUID = L;public Spublic P
&span class="hljs-keyword"&public&/span& &span class="hljs-title"&Person&/span&(String name) {
&span class="hljs-keyword"&this&/span&.name =
&span class="hljs-keyword"&public&/span& &span class="hljs-title"&Person&/span&(String name, Person person) {
&span class="hljs-keyword"&this&/span&.name =
&span class="hljs-keyword"&this&/span&.person =
&span class="hljs-keyword"&public&/span& String &span class="hljs-title"&getName&/span&() {
&span class="hljs-keyword"&return&/span&
&span class="hljs-keyword"&public&/span& &span class="hljs-keyword"&void&/span& &span class="hljs-title"&setName&/span&(String name) {
&span class="hljs-keyword"&this&/span&.name =
&span class="hljs-keyword"&public&/span& Person &span class="hljs-title"&getPerson&/span&() {
&span class="hljs-keyword"&return&/span&
&span class="hljs-keyword"&public&/span& &span class="hljs-keyword"&void&/span& &span class="hljs-title"&setPerson&/span&(Person person) {
&span class="hljs-keyword"&this&/span&.person =
public static &T extends Serializable& T clone(T obj) {T cloneObj = null;try {ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();ObjectOutputStream objectOutputStream = new ObjectOutputStream(byteArrayOutputStream);objectOutputStream.writeObject(obj);objectOutputStream.close();ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(byteArrayOutputStream.toByteArray());ObjectInputStream objectInputStream = new ObjectInputStream(byteArrayInputStream);cloneObj = (T) objectInputStream.readObject();objectInputStream.close();} catch (Exception e) {e.printStackTrace();}return cloneO}01-04 19:27:44.620 /.myapplicati I/clp: 名称: 小儿子; 父亲为: 父亲 01-04 19:27:44.620 /.myapplicati I/clp: 名称: 大儿子; 父亲为: 干爹45. 复写 equals 方法时不要识别不出自己public class Person {public S
&span class="hljs-keyword"&public&/span& &span class="hljs-title"&Person&/span&(String name) {
&span class="hljs-keyword"&this&/span&.name =
&span class="hljs-keyword"&public&/span& String &span class="hljs-title"&getName&/span&() {
&span class="hljs-keyword"&return&/span&
&span class="hljs-keyword"&public&/span& &span class="hljs-keyword"&void&/span& &span class="hljs-title"&setName&/span&(String name) {
&span class="hljs-keyword"&this&/span&.name =
&span class="hljs-annotation"&@Override&/span&
&span class="hljs-keyword"&public&/span& &span class="hljs-keyword"&boolean&/span& &span class="hljs-title"&equals&/span&(Object obj) {
&span class="hljs-keyword"&if&/span& (obj &span class="hljs-keyword"&instanceof&/span& Person) {
Person person = (Person)
&span class="hljs-comment"&//equalsIgnoreCase为忽略大小写&/span&
&span class="hljs-keyword"&return&/span& name.equalsIgnoreCase(person.getName());
}return super.equals(obj);}}
Person p1 = new Person("张三");Log.i("clp", "p1 is equals =" + p1.equals(p1));使用: return name.equalsIgnoreCase(person.getName().trim()); 01-04 19:41:01.360 /.myapplicati I/clp: p1 is equals =falsereturn name.equalsIgnoreCase(person.getName()); 01-04 19:41:48.420 /.myapplicati I/clp: p1 is equals =true46.equals 应该考虑 null 值情景接上面的例子,如果按照下面的方式判断,就会报错
Person p1 = new Person("张三");Person p2 = new Person(null);Log.i("clp", "p1 p2 is equals =" + p2.equals(p1));所以,应该按照下面的写:
@Overridepublic boolean equals(Object obj) {if (obj instanceof Person) {Person person = (Person)if (person.getName() == null || name == null) {return false;}return name.equalsIgnoreCase(person.getName());}return super.equals(obj);}47. 在 equals 中使用 getClass 进行类型判断接上面例子,如果有一个子类,代码如下:public class ManPerson extends Person {
&span class="hljs-keyword"&public&/span& &span class="hljs-keyword"&int&/span&
&span class="hljs-keyword"&public&/span& &span class="hljs-title"&ManPerson&/span&(String name, &span class="hljs-keyword"&int&/span& id) {
&span class="hljs-keyword"&this&/span&.name =
&span class="hljs-keyword"&this&/span&.id =
&span class="hljs-annotation"&@Override&/span&
&span class="hljs-keyword"&public&/span& &span class="hljs-keyword"&boolean&/span& &span class="hljs-title"&equals&/span&(Object obj) {
&span class="hljs-keyword"&if&/span& (obj &span class="hljs-keyword"&instanceof&/span& ManPerson) {
ManPerson person = (ManPerson)
&span class="hljs-keyword"&return&/span& &span class="hljs-keyword"&super&/span&.equals(obj) && person.id ==
&span class="hljs-keyword"&return&/span& &span class="hljs-keyword"&super&/span&.equals(obj);
}然后进行判断:
Person p1 = new Person("张三");ManPerson manPerson = new ManPerson("张三", 100);Log.i("clp", "p1 manPerson is equals =" + p1.equals(manPerson));结果是 true。这是因为 p1 为父类,所以使用了父类的 equals 方法进行判断。关键就是 equals 方法中使用了 instanceof。故修改如下:
@Overridepublic boolean equals(Object obj) {if (obj.getClass() != null && obj.getClass() == this.getClass()) {Person person = (Person)if (person.getName() == null || name == null) {return false;}return name.equalsIgnoreCase(person.getName());}return super.equals(obj);}48. 覆写 equals 方法必须覆写 hashCode 方法
Map&Person, Object& map = new HashMap&Person, Object&() {{put(new Person("张三"), new Object());}};Log.i("clp", "map has key=" + map.containsKey(new Person("张三")));上面方法,如果不覆写 hashCode,会返回 false。因为 map 是根据 hashCode 值决定数组的下标 (HashMap 底层是通过数组保存的)。如果不覆写,每一个对象都有一个 hasCode,自然会找不到所以 Person 类中添加如下方法:
@Overridepublic int hashCode() {return name.hashCode();}49. 推荐覆写 toString()原因是本身,此此方法返回的是对象引用的地址值。 01-04 21:29:51.320 /.myapplicati I/clp: person =.myapplication2.algorithm.Person@bd2e9
Person person = new Person("张三")Log.i("clp", "person =" + person.toString())01-04 21:29:12.490 /.myapplicati I/clp: person =name = 张三作用: 1. 声明友好类和包内访问常量 2. 为在包上标注注解提供便利 3. 提供包的整体注释说明51. 不要主动进行垃圾回收因为 System.gc 会停止所有的相应,去进行检测内存中是否有可回收的对象。可能会比较耗时,10S 或者 20S 也说不准。字符串52. 推荐使用 String 直接量赋值
String s1 = "张三";String s2 = "张三";String s3 = new String("张三");String s4 = s3.intern();Log.i("clp", "s1 s2 is equals=" + (s1 == s2));Log.i("clp", "s1 s3 is equals=" + (s1 == s3));Log.i("clp", "s1 s4 is equals=" + (s1 == s4));01-04 21:51:49.220 /.myapplicati I/clp: s1 s2 is equals=false 01-04 21:51:49.220 /.myapplicati I/clp: s1 s3 is equals=false 01-04 21:51:49.220 /.myapplicati I/clp: s1 s4 is equals=trueJava 为了避免产生大量的对象,内部有一个字符串池。创建字符串时,会先判断池子中是否有这个字符串,有就直接返回, 如果没有,就创建一个,丢到池子当中,并返回。 使用 new 创建,肯定是新建了一个对象。 intern 方法会检查当前的对象,在池子中是否有字面值相等的引用对象,如果有就返回池子中的对象,没有就放置到池子中,并返回。会不会有线程安全问题? String 是一个不可变对象。 1. 不可能有子类 2.String 中提供的方法中的返回值,都会新建一个对象,不会对原对象进行修改。要不要考虑垃圾回收? 字符串池,是保存子 JVM 的常量池当中,不会进行垃圾回收。53. 注意参数中传递的参数要求
//删除字符串public static String remove(String orgin, String sub) {return orgin.replaceAll(sub, "");}
Log.i("clp", "result =" + CldStringUtil.remove("好是好", "好"))Log.i("clp", "result =" + CldStringUtil.remove("$ 是 $", "$"))结果: 01-04 22:08:33.220 /.myapplicati I/clp: result = 是 01-04 22:08:33.220 /.myapplicati I/clp: result =是replaceAll 要求第一个参数是正则表达式。$ 这个符号在正则表达式中是字符串的结束位置。修改如下:
//删除字符串public static String remove(String orgin, String sub) {while (orgin.contains(sub)) {orgin = orgin.replace(sub, "");}return}54. 正确使用 String、StringBuffer、StringBuilder1.String 一旦创建,不可变 2.StringBuffer 是线程安全的,StringBuilder 是线程不安全的。 所以 StringBuffer 的性能要比 StringBuilder 低。 3. 性能方法,因为 String 每次都会新建,所以会远慢于 StringBuffer 和 StringBuilder55. 注意字符串的位置
String s1 = 1 + 2 + "abc";String s2 = "abc" + 1 + 2;Log.i("clp", "s1=" + s1);Log.i("clp", "s2=" + s2);01-05 06:40:30.540 /.myapplicati I/clp: s1=3abc 01-05 06:40:30.540 /.myapplicati I/clp: s2=abc121. 从左到右依次拼接 2. 只要遇到 String,则所有数据都转换为 String 类进行拼接 3. 如果是原始数据,则直接进行拼接,如果是对象,则调用 toString() 4. 在 + 表达式中,String 具有最高的优先级56. 自由选择字符串拼接方法
String s = "";long time = System.currentTimeMillis();for (int i = 0; i & 5000; i++) {s += "a";}long timeend = System.currentTimeMillis() -Log.i("clp", "time1 =" + timeend);
String a = "";
long time2 = System.currentTimeMillis();
for (int i = 0; i & 5000; i++) {
s = s.concat("a");
long timeend2 = System.currentTimeMillis() - time2;
Log.i("clp", "time1 =" + timeend2);
StringBuilder b = new StringBuilder();
long time3 = System.currentTimeMillis();
for (int i = 0; i & 5000; i++) {
b.append("a");
long timeend3 = System.currentTimeMillis() - time3;
Log.i("clp", "time1 =" + timeend3);
StringBuffer c = new StringBuffer();
long time4 = System.currentTimeMillis();
for (int i = 0; i & 5000; i++) {
c.append("a");
long timeend4 = System.currentTimeMillis() - time4;
Log.i("clp", "time1 =" + timeend4);
01-05 06:53:02.410 /.myapplicati I/clp: time1 =1160 01-05 06:53:04.070 /.myapplicati I/clp: time1 =1668 01-05 06:53:04.080 /.myapplicati I/clp: time1 =5 01-05 06:53:04.090 /.myapplicati I/clp: time1 =8书上说 concat 执行时间比直接添加少一倍。但是在我手机上测试为啥还要高???57. 推荐在复杂字符串操作中使用正则表达式public static int getCount(String word) {Pattern pattern = pile("\b\w+\b");Matcher matcher = pattern.matcher(word);int count = 0;while (matcher.find()) {count++;}return count;}
String s = "How are you !Good!";Log.i("clp", "count=" + CldStringUtil.getCount(s));01-05 07:10:17.220 /.myapplicati I/clp: count=458. 强烈建议使用 UTF 编码文件格式为 UTF-8
try {String s = "张三";byte[] b = s.getBytes("GBK");Log.i("clp", "string is =" + new String(b));Log.i("clp", "string is =" + new String(b, "GBK"));} catch (Exception e) {
}&/code&&/pre&
输出结果: 01-05 07:20:10.370 /.myapplicati I/clp: string is =???? 01-05 07:20:10.370 /.myapplicati I/clp: string is = 张三59. 对字符串排序持一种宽容的态度1. 使用 Arrays.sort 肯定不行,它是根据 UNICODE 代码表来排序的。2. 使用 Collator,但是只能包含常用的 7000 多个汉字。
String[] sortName = {"张三", "李四", "王五"}Comparator c = Collator.getInstance(Locale.CHINA)Arrays.sort(sortName, c)for (String str : sortName) {Log.i("clp", "name =" + str)}原因:java 使用 UNICODE 编码。 GB2312-&GB18030-&UNICODE数组和集合60. 性能考虑,数组是首选 public static int getCountArray(int[] list) {int sum = 0;long time = System.currentTimeMillis();for (int i = 0; i & list. i++) {sum += list[i];}long timeend = System.currentTimeMillis() -Log.i("clp", "array time is =" + timeend);return sum;} &span class="hljs-keyword"&public&/span& &span class="hljs-keyword"&static&/span& &span class="hljs-keyword"&int&/span& getCountList(List&Integer& list) {
&span class="hljs-keyword"&int&/span& &span class="hljs-keyword"&sum&/span& = &span class="hljs-number"&0&/span&;
&span class="hljs-keyword"&long&/span& time = System.currentTimeMillis();
&span class="hljs-keyword"&for&/span& (&span class="hljs-keyword"&int&/span& i = &span class="hljs-number"&0&/span&; i & list.size(); i++) {
&span class="hljs-keyword"&sum&/span& += list.get(i);&span class="hljs-comment"&//做了一次拆箱操作。Integer通过intValue方法自动转换为了int基本类型&/span&
&span class="hljs-keyword"&long&/span& timeend = System.currentTimeMillis() -
Log.i(&span class="hljs-string"&"clp"&/span&, &span class="hljs-string"&"data time is ="&/span& + timeend);
&span class="hljs-keyword"&return&/span& &span class="hljs-keyword"&sum&/span&;
}&/code&&/pre&
int[] data = new int[100000];for (int i = 0; i & data. i++) {data[i] = 2;}CldArrayUtil.getCountArray(data);List&Integer& list = new ArrayList&Integer&();for (int j = 0; j & 100000; j++) {list.add(2);}CldArrayUtil.getCountList(list);01-05 08:13:19.740 /.myapplicati I/clp: array time is =4 01-05 08:13:19.880 /.myapplicati I/clp: data time is =35 数组的效率是集合的 10 倍。这个说法是对的。61. 若有必要,使用变长数组
public static int[] expandArray(int[] data, int length) {if (length & 0) {length = 0;}return Arrays.copyOf(data, length);}
int[] data = new int[20];for (int i = 0; i & data. i++) { data[i] = 2; }data = CldArrayUtil.expandArray(data, 50);Log.i("clp", "length =" + data.length);Log.i("clp", "data[2]=" + data[2]);01-05 08:26:57.310 /.myapplicati I/clp: length =50 01-05 08:26:57.310 /.myapplicati I/clp: data[2]=262. 警惕数组的浅拷贝Arrays.copyOf 为数组的浅拷贝,如果是基本类型,直接拷贝值。如果是对象,拷贝的是引用地址。 所以如果改变拷贝后的对象的值,拷贝前的值也会发生变化。解决方式: 重新生成对象。63. 在明确的场景下,为集合指定初始容量1. 例如 ArrayList,如果不指定,初始容量为 10. 每次如果长度不够,就自动扩容到 1.5 倍。 所以,如果要指定一个长度为 50 的 List,最好直接指定容量
List&String& mlist = new ArrayList&&(50);for (int i = 0; i & 60; i++) {mlist.add("2");}Log.i("clp", "list size =" + mlist.size());01-05 19:23:08.320 /.myapplicati I/clp: list size =60Vector、HashMap、Stack 类似。64. 多种最值算法,适时选择
int[] data = new int[100000];for (int i = 0; i & data. i++) {data[i] = new Random().nextInt(10000);}int max = data[0];long time = System.currentTimeMillis();for (int i : data) {max = max & data[i] ? max : data[i];}long timeEnd = System.currentTimeMillis() -Log.i("clp", "timeEnd=" + timeEnd);Log.i("clp", "max data =" + max);01-05 19:35:47.690 /.myapplicati I/clp: timeEnd=6 01-05 19:35:47.690 /.myapplicati I/clp: max data = 9999
int[] data = new int[100000];for (int i = 0; i & data. i++) { data[i] = new Random().nextInt(10000); }//使用Arrays排序int max = data[0];long time = System.currentTimeMillis();Arrays.sort(data.clone());long timeEnd = System.currentTimeMillis() -Log.i("clp", "timeEnd=" + timeEnd);Log.i("clp", "max data =" + data[data.length - 1]);01-05 19:37:36.810 /.myapplicati I/clp: timeEnd=172 01-05 19:37:36.810 /.myapplicati I/clp: max data = 9281排序 10 万个数据,才有细微的差别。所以,小数据性能影响不大。用 Arrays.sort 排序代码可读性高一点。求第二大元素, 正常通过数据循环查找可以搞定,下面使用 TreeSet 实现 (过滤掉相同数据).
long time = System.currentTimeMillis();List&Integer& mList = Arrays.asList(data);TreeSet&Integer& ts = new TreeSet&Integer&(mList);int max = ts.lower(ts.last());long timeEnd = System.currentTimeMillis() -Log.i("clp", "timeEnd=" + timeEnd);Log.i("clp", "sec max data =" + max);01-05 19:42:18.750 /.myapplicati I/clp: timeEnd=1092 01-05 19:42:18.750 /.myapplicati I/clp: sec max data = 999865. 避开基本类型数组转换列表陷进
int[] data = new int[100000];for (int i = 0; i & data. i++) { data[i] = new Random().nextInt(10000); }List mList = Arrays.asList(data);Log.i("clp", "list size =" + mList.size());01-05 19:50:27.710 /.myapplicati I/clp: list size =1asList 需要输入一个泛型化的边长参数,基本类型是不能泛型化的,但是数组可以。所以上面就把数组泛型化为只有一个数组的。mList.get(0) 数据如下: 其他 7 个基本类型也有这个问题,所以如果要用,请使用包装类型。66.asList 方法产生的 List 对象不可更改
Integer[] data = new Integer[5];for (int i = 0; i & 5; i++) {data[i] = new Random().nextInt(10);}List&Integer& mList = Arrays.asList(data);mList.add(2);java.lang.RuntimeException: Unable to start activity ComponentInfo{old.pkg.com.myapplicati/newpkg.pkg.com.myapplication2.MainActivity}: java.lang.UnsupportedOperationExceptionat android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2279)at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2329)at android.app.ActivityThread.access$1100(ActivityThread.java:141)at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1242)因为通过 asList 产生的 List 不同于正常使用的 List,不能使用 add remove 方法。 只有 size toArray get set contains 五个方法可以用。List mList = Arrays.asList(1, 2, 3); 这种方式生成数组有巨大的隐患。67. 不同的列表选择不同的遍历方法 new Thread(new Runnable() {@Overridepublic void run() {List&Integer& mList = new ArrayList&&();for (int i = 0; i & 80 * 100; i++) {mList.add(new Random().nextInt(200));}long start = System.currentTimeMillis();int average = CldArrayUtil.average(mList);
&span class="hljs-keyword"&Log&/span&&span class="hljs-built_in"&.&/span&i(&span class="hljs-string"&"clp"&/span&, &span class="hljs-string"&"time ="&/span& &span class="hljs-subst"&+&/span& (System&span class="hljs-built_in"&.&/span&currentTimeMillis() &span class="hljs-subst"&-&/span& start) &span class="hljs-subst"&+&/span& &span class="hljs-string"&"ms"&/span&);
&span class="hljs-keyword"&Log&/span&&span class="hljs-built_in"&.&/span&i(&span class="hljs-string"&"clp"&/span&, &span class="hljs-string"&"average="&/span& &span class="hljs-subst"&+&/span& &span class="hljs-keyword"&average&/span&);
&span class="hljs-built_in"&List&/span&&span class="hljs-subst"&&&/span&&span class="hljs-built_in"&Integer&/span&&span class="hljs-subst"&&&/span& mList2 &span class="hljs-subst"&=&/span& &span class="hljs-literal"&new&/span& LinkedList&span class="hljs-subst"&&&&/span&();
for (int i &span class="hljs-subst"&=&/span& &span class="hljs-number"&0&/span&; i &span class="hljs-subst"&&&/span& &span class="hljs-number"&80&/span& &span class="hljs-subst"&*&/span& &span class="hljs-number"&100&/span&; i&span class="hljs-subst"&++&/span&) {
mList2&span class="hljs-built_in"&.&/span&add(&span class="hljs-literal"&new&/span& Random()&span class="hljs-built_in"&.&/span&nextInt(&span class="hljs-number"&200&/span&));
long start2 &span class="hljs-subst"&=&/span& System&span class="hljs-built_in"&.&/span&currentTimeMillis();
int average2 &span class="hljs-subst"&=&/span& CldArrayUtil&span class="hljs-built_in"&.&/span&&span class="hljs-keyword"&average&/span&(mList2);
&span class="hljs-keyword"&Log&/span&&span class="hljs-built_in"&.&/span&i(&span class="hljs-string"&"clp"&/span&, &span class="hljs-string"&"time2 ="&/span& &span class="hljs-subst"&+&/span& (System&span class="hljs-built_in"&.&/span&currentTimeMillis() &span class="hljs-subst"&-&/span& start2) &span class="hljs-subst"&+&/span& &span class="hljs-string"&"ms"&/span&);
&span class="hljs-keyword"&Log&/span&&span class="hljs-built_in"&.&/span&i(&span class="hljs-string"&"clp"&/span&, &span class="hljs-string"&"average2="&/span& &span class="hljs-subst"&+&/span& average2);
})&span class="hljs-built_in"&.&/span&start();&/code&&/pre&
使用 fori 循环
public static int average(List&Integer& list) {int sum = 0;for (int i = 0; i & list.size(); i++) {sum += list.get(i);}return sum / list.size();}01-05 21:07:22.310 /.myapplicati I/clp: time =8ms 01-05 21:07:22.310 /.myapplicati I/clp: average=98 01-05 21:07:23.280 /.myapplicati I/clp: time2 =929ms 01-05 21:07:23.280 /.myapplicati I/clp: average2=988000 个就是快 1S,80 万个就是 100S!!!!
public static int average(List&Integer& list) {int sum = 0;for (Integer i : list) {sum +=}return sum / list.size();}01-05 21:09:06.990 /.myapplicati I/clp: time =5ms 01-05 21:09:06.990 /.myapplicati I/clp: average=99 01-05 21:09:07.030 /.myapplicati I/clp: time2 =9ms 01-05 21:09:07.030 /.myapplicati I/clp: average2=98在手机上测试,使用 foreach 方法,消耗的时间差不多???ArrayList 实现了随机读取 (RandomAcess),而 LinkedList 实现了迭代器。书上建议通过判断是否有 RandomAcess
public static int average(List&Integer& list) {int sum = 0;if (list instanceof RandomAccess) {for (int i = 0; i & list.size(); i++) {sum += list.get(i);}} else {for (Integer i : list) {sum +=}}return sum / list.size();}01-05 21:11:53.070 /.myapplicati I/clp: time =4ms 01-05 21:11:53.070 /.myapplicati I/clp: average=98 01-05 21:11:53.130 /.myapplicati I/clp: time2 =12ms 01-05 21:11:53.130 /.myapplicati I/clp: average2=9868. 频繁插入和删除时用 LinkedListArrayList 和 LinkedList 性能比较添加: new Thread(new Runnable() {@Overridepublic void run() {List&String& mArrayList = new ArrayList&String&();for (int i = 0; i & 10; i++) {mArrayList.add("a");}long start = System.currentTimeMillis();for (int i = 0; i & 100000; i++) {mArrayList.add(2, "a");}Log.i("clp", "array list time =" + (System.currentTimeMillis() - start) + "ms");List&String& mLinkedList = new LinkedList&String&();
&span class="hljs-keyword"&for&/span& (&span class="hljs-keyword"&int&/span& i = &span class="hljs-number"&0&/span&; i & &span class="hljs-number"&10&/span&; i++) {
mLinkedList.add(&span class="hljs-string"&"a"&/span&);
&span class="hljs-keyword"&long&/span& start2 = System.currentTimeMillis();
&span class="hljs-keyword"&for&/span& (&span class="hljs-keyword"&int&/span& i = &span class="hljs-number"&0&/span&; i & &span class="hljs-number"&100000&/span&; i++) {
mLinkedList.add(&span class="hljs-number"&2&/span&, &span class="hljs-string"&"a"&/span&);
Log.i(&span class="hljs-string"&"clp"&/span&, &span class="hljs-string"&"linked list time ="&/span& + (System.currentTimeMillis() - start2) + &span class="hljs-string"&"ms"&/span&);
}).start();&/code&&/pre&
01-05 21:34:13.060 /.myapplicati I/clp: array list time =15847ms 01-05 21:34:13.170 /.myapplicati I/clp: linked list time =116ms10 万个数据的话,相差 100 倍。删除: new Thread(new Runnable() {@Overridepublic void run() {List&String& mArrayList = new ArrayList&String&();for (int i = 0; i & 10 * 10000; i++) {mArrayList.add("a");}long start = System.currentTimeMillis();while (mArrayList.size() & 0){mArrayList.remove(0);}Log.i("clp", "array list time =" + (System.currentTimeMillis() - start) + "ms");List&String& mLinkedList = new LinkedList&String&();
&span class="hljs-keyword"&for&/span& (&span class="hljs-keyword"&int&/span& i = &span class="hljs-number"&0&/span&; i & &span class="hljs-number"&10&/span& * &span class="hljs-number"&10000&/span&; i++) {
mLinkedList.add(&span class="hljs-string"&"a"&/span&);
&span class="hljs-keyword"&long&/span& start2 = System.currentTimeMillis();
&span class="hljs-keyword"&while&/span& (mLinkedList.size() & &span class="hljs-number"&0&/span&) {
mLinkedList.remove(&span class="hljs-number"&0&/span&);
Log.i(&span class="hljs-string"&"clp"&/span&, &span class="hljs-string"&"linked list time ="&/span& + (System.currentTimeMillis() - start2) + &span class="hljs-string"&"ms"&/span&);
}).start();&/code&&/pre&
01-05 21:37:58.600 /.myapplicati I/clp: array list time =15108ms 01-05 21:37:58.700 /.myapplicati I/clp: linked list time =13ms删除,性能相差 1000 倍。修改: new Thread(new Runnable() {@Overridepublic void run() {List&String& mArrayList = new ArrayList&String&();for (int i = 0; i & 10
10000; i++) {mArrayList.add("a");}long start = System.currentTimeMillis();for (int i = 0; i & 10
10000; i++) {mArrayList.set(10000, "b");}Log.i("clp", "array list time =" + (System.currentTimeMillis() - start) + "ms");List&String& mLinkedList = new LinkedList&String&();
&span class="hljs-keyword"&for&/span& (&span class="hljs-built_in"&int&/span& i = &span class="hljs-number"&0&/span&; i & &span class="hljs-number"&10&/span& * &span class="hljs-number"&10000&/span&; i++) {
mLinkedList.add(&span class="hljs-string"&"a"&/span&);
long start2 = System.currentTimeMillis();
&span class="hljs-keyword"&for&/span& (&span class="hljs-built_in"&int&/span& i = &span class="hljs-number"&0&/span&; i & &span class="hljs-number"&10&/span& * &span class="hljs-number"&10000&/span&; i++) {
mLinkedList.&span class="hljs-keyword"&set&/span&(&span class="hljs-number"&10000&/span&, &span class="hljs-string"&"b"&/span&);
&span class="hljs-built_in"&Log&/span&.i(&span class="hljs-string"&"clp"&/span&, &span class="hljs-string"&"linked list time ="&/span& + (System.currentTimeMillis() - start2) + &span class="hljs-string"&"ms"&/span&);
}).start();&/code&&/pre&
01-05 21:40:26.700 /.myapplicati I/clp: array list time =28ms 01-05 21:40:55.580 /.myapplicati I/clp: linked list time =28672ms总结: 频繁的删除和插入,使用 LinkedList。 如果频繁的获取和修改。使用 ArrayList69. 列表相等只需关系元素数据判断集合是否相等时,只需要判断元素是否相等即可。 ArrayList&String& mList = new ArrayList&String&();mList.add("a");
Vector&span class="hljs-subst"&&&/span&&span class="hljs-built_in"&String&/span&&span class="hljs-subst"&&&/span& mVList &span class="hljs-subst"&=&/span& &span class="hljs-literal"&new&/span& Vector&span class="hljs-subst"&&&/span&&span class="hljs-built_in"&String&/span&&span class="hljs-subst"&&&/span&();
mVList&span class="hljs-built_in"&.&/span&add(&span class="hljs-string"&"a"&/span&);
&span class="hljs-keyword"&Log&/span&&span class="hljs-built_in"&.&/span&i(&span class="hljs-string"&"clp"&/span&, &span class="hljs-string"&"is equals ="&/span& &span class="hljs-subst"&+&/span& mList&span class="hljs-built_in"&.&/span&&span class="hljs-keyword"&equals&/span&(mVList));&/code&&/pre&
01-06 06:56:50.610 /.myapplicati I/clp: is equals =trueequals 是在 AbstractList 中实现的,代码如下: public boolean equals(Object o) {if (o == this)return true;if (!(o instanceof List))return false;
ListIterator&E& e1 = listIterator();
ListIterator e2 = ((List) o).listIterator();
&span class="hljs-keyword"&while&/span& (e1.hasNext() && e2.hasNext()) {
E o1 = e1.next();
Object o2 = e2.next();
&span class="hljs-keyword"&if&/span& (!(o1==&span class="hljs-keyword"&null&/span& ? o2==&span class="hljs-keyword"&null&/span& : o1.equals(o2)))
&span class="hljs-keyword"&return&/span& &span class="hljs-keyword"&false&/span&;
&span class="hljs-keyword"&return&/span& !(e1.hasNext() || e2.hasNext());
}&/code&&/pre&
70. 子列表只是原列表的一个视图 List&String& mlist = new ArrayList&String&();mlist.add("A");mlist.add("B");ArrayList&String& mBList = new ArrayList&&(mlist);
&span class="hljs-built_in"&List&/span&&span class="hljs-subst"&&&/span&&span class="hljs-built_in"&String&/span&&span class="hljs-subst"&&&/span& mCList &span class="hljs-subst"&=&/span& mlist&span class="hljs-built_in"&.&/span&subList(&span class="hljs-number"&0&/span&, mlist&span class="hljs-built_in"&.&/span&size());
mCList&span class="hljs-built_in"&.&/span&add(&span class="hljs-string"&"C"&/span&);
&span class="hljs-keyword"&Log&/span&&span class="hljs-built_in"&.&/span&i(&span class="hljs-string"&"clp"&/span&, &span class="hljs-string"&"mlist mBlist is equals ="&/span& &span class="hljs-subst"&+&/span& mlist&span class="hljs-built_in"&.&/span&&span class="hljs-keyword"&equals&/span&(mBList));
&span class="hljs-keyword"&Log&/span&&span class="hljs-built_in"&.&/span&i(&span class="hljs-string"&"clp"&/span&, &span class="hljs-string"&"mlist mCList is equals ="&/span& &span class="hljs-subst"&+&/span& mlist&span class="hljs-built_in"&.&/span&&span class="hljs-keyword"&equals&/span&(mCList));&/code&&/pre&
01-06 07:18:39.990 /.myapplicati I/clp: mlist mBlist is equals =false 01-06 07:18:39.990 /.myapplicati I/clp: mlist mCList is equals =truesubList 是在原数组上进行操作。71. 推荐使用 subList 处理局部列表
List&String& mList = new ArrayList&String&();for (int i = 0; i & 100; i++) {mList.add("a");}mList.subList(20, 30).clear();Log.i("clp", "mList size =" + mList.size());01-06 07:28:51.470 /.myapplicati I/clp: mList size =9072. 生成子列表之后不要再操作原列表
List&String& mList = new ArrayList&String&();for (int i = 0; i & 100; i++) {mList.add("a");}List&String& mSubList = mList.subList(20, 30);mList.add("d");Log.i("clp", "mlist size =" + mList.size());Log.i("clp", "mSubList size =" + mSubList.size());java.lang.RuntimeException: Unable to start activity ComponentInfo {.myapplicati/.myapplication2.MainActivity}: java.util.ConcurrentModificationException操作子列表也有可能导致报错,如下:
List&String& mList = new ArrayList&String&()for (int i = 0mList.add("a")}List&String& mSubList = mList.subList(20, 30)List&String& mSubList2 = mList.subList(10, 30)mSubList.add("d")//
mSubList2.add("e")Log.i("clp", "mlist size =" + mList.size())Log.i("clp", "mSubList size =" + mSubList.size())Log.i("clp", "mSubList2 size =" + mSubList2.size())73. 使用 Comparator 进行排序public class Person implements Comparable&Person& { &span class="hljs-keyword"&public&/span& &span class="hljs-keyword"&int&/span&
&span class="hljs-keyword"&public&/span& S
&span class="hljs-keyword"&public&/span& Person(&span class="hljs-keyword"&int&/span& id, String name) {
&span class="hljs-keyword"&this&/span&.id =
&span class="hljs-keyword"&this&/span&.name =
&span class="hljs-keyword"&public&/span& &span class="hljs-keyword"&int&/span& compareTo(Person person) {
&span class="hljs-keyword"&if&/span& (person == &span class="hljs-keyword"&null&/span&) {
&span class="hljs-keyword"&return&/span& -&span class="hljs-number"&1&/span&;
&span class="hljs-keyword"&return&/span& Integer.valueOf(id).compareTo(Integer.valueOf(person.id));
List&Person& mList = new ArrayList&Person&();mList.add(new Person(2, "张二"));mList.add(new Person(1, "张一"));mList.add(new Person(4, "张四"));mList.add(new Person(3, "张三"));Collections.sort(mList);for (int i = 0; i & mList.size(); i++) {Log.i("clp", "index =" + i + ";name =" + mList.get(i).name);}使用 Comparator 可以拓展排序。
List&Person& mList = new ArrayList&Person&();mList.add(new Person(2, 440300, "张二"));mList.add(new Person(1, 440322, "张一"));mList.add(new Person(4, 440310, "张四"));mList.add(new Person(3, 440200, "张三"));mList.add(new Person(6, 440200, "张六"));mList.add(new Person(5, 440200, "张五"));Collections.sort(mList, new PerComparator());for (int i = 0; i & mList.size(); i++) {Log.i("clp", "index =" + i + ";cityId=" + mList.get(i).cityId + ";name =" + mList.get(i).name);}
public class PerComparator implements Comparator&Person& {@Overridepublic int compare(Person person, Person t1) {if (person.cityId & t1.cityId) {return 1;} else if (person.cityId == t1.cityId) {if (person.id & t1.id) {return 1;} else if (person.id == t1.id) {return 0;} else {return -1;}} else {return -1;}}}如果想实现倒序,直接使用: Collections.sort(mList, Collections.reverseOrder(new PerComparator()));
Collections.reverse(mList);---对排序之后的,进行倒序Comparable 实现默认排序。Comparator 可以实现拓展排序。1.indexOf 是通过 for 循环进行排序查找第一个符合条件的 2.binarySearch 是通过二分查找,但是前提也是必须先排序所以,如果已经排序的,使用 binarySearch 性能会高很多。75. 集合中的元素必须做到 compartTo 和 equals 同步public class Person implements Comparable&Person& {
&span class="hljs-keyword"&public&/span& &span class="hljs-keyword"&int&/span&
&span class="hljs-keyword"&public&/span& S
&span class="hljs-keyword"&public&/span& Person(&span class="hljs-keyword"&int&/span& id, String name) {
&span class="hljs-keyword"&this&/span&.id =
&span class="hljs-keyword"&this&/span&.name =
&span class="hljs-keyword"&public&/span& &span class="hljs-keyword"&int&/span& compareTo(Person person) {
&span class="hljs-keyword"&if&/span& (person == &span class="hljs-keyword"&null&/span&) {
&span class="hljs-keyword"&return&/span& -&span class="hljs-number"&1&/span&;
&span class="hljs-keyword"&return&/span& pareTo(&span class="hljs-keyword"&this&/span&.name);
&span class="hljs-keyword"&public&/span& &span class="hljs-keyword"&boolean&/span& equals(Object o) {
&span class="hljs-keyword"&if&/span& (o == &span class="hljs-keyword"&null&/span&) {
&span class="hljs-keyword"&return&/span& &span class="hljs-keyword"&false&/span&;
&span class="hljs-keyword"&if&/span& (o == &span class="hljs-keyword"&this&/span&) {
&span class="hljs-keyword"&return&/span& &span class="hljs-keyword"&true&/span&;
&span class="hljs-keyword"&if&/span& (&span class="hljs-keyword"&this&/span&.getClass() != o.getClass()) {
&span class="hljs-keyword"&return&/span& &span class="hljs-keyword"&false&/span&;
Person p = (Person)
&span class="hljs-keyword"&return&/span& Integer.valueOf(id).compareTo(Integer.valueOf(p.id)) == &span class="hljs-number"&0&/span&;
List&Person& mList = new ArrayList&Person&();mList.add(new Person(1, "张二"));mList.add(new Person(1, "张一"));
Person p = &span class="hljs-keyword"&new&/span& Person(&span class="hljs-number"&1&/span&, &span class="hljs-string"&"张一"&/span&);
&span class="hljs-built_in"&int&/span& index1 = mList.indexOf(p);
&span class="hljs-built_in"&int&/span& index2 = Collections.binarySearch(mList, p);
&span class="hljs-built_in"&Log&/span&.i(&span class="hljs-string"&"clp"&/span&, &span class="hljs-string"&"index1="&/span& + index1);
&span class="hljs-built_in"&Log&/span&.i(&span class="hljs-string"&"clp"&/span&, &span class="hljs-string"&"index2="&/span& + index2);&/code&&/pre&
04-18 11:51:12.192 /com.example.demo I/clp: index1=0 04-18 11:51:12.192 /com.example.demo I/clp: index2=1indexOf 是通过对象中的 equals 来判断是否相等, binarySearch 是通过 compartTo 来判断是否相等。所以 2 个方法应该同步。76. 集合运算中使用更优雅的方式 List&String& mList1 = new ArrayList&String&()mList1.add("a")mList1.add("b")List&String& mList2 = new ArrayList&String&()mList2.add("a")mList2.add("c")
// mList1.addAll(mList2)// Log.i("clp", "并集 size=" + mList1.size())// //04-18 12:07:46.552 12423-12423/com.example.demo I/clp: 并集 size=4
// mList1.retainAll(mList2)// Log.i("clp", "交集 size=" + mList1.size())//04-18 12:08:55.022 12423-12423/com.example.demo I/clp: 交集 size=1
// mList1.removeAll(mList2)// Log.i("clp", "差集 size=" + mList1.size())//04-18 12:09:44.782 12423-12423/com.example.demo I/clp: 差集 size=1
//无重复的并集
mList2&span class="hljs-preprocessor"&.removeAll&/span&(mList1)&span class="hljs-comment"&;&/span&
mList1&span class="hljs-preprocessor"&.addAll&/span&(mList2)&span class="hljs-comment"&;&/span&
Log&span class="hljs-preprocessor"&.i&/span&(&span class="hljs-string"&"clp"&/span&, &span class="hljs-string"&"无重复的并集 size="&/span& + mList1&span class="hljs-preprocessor"&.size&/span&())&span class="hljs-comment"&;&/span&
// 04-18 12:10:34.862 12423-12423/com.example.demo I/clp: 无重复的并集 size=3无重复的并集,不能使用 HashSet,因为会把本来重复的元素合并掉。77. 使用 shuffle 打乱列表
int count = 10;List&String& mList = new ArrayList&&(10);for (int i = 0; i & 10; i++) {mList.add(i + "");}Collections.shuffle(mList);for (int i = 0; i & 10; i++) {Log.i("clp", "value" + mList.get(i));}78. 减少 HashMap 中元素的数量1. 比 ArrayList 多了 Entry 对象,如果有 40 万个数据,就是多了 40 万个对象 2. 扩容机制不一样,HashMap 是 2 倍扩容,ArrayList 是 1.5 倍 3.HashMap 有一个加载因子,意思是到达容量的 0.75 就开始扩容了所以大量数据的时候,HashMap 比 ArrayList 先内存溢出。79. 集合中的哈希码尽量不要重复HashMap 是通过哈希值,实现比 ArrayList 快速的查找,如果哈希码是一样的,性能就和链表的性能是一样的。80. 多线程使用 Vector 和 HashTable
final Vector&String& mVList = new Vector&String&();for (int i = 0; i & 10000; i++) {mVList.add("火车票" + i);}for (int i = 0; i & 10; i++) {new Thread(new Runnable() {@Overridepublic void run() {while (true) {String mR = mVList.remove(0);Log.i("clp", "cur thread id=" + Thread.currentThread().getId() + ";remove =" + mR);}}}).start();}多个线程同步,但是不能实现,一个线程读的时候,另一个线程在写。81. 非稳定序列推荐使用 List
SortedSet&Person& sortSet = new TreeSet&Person&()sortSet.add(new Person(15, "张三"))sortSet.add(new Person(10, "张四"))for (Person per : sortSet) {Log.i("clp", "id=" + per.id + ";name=" + per.name)}04-18 15:44:55.202 /com.example.demo I/clp: id=10;name= 张四 04-18 15:44:55.202 /com.example.demo I/clp: id=15;name= 张三
SortedSet&Person& sortSet = new TreeSet&Person&()sortSet.add(new Person(15, "张三"))sortSet.add(new Person(10, "张四"))sortSet.first().id = 20for (Person per : sortSet) {Log.i("clp", "id=" + per.id + ";name=" + per.name)}04-18 15:45:49.532 /com.example.demo I/clp: id=20;name= 张四 04-18 15:45:49.532 /com.example.demo I/clp: id=15;name= 张三SortedSet 只有在插入的时候,进行排序。
sortSet = new TreeSet&Person&(new ArrayList&Person&(sortSet));可以通过 new 重新构建。基本类型,建议使用 SortedSet,如果是自己创建的对象,可以使用 Colletions.sort82. 集合大家族一、List 实现 List 的接口主要有:ArrayList- 动态数组 LinkedList- 双向链表 Vector- 线程安全的动态数组 Stack- 对象栈,先进后出二、Set- 不包含重复元素的集合: EnumSet- 枚举类型的专用 Set,所有的元素都是枚举类型 HashSet- 以哈希码决定元素位置的 Set,与 HashMap 类似,提供快速的插入和查找 TreeSet- 自动排序的 Set,实现了 SortedSet 接口三、Map- 分为排序的 Map 和非排序 Map TreeMap- 根据 Key 值自动排序 HashMap HashTable Properties:HashTable 的子类,主要从 Property 文件中加载数据,并提供方便的读写。 EnumMap WeakHashMap: 可以被垃圾回收的 HashMap四、Queue 队列 - 分为阻塞和非阻塞队列五、数组 所有的集合底层存储的都是数组,数据可以存储基本类型,集合不行。六、工具类 数组的工具类:Array 和 Arrays 集合的工具类:Collections如果需要精确排序,则需要使用开源项目。如 pinyin4j。枚举和注解83. 推荐使用枚举定义常亮public enum SeaSon {Sping, Summer, Autumn, W
&span class="hljs-keyword"&public&/span& &span class="hljs-keyword"&static&/span& SeaSon &span class="hljs-title"&getCommonSeason&/span&() {
&span class="hljs-keyword"&return&/span& S
&span class="hljs-keyword"&for&/span& (SeaSon s : SeaSon.values()) {
Log.i(&span class="hljs-string"&"clp"&/span&, &span class="hljs-string"&"s values ="&/span& + s);
Log.i(&span class="hljs-string"&"clp"&/span&, &span class="hljs-string"&"common ="&/span& + SeaSon.getCommonSeason());&/code&&/pre&
04-19 10:26:24.608 /com.example.demo I/clp: s values =Sping 04-19 10:26:24.608 /com.example.demo I/clp: s values =Summer 04-19 10:26:24.608 /com.example.demo I/clp: s values =Autumn 04-19 10:26:24.608 /com.example.demo I/clp: s values =Winner 04-19 10:26:24.608 /com.example.demo I/clp: common =Sping84. 使用构造函数协助描述枚举项public enum SeaSon {Sping("春"), Summer("夏"), Autumn("秋"), Winner("冬"); &span class="hljs-keyword"&private&/span& S
SeaSon(String desc) {
&span class="hljs-keyword"&this&/span&.desc =
&span class="hljs-keyword"&public&/span& String &span class="hljs-title"&getDesc&/span&() {
&span class="hljs-keyword"&return&/span&
&span class="hljs-keyword"&public&/span& &span class="hljs-keyword"&static&/span& SeaSon &span class="hljs-title"&getCommonSeason&/span&() {
&span class="hljs-keyword"&return&/span& S
for (SeaSon s : SeaSon.values()) {Log.i("clp", "s values =" + s.getDesc())}
Log&span class="hljs-preprocessor"&.i&/span&(&span class="hljs-string"&"clp"&/span&, &span class="hljs-string"&"common ="&/span& + SeaSon&span class="hljs-preprocessor"&.getCommonSeason&/span&())&span class="hljs-comment"&;&/span&&/code&&/pre&
构造函数还可以比这个更复杂,传递对象等。85. 小心 switch 带来的空值异常
public void doSwSeaSon(SeaSon seaSon) {switch (seaSon) {case Sping:Log.i("clp", "Sping");break;default:Log.i("clp", "其他类型");break;}}doSwSeaSon(null);java.lang.NullPointerException: Attempt to invoke virtual method ‘int com.cp.demo.java.SeaSon.ordinal()’ on a null object referencecase 的其实是:SeaSon.Sping.ordinal(), 所以要做对象的空值判断。86. 在 switch 的 default 代码块中增加 AssertionError 错误因为枚举类型和 case 没有强制关系,如果后续增加了一个,没有 case,就会导致 switch 漏掉这个枚举项。87. 枚举使用 valueOf 前必须进行校验否则会抛出异常
List&String& mList = Arrays.asList("Sping", "sss");for (int i = 0; i & mList.size(); i++) {SeaSon sea = SeaSon.valueOf(mList.get(i));if (sea == null) {Log.i("clp", "没有此枚举值");} else {Log.i("clp", "有值");}}java.lang.IllegalArgumentException: sss is not a constant in com.cp.demo.java.SeaSon两种方案: 1. 捕获异常
List&String& mList = Arrays.asList("Sping", "sss");for (int i = 0; i & mList.size(); i++) {try {SeaSon sea = SeaSon.valueOf(mList.get(i));Log.i("clp", "有值");} catch (IllegalArgumentException e) {Log.i("clp", "没有此枚举值");}}04-19 11:35:20.148 /com.example.demo I/clp: 有值 04-19 11:35:20.148 /com.example.demo I/clp: 没有此枚举值2. 拓展枚举类
public static boolean contains(String name) {for (SeaSon sen : values()) {if (sen.name().equals(name)) { return true;}} return false;}
List&String& mList = Arrays.asList("Sping", "sss");for (int i = 0; i & mList.size(); i++) {boolean sea = SeaSon.contains(mList.get(i));if (sea) {Log.i("clp", "有值");} else {Log.i("clp", "没有此枚举值");}}88. 用枚举实现工厂方法模式更简洁1. 非静态方法实现。public interface Car {public void drive();} public class FortCar implements Car { &span class="hljs-annotation"&@Override&/span&
&span class="hljs-keyword"&public&/span& &span class="hljs-keyword"&void&/span& &span class="hljs-title"&drive&/span&() {
Log.i(&span class="hljs-string"&"clp"&/span&, &span class="hljs-string"&"fort drive"&/span&);
} public class BuickCar implements Car { &span class="hljs-annotation"&@Override&/span&
&span class="hljs-keyword"&public&/span& &span class="hljs-keyword"&void&/span& &span class="hljs-title"&drive&/span&() {
Log.i(&span class="hljs-string"&"clp"&/span&, &span class="hljs-string"&"buick drive"&/span&);
} public enum CarFactory {FortCar, BuickC &span class="hljs-keyword"&public&/span& Car &span class="hljs-title"&create&/span&() {
&span class="hljs-keyword"&switch&/span& (&span class="hljs-keyword"&this&/span&) {
&span class="hljs-keyword"&case&/span& FortCar:
&span class="hljs-keyword"&return&/span& &span class="hljs-keyword"&new&/span& FortCar();
&span class="hljs-keyword"&case&/span& BuickCar:
&span class="hljs-keyword"&return&/span& &span class="hljs-keyword"&new&/span& BuickCar();
&span class="hljs-keyword"&default&/span&:
Log.i(&span class="hljs-string"&"clp"&/span&, &span class="hljs-string"&"无效参数"&/span&);
&span class="hljs-keyword"&return&/span& &span class="hljs-keyword"&null&/span&;
}04-19 11:55:34.988 /com.example.demo I/clp: fort drive2. 通过抽象方法生成public enum CarFactory {FortCar {@Overridepublic Car create() {return new FortCar();}}, BuickCar {@Overridepublic Car create() {return new BuickCar();}};
&span class="hljs-keyword"&public&/span& &span class="hljs-keyword"&abstract&/span& Car &span class="hljs-title"&create&/span&();
}89. 枚举项的数量限制的 64 个以内long e = -1L &&& -65;long e = -1L &&& -1;long e = -1L &&& 63;long e = -1L &&& 1;
long e = -1L &&& 62;
int e = -1 &&& 31;int e = -1 &&& 1;小于等于 64 和大于 64 处理的机制是不一样的。
Enum[] universe = getUniverse(elementType);if (universe == null)throw new ClassCastException(elementType + "not an enum");
&span class="hljs-keyword"&if&/span& (universe.length &= &span class="hljs-number"&64&/span&)
&span class="hljs-keyword"&return&/span& &span class="hljs-keyword"&new&/span& RegularEnumSet&&(elementType, universe);
&span class="hljs-keyword"&else&/span&
&span class="hljs-keyword"&return&/span& &span class="hljs-keyword"&new&/span& JumboEnumSet&&(elementType, universe);
RegularEnumSet:void addAll() {if (universe.length != 0)elements = -1L &&& -universe.}
JumboEnumSet:void addAll() {for (int i = 0; i & elements. i++)elements[i] = -1;elements[elements.length - 1] &&&= -universe.size = universe.}所以内部是以 64 位拆分进行分组。90. 小心注解继承91. 枚举和注解结合使用威力很大92. 注意 @Overrig 不同版本的区别如果是 Java1.6 版本的程序移植到 1.5 版本环境中,就需要删除实现接口方法上的 @Override 注解泛型和反射93.Java 的泛型是类型擦除的java 的编译期和运行期解读: 编译期: 源码 -&class 文件的过程 运行期: 在 JVM 中运行的过程
public void initList(List&Integer& mList) {
&span class="hljs-keyword"&public&/span& &span class="hljs-keyword"&void&/span& &span class="hljs-title"&initList&/span&(List&String& mList) {
}&/code&&/pre&
按照上面这种方式写,报错。 initList(List)’ clashes with ‘initList(List)’; both methods have same erasure
List&String& mList = new ArrayList&String&();List&Integer& mIList = new ArrayList&Integer&();Log.i("clp", "is equals=" + (mList.getClass() == mIList.getClass()));04-25 15:49:13.356 /.myapplicati I/clp: is equals=true他们擦除后的类型都是 ListJava 泛型-类型擦除: 94. 不能初始化泛型参数和数组
T t = new T();T[] mTArray = new T[];List&T& mList = new ArrayList&T&();以上 3 个写法,在 AS 上面都报错,需要在运行期指定 T 类型。95. 强制声明泛型的实际类型List&Integer& mList = CldCalMiniUtil.asList();List&Integer& mList = CldCalMiniUtil.&Integer&asList();List&Number& mList2 = CldCalMiniUtil.asList(1, 2.2);List&Number& mList2 = CldCalMiniUtil.&Number&asList(1, 2.2);
助力小程序快速上线
Promoted by
Feel easy about trust.
Powered by
2.1.0 o 487ms

我要回帖

更多关于 java如何写出漂亮代码 的文章

 

随机推荐