不断找漏洞。自我总结
1.
A a=new A(1); A b=new A(2); b=a; System.out.println(b.a); // 1 b.setA(0); System.out.println(a.a); //0注意: b=a; 实际上意思是变量a,b指向同一个内存地址。这是因为,对于 引用类型的变量值是所指对象的内存地址。b=a,就是将a的地址赋值给a,因此a,b指向同一块内存空间。再深究到JVM的垃圾回收机制的话,此时
A b=new A(2);对象的内存将被释放。
2.
if (num < 0 && num == Math.abs(num)) int a=5;
这样写是错误的。因为if语句后面的语句如果不加{ },必须是可执行语句。赋值语句不可以的!
3. 更新于2011.8.12 23:36
唉。又忘记了 == 和 equal 的区别了。。 == 是比较的内存地址,equal才是比较的值。对于引用型变量,如果是比较值的话,最好的办法是重写equal方法。
Integer a=new Integer(5); Integer b=new Integer(5); System.out.println(a==b);这个打印出来false。因为new一次就申请一个内存空间。
Integer a=2; Integer b=2; System.out.println(a==b); //打印出来true,因为指向同一个内存空间。 a,b都是指向一个常量2。(2存在于栈中!) //同理: String s1="a"; String s2="a"; System.out.println(s1==s2); //打印true 因为指向同一个内存空间。(牵扯到常量池) System.out.println(s1=="a"); //打印true 因为都是指向一个常量的。 String s11=new String("a"); String s21=new String("a"); System.out.println(s11=="a"); //打印false。s11是新申请的内存。"a"是存在于常量池中的。 System.out.println(s11==s21); //打印 false 因为两边都是通过new新申请内存空间,
要注意:int a=3,这个3是存在于栈中的
而String str="a";这个a存在于常量池的。
八种基本数据类型,及对象引用的空间,均是分布在栈中,因为它们的大小,在分配空间前就能确定。
常量池是用来存字符串常量的。不存整型变量。
4.更新于2011 .8.12 2:05
为什么要使用ArrayList里面的 toArray()方法。看下面代码就知道了:
List<String> list=new ArrayList<String>(); list.add("a"); System.out.println(list.size()); //输出1 List<String> l1=list; l1.remove(0); System.out.println(list.size()); //输出0 System.out.println(l1.size()); //输出0
可以看出来如果直接通过赋值语句传递List类型变量的话,更改一个List会对别的List产生一样的后果。这通常不是我们希望看到的。即使将上面的代码改为下面,也依然得到相同的结果!
List<String> l1=new ArrayList<String>(); l1=list;
至于原因,稍微延伸一下。假设有一个Student类,我们都知道如果
Student student1=new Student(3,"zhangsan"); Student student2=s1;那么,s1和s2将同时指向同一个内存地址。说得更详细点是student1,student2变量中存储的东西是一样的,这个东西就是一个Student对象的地址。此时,如果我们让对象s2调用类Student里set()方法改变s2里面的一些属性,同时也会更改对象s1里面的属性。
ArrayList也是一个类。和Student没啥大的区别,唯一的区别就是ArrayList是已经写好包装好的类,本质上两者还是一样的。这样的话,就不难解释为什么出现上面的情况。
这就是我们需要用到 toArray()方法的原因。对于这个方法,API是这样解释的:
按适当顺序(从第一个到最后一个元素)返回包含此列表中所有元素的数组。
由于此列表不维护对返回数组的任何引用,,因而它将是“安全的”。(换句话说,此方法必须分配一个新的数组)。因此,调用者可以自由地修改返回的数组。
但是在用到toArray()方法的时候需要注意:它的返回值是一个Object型的数组。如果还想继续得到String类型的数组,需要这样做:
String []s=list.toArray(new String[0]);
刚才从ArrayList延伸到了普通的类,我们都知道如果想把上面提到的student2=student1,改变一下,使student2既得到student1的属性,又可以自由改变这些属性而不影响到student1。恩,那就是clone()方法。要想使用clone( )方法,必须实现Cloneable接口。在这里就不多说了。
还是回到ArrayList上面来,我们利用toArray()的原因是向得到一个与原来数组相同的数组,但是又想新开辟内存地址,想与原来的数组划清界线。这不就是类Object里面clone()方法的功能吗?本来还担心,使用clone()方法得实现Cloneable接口,那不就是得重写ArrayList吗?好麻烦。。。不过后来竟然在API中看到ArrayList中自带了clone()方法。。欣喜啊~这样的话,我们其实就可以抛弃toArray()方法了。两者实现的是相同的功能,但是clone()方法返回的是ArrayList,而toArray()得到的只能是普通数组。。ArrayList当然比普通数组强大得多了。
总结一下:这次从 toArray()方法出发,到最后把它给抛弃了。。(或许还有别的好处,望赐教。。)
5. 2011.8.12 晚 10:10
数组为 Null和数组大小为0,是两个不通的概念。
List<String > l=new ArrayList<String>(); System.out.println(l==null); //false System.out.println(l.size()); //输出0
6. 2011.9.5 16:04
6.1
(int)Math.random()*10;
这个句子的执行顺序是:先(int)Math.random(),再乘以10
6.2
final标识符的意思是不能被改变。
1.类被final修饰的话,表示这个类不能被继承。
final类不能被继承,因此final类的成员方法没有机会被覆盖,默认都是final的。在设计类时候,如果这个类不需要有子类,类的实现细节不允许 改变,并且确信这个类不会载被扩展,那么就设计为final类。
2.方法被final修饰的话,表示这个方法不能被改变,即不能被子类里面的方法覆盖(可以被继承)。
使用final方法的原因有二:
第一、把方法锁定,防止任何继承类修改它的意义和实现。
第二、高效。编译器在遇到调用final方法时候会转入内嵌机制,大大提高执行效率。
3.变量被final修饰的话,表示变量的值不能被改变。并且在对象生成的时候必须有值。这就决定了final变量的两种赋 值方式:
方式一:定义变量的时候进行赋值
final static int a=4;
final static int a=(int)(Math.random()*10);
方式二:在构造函数里面对变量进行赋值:
final int a; public MainClass(int b) { a=b; }这两个地方只能选其一,要么在定义时给值,要么在构造函数中给值,不能同时既在定义时给了值,又在构造函数中给另外的值。
6.3 重载是载同一个类里面写另外一个方法和已经存在的某个方法同名,但是参数不一样。
重写是对于继承而言的,继承类重新编写基类的方法。
6.3
for(int i=2,double j=5;i<=6;){ }这样写实错误的。
for(int i=2,int j=5;i<=6;){ }这样写也是不对的。
for(int i=2, j=5;i<=6;){ }而只有这样是对的!
7. 2011.9.6 15:40
泛型:
package com.bjsxt.dp.strategy; public abstract class Compartor <E>{ public abstract int compare(E t1,E t2); }
package com.bjsxt.dp.strategy; public class ComparatorCatWeight extends Compartor<Cat> { @Override public int compare(Cat t1, Cat t2) { if (t1.getWeight() > t2.getWeight()) return 1; else if (t1.getWeight() < t2.getWeight()) return -1; else return 0; } }
8. 2011.11.23 11:25
也许你还记得,Function 对象这一章中介绍过 Function 的 toString() 方法通常输出的是函数的源代码。覆盖该方法,可以返回另一个字符串(在这个例子中,可以返回 "Function code hidden")。不过,toString() 指向的原始函数怎么了呢?它将被无用存储单元回收程序回收,因为它被完全废弃了。没有能够恢复原始函数的方法,所以在覆盖原始方法前,比较安全的做法是存储它的指针,以便以后的使用。有时你甚至可能在新方法中调用原始方法:
Function.prototype.originalToString = Function.prototype.toString;
Function.prototype.toString = function() {
if (this.originalToString().length > 100) {
return "Function too long to display.";
} else {
return this.originalToString();
}
};
TIY
在这段代码中,第一行代码把对当前 toString() 方法的引用保存在属性 originalToString 中。然后用定制的方法覆盖了 toString() 方法。新方法将检查该函数源代码的长度是否大于 100。如果是,就返回错误信息,说明该函数代码太长,否则调用 originalToString() 方法,返回函数的源代码。
这个表明,在js里面,将函数看成一个变量会容易理解一点。
9. 2011.11.23 19:32
在JavaScript里面:
var arr = new Array() arr[0]="1";arr[2]="1";arr[2]="1"; for(var t in arr){ document.write(t) }
这点是不同于Java的。
10 2011 .11.25 21::45
在jsp页面中,可以单独定义一个方法,而不是必须在类里面,则必须定义在<% ! %> 里面
11 2012.3.20 18:14
HashMap 与HashTable的最大区别是HashMap的键可以为null,为HashTable的不可以。
12. 2012.9.14
(Element)node1.getFirstChild()应该是从右至左运算,即先运算node1.getFirstChild(),然后再强制转换。 .比()运算优先级高。
12. 2012.12.14 20:11
在编程的时候,特别是在看别人做好的项目的时候,不可因为一个地方有疑问而据纠结很长时间,而是应该抓住重点!!
13.2012.12.22 15:55
在Action中得到tomcat的绝对路径。
String realPath = request.getSession().getServletContext().getRealPath("/")+"WEB-INF/image/";