==、equals与hashCode
==
基本数据类型用= =比较的是数据的值。
引用类型用= =进行比较的是他们在内存中的存放地址。
equals
默认情况(没有覆盖equals方法) Object的equals方法主要用于判断对象内存地址引用是不是同一个 地址(是不是同一个对象)
覆盖equals方法:根据具体的代码确定equlas方法,覆盖后一般都是通过对象的内容是否相等来判断对象是否相等。
hashCode()方法返回的就是一个hash码(int类型)。
hash码的主要用途就是在对对象进行散列的时候作为key输入,我们需要每个对象的hash码尽可能不同,这样才能保证散列的存取性能(将数据按特定算法指定到一个地址上)。事实上,Object类提供的默认实现确实保证每个对象的hash码不同(在对象的内存地址基础上经过特定算法返回一个hash码)。
序列化
什么是序列化?
对象序列化是一个用于将对象状态转换为字节流的过程,可以将其保存到磁盘文件中或通过网络发送到任何其他程序;从字节流创建对象的相反的过程称为反序列化。
序列化的方式?
方式1:要传递的类实现Serializable接口传递对象(Java自带) 方式2:要传递的类实现Parcelable接口传递对象(android专用)
Serializable 和Parcelable的对比
android上应该尽量采用Parcelable,效率至上
(1)编码上: Serializable代码量少,写起来方便;Parcelable代码多一些
(2)效率上: Parcelable的速度比高十倍以上;
serializable的迷人之处在于你只需要对某个类以及它的属性实现Serializable 接口即可。Serializable 接口是一种标识接口(marker interface),这意味着无需实现方法,Java便会对这个对象进行高效的序列化操作。
serializable的缺点是使用了反射,序列化的过程较慢。这种机制会在序列化的时候创建许多的临时对象,容易触发垃圾回收。
Parcelable方式的实现原理是将一个完整的对象进行分解,而分解后的每一部分都是Intent所支持的数据类型,这样也就实现传递对象的功能了
Android序列化应用场景
需要在多个部件(Activity或Service)之间通过Intent传递一些数据,简单类型(如:数字、字符串)的可以直接放入Intent。复杂类型必须实现Parcelable接口。
1)在使用内存的时候,Parcelable比Serializable性能高,所以推荐使用Parcelable。
2)Serializable在序列化的时候会产生大量的临时变量,从而引起频繁的GC。
3)Parcelable能使用在要将数据存储在磁盘上的情况,因为Parcelable不能很好的保证数据的持续性在外界有变化的情况下。尽管Serializable效率低点,但此时还是建议使用Serializable 。不
内部类
什么是内部类
定义在类内部的类就被称为内部类。外部类按常规的类访问方式使用内部类,唯一的差别是内部类可以访问外部类的所有方法与属性,包括私有方法与属性。
内部类是一个编译时的概念。外部类outer.java内定义了一个内部类inner,一旦编译成功,就会生成两个完全不同的.class文件,分别是outer.class和outer$inner.class。
为什么要设计内部类
内部类是为了更好的封装,把内部类封装在外部类里,不允许同包其他类访问
内部类中的属性和方法即使是外部类也不能直接访问,相反内部类可以直接访问外部类的属性和方法,即使private
实现多继承:每个内部类都能独立地继承一个(接口的)实现,所以无论外围类是否已经继承了某个(接口的)实现,对于内部类都没有影响。
匿名内部类用于实现回调
解释:为什么Java中成员内部类可以访问外部类成员?
内部类的构造函数初始化内部类对象时, 会默认传入外部类的引用。
继承和重写
继承:
静态属性跟方法、非静态属方法都可以继承。
重写
静态属性、非静态属性、静态方法都没有多态的说法(不会重写只是隐藏了父类的)。
只有非静态方法有多态的说法。
具体理解:
申明变量Parent child = new Child(),
1、调用child的静态属性、非静态属性、静态方法,因为这几种情况没有多态的说法,变量申明是又是Parent,所以会调用Parent的属性和方法。
2、调用child的非静态方法,因为非静态方法有多态的说法,所以会调用实际对象child的非静态方法。
编码
几种编码格式的比较
1、GB2312 与 GBK 编码规则类似,但是 GBK 范围更大,它能处理所有汉字字符,所以 GB2312 与 GBK 比较应该选择 GBK。
2、UTF-16 与 UTF-8 都是处理 Unicode 编码,它们的编码规则不太相同,相对来说 UTF-16 编码效率最高,字符到字节相互转换更简单,进行字符串操作也更好。它适合在本地磁盘和内存之间使用,可以进行字符和字节之间快速切换,如 Java 的内存编码就是采用 UTF-16 编码。但是它不适合在网络之间传输,因为网络传输容易损坏字节流,一旦字节流损坏将很难恢复,想比较而言 UTF-8 更适合网络传输,对 ASCII 字符采用单字节存储,另外单个字符损坏也不会影响后面其它字符,在编码效率上介于 GBK 和 UTF-16 之间,所以 UTF-8 在编码效率上和编码安全性上做了平衡,是理想的中文编码方式。UTF-16是固定长度16bit,两个字节。UTF-8变长度1-4个字节。
Java的异常体系
final、finally、finalize区别与使用
final 修饰符(关键字)
final用于控制成员、方法或者是一个类是否可以被重写或者继承等功能。
(1)如果类被声明为final,意味着它不能再派生出新的子类,不能作为父类被继承。
(2)将变量或者方法声明为final,可以保证他们在使用中不被改变。其初始化可以在两个地方:一是其定义处,也就是说,在final变量定义时直接给其赋值;二是构造函数中。这2个地方只能选其一,要么在定义处直接给其赋值,要么在构造函数中给值,并且在以后的引用中,只能读取,不可修改。被声明为final的方法也同样只能使用,不能重写。
finally(用于异常处理)
finalize(用于垃圾回收)
finalize这个是方法名。在java中,允许使用finalize()方法在垃圾收集器将对象从内存中清理出去之前做必要的清理工作。这个方法是Object类中定义的,因此,所有的类都继承了它。finalize()方法是在垃圾收集器删除对象之前对这个对象调用的。
尽量避免使用finalize():
1、finalize()不一定会被调用, 因为java的垃圾回收器的特性就决定了它不一定会被调用.
2、就算finalize()函数被调用, 它被调用的时间充满了不确定性, 因为程序中其他线程的优先级远远高于执行finalize()函数线程的优先级。也许等到finalize()被调用,数据库的连接池或者文件句柄早就耗尽了.
3、如果一种未被捕获的异常在使用finalize方法时被抛出,这个异常不会被捕获,finalize方法的终结过程也会终止,造成对象出于破坏的状态。被破坏的对象又很可能导致部分资源无法被回收, 造成浪费.
4、finalize()和垃圾回收器的运行本身就要耗费资源, 也许会导致程序的暂时停止.
Java的反射机制
什么是反射?——框架设计的灵魂
Java反射说的是在运行状态中,对于任何一个类,我们都能够知道这个类有哪些方法和属性。对于任何一个对象,我们都能够对它的方法和属性进行调用。
我们把这种动态获取对象信息和调用对象方法的功能称之为反射机制。
字节码Class对象
将(.java类文件)经过编译后的.class字节码文件(位于硬盘上)通过类加载器(ClassLoader)加载进内存,通过java.lang.Class类对象对字节码文件进行描述。每一个类都是一个Class类的实例对象。
Class类对象是用来对.class文件进行描述。主要包括三个成员变量:类成员变量 Field[] fields
类构造方法 Constructor[] constructors
类成员方法 Method[] methods
Java注解
什么是Java注解
注解(Annotation)是插入代码中的元数据,一种代码级别的说明。它是在JDK5.0及以后版本引入的一个特性,与类、接口、枚举是在同一个层次。它可以声明在包、类、字段、方法、局部变量、方法参数等的前面,用来对这些元素进行说明,注释。
注解的分类
按照运行机制分类
源码注解:注解只在源码中存在,编译成.class文件就不存在了
编译时注解:注解只在源码中与.class文件都存在了,包括@Override、@Deprecated、@SuppressWarnnings
运行时注解:在运行阶段仍起作用,甚至影响运行逻辑的注解,如@Autowired
自定义注解
格式
元注解
public @interface 注解名称{
... 属性列表
}
本质
注解本质上就是一个接口,该接口默认继承java.lang.annotation.Annotation接口。
public interface MyAnno extends java.lang.annotation.Annotation{}