【转载】Java基础总结(一)
Java基础
switch能否用string做参数
在 Java 7之前,switch 只能支持 byte、short、char、int或者其对应的封装类以及 Enum 类型。在 Java 7中,String支持被加上了。这个新特性是在编译器这个层次上实现的。而在Java虚拟机和字节码这个层次上还是只支持在switch语句中使用与整数类型兼容的类型。这么做的目的就是为了减少这个特性所影响的范围,以降低实现的代价。
object有哪些公用方法:equals,hashcode,clone,wait,notify、getClass等
-
clone方法
保护方法,实现对象的浅复制,只有实现了Cloneable接口才可以调用该方法,否则抛出CloneNotSupportedException异常。主要是JAVA里除了8种基本类型传参数是值传递,其他的类对象传参数都是引用传递(说法不准确,java都是值传递),我们有时候不希望在方法里讲参数改变,这是就需要在类中复写clone方法。 -
getClass方法
final方法,获得运行时类型。 -
toString方法
该方法用得比较多,一般子类都有覆盖。 -
finalize方法
该方法用于释放资源。因为无法确定该方法什么时候被调用,很少使用。 -
equals方法
该方法是非常重要的一个方法。一般equals和==是不一样的,但是在Object中两者是一样的。子类一般都要重写这个方法。 -
hashCode方法
该方法用于哈希查找,可以减少在查找中使用equals的次数,重写了equals方法一般都要重写hashCode方法。这个方法在一些具有哈希功能的Collection中用到。一般必须满足obj1.equals(obj2)==true。可以推出obj1.hashCode()==obj2.hashCode(),但是hashCode相等不一定就满足equals。不过为了提高效率,应该尽量使上面两个条件接近等价。如果不重写hashcode(),在HashSet中添加两个equals的对象,会将两个对象都加入进去。 -
wait方法
wait方法就是使当前线程等待该对象的锁,当前线程必须是该对象的拥有者,也就是具有该对象的锁。wait()方法一直等待,直到获得锁或者被中断。wait(long timeout)设定一个超时间隔,如果在规定时间内没有获得锁就返回。调用该方法后当前线程进入睡眠状态,直到以下事件发生。
(1)其他线程调用了该对象的notify方法。
(2)其他线程调用了该对象的notifyAll方法。
(3)其他线程调用了interrupt中断该线程。
(4)时间间隔到了。
此时该线程就可以被调度了,如果是被中断的话就抛出一个InterruptedException异常。 -
notify方法
该方法唤醒在该对象上等待的某个线程。 -
notifyAll方法
该方法唤醒在该对象上等待的所有线程。- note:7、8、9可以用于多线程通信。
String、StringBuffer与StringBuilder的区别。
String 字符串常量
StringBuilder 字符串变量(非线程安全)
StringBuffer 字符串变量(线程安全)
效率问题以及锁的问题?
为什么效率高?
加锁加载了哪?
try catch finally,try里有return,finally还执行么?
结论:
1. 不管有木有出现异常,finally块中代码都会执行;
2. 当try和catch中有return时,finally仍然会执行;
3. finally中有return,返回的值是finally中的值;finally中没有return,返回的是第一次出现return中的值。
Excption与Error包结构。
- 粉红色的是受检查的异常(checked exceptions),其必须被 try{}catch语句块所捕获,或者在方法签名里通过throws子句声明。
- 受检查的异常必须在编译时被捕捉处理,命名为 CHecked Exception 是因为Java编译器要进行检查,Java虚拟机也要进行检查,以确保这个规则得到遵守。
- 绿色的异常是运行时异常(runtime exceptions),需要程序员自己分析代码决定是否捕获和处理,比如 空指针,被0除…。
- 而声明为Error的,则属于严重错误,需要根据业务信息进行特殊处理,Error不需要捕捉。
Override和Overload的含义与区别
- 方法的重写(Overriding)和重载(Overloading)是Java多态性的不同表现。
- 重写(Overriding)是父类与子类之间多态性的一种表现,而重载(Overloading)是一个类中多态性的一种表现。
- 如果在子类中定义某方法与其父类有相同的名称和参数,我们说该方法被重写 (Overriding) 。子类的对象使用这个方法时,将调用子类中的定义,对它而言,父类中的定义如同屏蔽了。
-
如果在一个类中定义了多个同名的方法,它们或有不同的参数个数或有不同的参数类型或有不同的参数次序,则称为方法的重载(Overloading)。不能通过访问权限、返回类型、抛出的异常进行重载。
-
Override 特点
- 覆盖的方法的标志必须要和被覆盖的方法的标志完全匹配,才能达到覆盖的效果;
- 覆盖的方法的返回值必须和被覆盖的方法的返回一致;
- 覆盖的方法所抛出的异常必须和被覆盖方法的所抛出的异常一致,或者是其子类;
- 方法被定义为final不能被重写。
- 对于继承来说,如果某一方法在父类中是访问权限是private,那么就不能在子类对其进行重写覆盖,如果定义的话,也只是定义了一个新方法,而不会达到重写覆盖的效果。(通常存在于父类和子类之间。)
-
Overload 特点
- 在使用重载时只能通过不同的参数样式。例如,不同的参数类型,不同的参数个数,不同的参数顺序;
- 不能通过访问权限、返回类型、抛出的异常进行重载;
- 方法的异常类型和数目不会对重载造成影响;
- 重载事件通常发生在同一个类中,构造方法或者普通方法。
-
其具体实现机制:
- overload是重载,重载是一种参数多态机制,即代码通过参数的类型或个数不同而实现的多态机制。是一种静态的绑定机制(在编译时已经知道具体执行的是哪个代码段)。
- override是覆盖。覆盖是一种动态绑定的多态机制。即在父类和子类中同名元素(如成员函数)有不同 的实现代码。执行的是哪个代码是根据运行时实际情况而定的。
Interface与abstract类的区别
- 接口和抽象类有什么区别,选择使用接口和抽象类的依据是什么?
- 接口和抽象类的概念不一样。接口是对动作的抽象,抽象类是对根源的抽象。
- 抽象类表示的是,这个对象是什么。接口表示的是,这个对象能做什么。比如,男人,女人,这两个类(如果是类的话……),他们的抽象类是人。说明,他们都是人。人可以吃东西,狗也可以吃东西,你可以把“吃东西”定义成一个接口,然后让这些类去实现它.所以,在高级语言上,一个类只能继承一个类(抽象类)(正如人不可能同时是生物和非生物),但是可以实现多个接口(吃饭接口、走路接口)。
- 第一点, 接口是抽象类的变体,接口中所有的方法都是抽象的。而抽象类是声明方法的存在而不去实现它的类。
- 第二点, 接口可以多继承,抽象类不行
- 第三点, 接口定义方法,不能实现,而抽象类可以实现部分方法。
- 第四点, 接口中基本数据类型为static 而抽类象不是的。
- 当你关注一个事物的本质的时候,用抽象类;当你关注一个操作的时候,用接口。
- 抽象类的功能要远超过接口,但是,定义抽象类的代价高。因为高级语言来说(从实际设计上来说也是)每个类只能继承一个类。在这个类中,你必须继承或编写出其所有子类的
- 虽然接口在功能上会弱化许多,但是它只是针对一个动作的描述。而且你可以在一个类中同时实现多个接口。在设计阶段会降低难度的。
JDK8新特性:
* 在JDK7及以前的版本中,接口中都是抽象方法,不能定义方法体,但是从jdk8开始,接口中可以定义静态的非抽象的方法,直接使用接口名调用静态方法,但是它的实现类的类名或者实例却不可以调用接口中的静态方法。
* 也可以定义普通的非抽象的方法,普通的非抽象方法要在返回值前加上default,对于普通的非抽象方法必须使用子类的实例来调用。如果有多个接口定义了相同的默认方法,实现多个这些接口时必须重写默认方法,否则编译失败。
* jdk8的接口中,开始允许使用关键字default。
面向接口编程与面向对象编程(对上面进行延伸)
- 面向接口编程就是面向抽象编程、面向规范编程,它带来的最大的好处便是解耦、增强扩展性、屏蔽变化。
- 封闭-开放原则:设计最好满足对修改封闭,对扩展开放。为什么?上一个版本代码已经发布,你新添加的业务要去修改原有的代码,会引入很多未知的bug,尽量不动原有代码,减少bug出现的概率;而是以“添加”的形式增加新功能。
- 实现多态。
- 减少耦合性。
- 令各个成员依赖与抽象, 而不是依赖与具体。
- 方便维护和扩展。
@see:http://blog.csdn.net/nvd11/article/details/42305895
static class 与non static class的区别
- 内部静态类不需要有指向外部类的引用;但非静态内部类需要持有对外部类的引用。
- 非静态内部类能够访问外部类的静态和非静态成员;静态类不能访问外部类的非静态成员,他只能访问外部类的静态成员。
- 一个非静态内部类不能脱离外部类实体被创建,一个非静态内部类可以访问外部类的数据和方法,因为他就在外部类里面。
【关于内存泄露】
* 内部类持有外部类的引用,或者说内部类对外部类持有隐式的引用。假如我们在内部类中做耗时的操作或者说有个while(true)死循环,即内部类的对象一直存在; 那么当这个MainActivity应该被回收时(比如屏幕的旋转)GC发现它还被其内部类的对象引用 所以就不会将其回收.假如该Activity中含有大量的资源(比如图片)那么就很容易发生OOM.
* 优化方式:使用静态的内部类,这样的内部类就不会持有外部类的隐式引用,也就不会影响到GC对于外部类的回收;使用弱引用对耗内存对象进行包装。
public class A {
void a1() {
}
class B{
void b1() {
// 可以直接访问
a1();
}
}
static class C {
void c1() {
// 不能访问
// a1();
}
}
public static void main(String[] args) {
A a = new A();
// 非静态内部类必须依附于外部类
B b = a.new B();
C c = new C();
}
}
foreach与正常for循环效率对比。
- 需要循环数组结构的数据时,建议使用普通for循环,因为for循环采用下标访问,对于数组结构的数据来说,采用下标访问比较好。
- 需要循环链表结构的数据时,一定不要使用普通for循环,这种做法很糟糕,数据量大的时候有可能会导致系统崩溃。为什么:查看链表源码(比如LinkedList)的get(i)方法发现,会遍历为了查询一个值整个链表,直到便利到当前位置;但是数组(比如ArrayList)就不一样了,直接定位的。
-
for在遍历期间可以修改;foreach在遍历期间不可以修改。
-
fail-fast 机制是java集合(Collection)中的一种错误机制。当多个线程对同一个集合的内容进行操作时,就可能会产生fail-fast事件。例如:当某一个线程A通过iterator去遍历某集合的过程中,若该集合的内容被其他线程所改变了;那么线程A访问集合时,就会抛出ConcurrentModificationException异常,产生fail-fast事件。
- 要了解fail-fast机制,我们首先要对ConcurrentModificationException 异常有所了解。当方法检测到对象的并发修改,但不允许这种修改时就抛出该异常。同时需要注意的是,该异常不会始终指出对象已经由不同线程并发修改,如果单线程违反了规则,同样也有可能会抛出改异常。
- 诚然,迭代器的快速失败行为无法得到保证,它不能保证一定会出现该错误,但是快速失败操作会尽最大努力抛出ConcurrentModificationException异常,所以因此,为提高此类操作的正确性而编写一个依赖于此异常的程序是错误的做法,正确做法是:ConcurrentModificationException 应该仅用于检测 bug。
反射机制
-
什么是反射机制?
简单说,反射机制得是程序在运行时能够获取自身的信息。在java中,只要给定类的名字,那么就可以通过反射机制来获得类的所有信息。 -
java反射机制提供了什么功能?
- 在运行时能够判断任意一个对象所属的类
- 在运行时构造任意一个类的对象
- 在运行时判断任意一个类所具有的成员变量和方法
- 在运行时调用任一对象的方法
- 在运行时创建新类对象
-
哪里用到反射机制?
jdbc中有一行代码:Class.forName(‘com.MySQL.jdbc.Driver.class’).newInstance();那个时候只知道生成驱动对象实例,后来才知道,这就是反射,现在
很多框架都用到反射机制,hibernate,struts都是用反射机制实现的。- note:这也就是为什么说使用双重锁实现单例模式有风险,可以通过反射创建对象,因此不能保证只有一个实例。
String类内部实现,能否改变String对象内容,String源码
- 源码分析:求完善
- String常量池讲解 @see:http://jefferent.iteye.com/blog/1127799
- intern()方法的作用
TODO:求完善
Java1.7与1.8新特性
-
jdk1.7
1 对集合类的语言支持;
2 自动资源管理;
3 改进的通用实例创建类型推断;
4 数字字面量下划线支持;
5 switch中使用string;
6 二进制字面量;
7 简化可变参数方法调用;
8 新增一些取环境信息的工具方法;
9 Boolean类型反转,空指针安全,参与位运算;
10 两个char间的equals;
11 安全的加减乘除;
12 map集合支持并发请求 ,且可以写成 Map map = {name:”xxx”,age:18}; -
jdk1.8
接口的默认方法与静态方法
lambda表达式
Annotation 多重注解
java.util.stream支持在流上的函数式风格的值操作
总结文档在这里,比较详细~https://github.com/scsfwgy/AndroiderTechnology