前言:
很多人会有这样一个体会,Java学了好几遍了,可有时敲代码时对某些知识点还是不能记忆犹新,模棱两可。还是得翻书,百度查资料。为了摆脱这个毛病,写下这篇博文,把易忘的,易错的知识点,以及重点难点,写下来,便于参考与记忆。次数多了,就会记在脑海里了。
一、equals()方法与“==”
这个方法真的是困扰了我好几次了。一直没明白它到底比较的是什么。今天把它揪出来问问吧。
首先来说下“==”,它是用来比较两个对象在堆内存的首地址,即用来比较两个引用变量是否指向同一个对象。当然了,这是对两个引用类型来说的。如果是8大基础类型,自然就是两个值想不想等了。那equals呢?equals()是object类的一个方法。如果子类不重写equals()方法,那么它和“==”的比较是一样的。也是比较两个引用变量是否指向同一个对象。下面举几个例子看看。
String s1 = new String( "123");
String s2 = new String( "123");
String s3 ="456";
String s4 ="456";
StringBuffer s5 = new StringBuffer("a");
StringBuffer s6 = new StringBuffer("a");
System.out.println(s1==s2); //false
System.out.println(s3==s4); //true
System.out.println(s5==s6); //false
System.out.println(s1.equals(s2)); //true
System.out.println(s3.equals(s4)); //true
System.out.println(s5.equals(s6)); //false
看了上面的例子是不是有想法:s1.equals(s2)是true, s5.equals(s6)却又是false,这是为何?因为String类重写了equals()方法。比较的是两个字符串的值是不是相等。而StringBuffer没有重写。所以结果如此。
//String 类重写的equals();
public boolean equals(Object anObject) {
if (this == anObject) {
return true;
}
if (anObject instanceof String) {
String anotherString = (String) anObject;
int n = count;
if (n == anotherString.count) {
int i = 0;
while (n-- != 0) {
if (charAt(i) != anotherString.charAt(i))
return false;
i++;
}
return true;
}
}
return false;
}
这一比较,心理总算踏实了,再也不会犯错了。
二、异常Exception
可能,我又记不起哪些是运行时异常了。整理下吧!
异常Exception(广义、体系)
Throwable 可抛的,是所有异常和错误的父类
Error 严重的问题,不需要程序去处理
Exception(狭义) 可能需要程序去处理
RuntimeException 运行时异常,它和它的子类都是非受检异常
1.非受检异常: 可以不对其进行异常处理,通过严谨的编码逻辑就可以避免的异常如:ArrayIndexOutofBoundsException、NullPointerException、ClassCastException、ArithmeticException…
2.受检异常:是Exception的子类但不是RuntimeException的子类,都是受检异常,受检异常必须要进行异常处理。如:FileNotFoundException、IOException、MalformedURLException、ClassNotFoundException…
3.如何处理异常:try、catch、finally
try 尝试运行可能出现异常的代码
catch 捕捉某一类型的异常对其进行处理
try{
代码1
}catch(异常类型 引用名){
代码2
}finally{
代码3
}
代码1是要尝试运行的可能出现异常的代码
代码2是捕捉到某种类型(小括号里的类型)异常要执行的处理逻辑
代码3是无论任何情况都会被最终执行的代码,用于收尾工作
三、反射
反射,平常开发中用的较少,在封装框架时偶尔会用到。刚开始学习的时候,只是了解了下皮毛。然后就抛之脑后了,现在要把他再捡起来咯。
反射相关功能的实现,封装在java.lang.reflect包下,该包下有Method,Constructor,field,Proxy,InvocationHandler 等类。先来看看一些实例吧。
先定义一个简单的类A吧
class A{
public String a ;
public int b ;
public void talk(String a){
System.out.println(a);
}
public A(String a,int b){
this.a=a;
this.b=b;
System.out.println("有参构造方法");
}
public A(){
System.out.println("无参构造方法");
}
}
再通过反射来获取下这些方法和属性:
//获取Class对象
Class clazz =A.class;
//返回A类的public字段
Field field = clazz.getField("a");
//返回A的构造方法
Constructor c = clazz.getConstructor(String.class,int.class);
//返回A类的所有为public 声明的构造方法
Constructor[] cons = clazz.getConstructors();
//返回A类所有的构造方法,包括private
Constructor[] cons2 = clazz.getDeclaredConstructors();
//返回A类所有的public 方法
Method[] ms = clazz.getMethods();
//返回A类所有的方法,包括private
Method[] allMs = clazz.getDeclaredMethods();
//返回A类的第一个public 方法
Method m = clazz.getMethod("talk", String.class);
//执行talk()方法
m.invoke(clazz.newInstance(), "反射");
你可能会问,既然A类都有了,为啥不直接new,还搞得这么麻烦呢。其实我只是为了方便举例子,认识下这些方法,在实际运用中,我们是拿不到具体的类的,也许你也不知道这个类具体是哪一个,因为你在搭建这个框架的时候,那个类还没诞生呢。但可以通过下面这种方式获得Class对象。
Class clazz = Class.forName("com.dx.demi.A");
获取反射最大的作用就在于我们可以不在编译时知道某个对象的类型,而在运行时得到。同时我们只需要得到我们想得到的类的名字即可(如果不在一个包,必须写完整的名字包括包名)。
今天暂时写这些点。以后遇到了,再添加!