1、面向对象的三大特性:封装、继承、多态
封装:对类的访问进行限制,决定了哪些类有权限访问这个类。在Java上表示为访问修饰符,public对所有的类开放,protected仅对子类开放,default仅对相同包名的类开放(在开发中,没有任何访问修饰符就为 default),private仅对本类开放
继承:让类与类之间存在关系,子类继承父类,子类则拥有父类的特性,子类可以在父类的基础进行扩展。另外Java还出了接口,这个是对类在不影响继承关系下进行扩展,这个接口解决了类只能单继承的弊端,一个类可以通过实现多种接口获得新特性
多态:在继承的基础上进行变换,既然能通过继承或者实现的方式使得获取新特性,这些特性都是在父类或者接口定义的,那么换过来想,子类可以直接作为父类或者接口来使用。在单继承或者多实现的情况下,类的关系都将会变得复杂,这个时候需要运用Java多态的特性,很多情况下都不需要关心这个子类对象有什么特性,因为我们没有运用到,那么可以把子类进行简化,简化成它的父类类型或者接口类型,更加明确了对象的作用。在Java大多表现为面向接口编程,例如 List 类型可以通过子类 ArrayList 进行创建(List list = new ArrayList()),虽然 ArrayList 是 List 的一个具体的实现对象,但是我们没有运用到 ArrayList 的特性,我们可以直接将这个对象当成 List 类型来使用,面向对象三大特性只是一种思想,需要我们真正了解才能运用得好
2、final关键字
final 是最终的意思,这个是Java的修饰符,在类、字段、方法有不同的作用
在类上面:表示这个类不能被继承了,也就是说被 final 修饰的类不会有子类
在字段上面:表示这个字段只能被赋值一次,并且只能在对象初始化完成之前赋值完成
在方法上面:表示这个方法不能被子类重写,保证方法的安全性.
3、static 关键字
static是静态的意思,这个是Java的修饰符,在类、字段、方法也有不同的作用
在类上面:不能修饰外部类(因为它本身就是独立的),一般修饰内部类(修饰之后就变成了静态内部类),代表这个内部类是独立的,不需要和外部类有直接来往(访问外部类的对象、字段、方法)
在字段上面:代表这个字段所在的类无论被创建多少次,它都只被创建一次并且是在第一次,也就是说,这些对象上面被 static 修饰的字段都是同一个对象
在方法上面:代表这个方法是独立于对象之外,不需要通过实例化(new)对象,而可以直接通过类名访问这个静态方法
4、instanceof关键字
这个是Java中判断对象类型的关键字,它可以有效避免错误的强转带来的类型转换异常(ClassCastException),先判断这个对象是不是某一种类型的Class ,如果是就可以进行强转,不用担心抛出异常导致程序崩溃。
需要注意两点:
1. 如果判断的对象为空,不管这个对象的类型符不符合要求,instanceof 的结果都为 false
2. 如果同时判断两种类型,并且这两种类型是子父类关系,需要注意判断的顺序,先判断子类类型再判断父类类型,因为如果这个对象是子类的对象,不管是判断子类类型还是父类类型都会返回 true,所以这里我们需要先判断是不是子类类型,如果不是子类类型再判断是不是父类类型
5、进程
为了保证不同的应用程序不能互相访问,所以给每个应用程序单独了设置了一个进程,应用程序运行在进程之中,一般情况下一个应用程序只有一个进程,进程与进程不能直接访问,需要通过安卓跨进程通讯 Binder 机制进行通讯。
线程:线程运行在进程之中,必须依赖进程才能存活,线程可以通过抢占CPU的执行权来执行这个线程中的任务,所以线程也就有了优先级这个概念,我们可以通过给线程设置优先级来提升对CPU的抢占率,从而提高任务的执行速度
6、多线程安全的问题
多个线程同时执行,并且向同一个对象进行修改操作的时候,这个时候就会引发线程安全的问题,这个是由于线程执行的不确定性和不完整性导致的,我们不知道线程什么时候执行,什么时候执行完毕,线程总是执行一会儿然后停顿一会儿留点时间给其他线程执行,这样线程之间的交替交叉执行,如果只是对数据的读取操作,则不会出现问题,但是如果写入操作中,数据还没有来得及改变,导致其他线程访问到还只是改变之前的数据
解决方法:
一、使用synchronized (synchronized 修饰普通方法、静态方法、代码块时的差异)
二、使用lock (java中实现同步的两种方式:syschronized和lock的区别和联系)
7、对象序列化
对象序列化是保存对象内容的一种方式,我们可以通过序列化,将这个对象保存成一个数据进行传输,接收方再通过这个数据解析成对象,在Android跨进程通讯中,是不支持使用对象直接通讯的方式,所以需要通过序列化的方式去传递数据
Serializable:这个是Java出的一种序列化方式
Parcelable:这个是Android出的一种序列化方式
Serializable代码的实现方式:
Parcelable的代码实现:
可以很直观得看出 Serializable 用起来比 Parcelable 更简单得多,同样是接口,Serializable 只需要实现这个接口即可,而 Parcelable 需要实现它的 writeToParcel 方法,同时要多创建一个的对象构造函数,还要创建一个内部类,这个内部类的代码思路很简单,创建需要被序列化类的实例对象和数组对象
都说 Parcelable 的效率比 Serializable 要高,那么到底高在哪儿了
Serializable 接口什么方法都没有,而 Parcelable 却要做这些读取保存的操作,同样是接口,同样是序列化,究竟是因为什么导致?
我们设想一下,假如让我们实现和 Serializable 一样的效果,我们会怎么做?或许根本不用想,只能通过反射的形式,反射获取对象字段的值,再通过反射创建一个这个类型的对象,最后再通过反射给这个新对象的字段赋值,从而达到这个新对象里面的内容和之前对象的内容是相同的,虽然它们不是同一个对象,但是对象里面的内容是相同的
Serializable 至少要通过三次以上反射才能完成对对象的Copy,我们都知道反射是一个耗性能低效率的操作,在反射次数比较少的情况下,我们可以忽略不计,如果在反射次数比较多的情况下,Serializable 真的不如 Parcelable,虽然 Parcelable 用起来麻烦,但是在性能优化这块 Parcelable 还是做得比较好的,所以我的建议是,如果被序列化的对象里面的字段很少的情况下,我们可以根据自己的需求来,但是在对象的字段比较复杂的情况下,特别是字段是另一种类型的对象情况下,我们应该选用 Parcelable 来实现对象序列化