01、抽象类和接口的区别
接口是对动作的抽象,抽象类是对根源的抽象。
- 抽象类要被子类继承,接口要被子类实现。
- 抽象类和接口都不能直接实例化,如果要实例化,抽象类变量必须指向实现所有抽象方法的子类对象,接口变量必须指向实现所有接口方法的类对象。
- 接口里面只能对方法进行声明,抽象类既可以对方法进行声明也可以对方法进行实现。
- 接口里定义的变量只能是公共的静态的常量,抽象类中的变量是普通变量。
- 抽象类里的抽象方法必须全部被子类所实现,如果子类不能全部实现父类抽象方法,那么该子类只能是抽象类。同样,一个实现接口的时候,如不能全部实现接口方法,那么该类也只能为抽象类。
- 抽象方法只能申明,不能实现,接口是设计的结果 ,抽象类是重构的结果
- 抽象类里可以没有抽象方法,如果一个类里面有抽象方法,那么这个类一定是抽象类。
02、(持久化)数据存储(五种)
- 网络存储:使用http(s)协议或者Socket通信作为传输方式。应用网络框架来接收/发送数据,数据格式通常是XML、Json。由于数据在传输过程中容易丢包、拦截,所以其安全性最差。
- 文件存储:通过字节流操作,对二进制数据进行处理。
- 数据库存储:SQLite是一个轻量级数据库,以及在其基础上封装的一些数据库框架,还有其他方式的数据库等。是一个数据列表的方式存储数据,其在安全上和存取效率上也是最好的。
- ContentProvider:在不同应用程序中共享数据时,其数据的暴露方式是采取类似数据库中表的方式,它是通过Uri来查询ContentProvider中的数据的。
- SharePreference:是一种轻量级的数据存储机制,它可以将一些简单数据类型的数据,以键值对的方式存储在应用程序的目录中,以XML格式存在。
03、泛型中extends和super的区别
上界类型通配符(? extends)
下界类型通配符(? super )
- 限定通配符总是包括自己
- 上界类型通配符:add方法受限
- 下界类型通配符:get方法受限
- 如果你想从一个数据类型里获取数据,使用 ? extends 通配符
- 如果你想把对象写入一个数据结构里,使用 ? super 通配符
- 如果你既想存,又想取,那就别用通配符
- 不能同时声明泛型通配符上界和下界
04、父类的静态方法能否被子类重写
- 静态方法:java中,static修饰符修饰的方法就是静态方法。所谓静态就是指:在编译之后所分配的内存会一直存在(不会被回收),直到程序退出内存才会释放这个空间。
- 重写:子类继承父类后,定义了一个和父类中的一模一样方法,这个一模一样是值方法名和参数的定义一模一样。这时候子类要实现这个方法,就称为对父类方法的重写。
- 父类的静态方法可以被子类继承,但是不能重写。
05、进程和线程的区别
- 进程是操作系统资源分配的基本单位
- 线程是任务调度和执行的基本单位
- 进程是资源分配的最小单位,线程是程序执行的最小单位。
- 进程有自己的独立地址空间,每启动一个进程,系统就会为它分配地址空间,建立数据表来维护代码段、堆栈段和数据段,这种操作非常昂贵。而线程是共享进程中的数据的,使用相同的地址空间,因此CPU切换一个线程的花费远比进程要小很多,同时创建一个线程的开销也比进程要小很多。
- 线程之间的通信更方便,同一进程下的线程共享全局变量、静态变量等数据,而进程之间的通信需要以通信的方式(IPC)进行。不过如何处理好同步与互斥是编写多线程程序的难点。
- 但是多进程程序更健壮,多线程程序只要有一个线程死掉,整个进程也死掉了,而一个进程死掉并不会对另外一个进程造成影响,因为进程有自己独立的地址空间。
06、final,finally,finalize的区别
- final修饰符(关键字),final可以用来修饰类,方法和变量(成员变量或局部变量)。修饰的类不能被继承。修饰的变量和方法不能被修改。
- 异常处理的一部分,它只能用在try/catch语句中。
- finalize()方法,在Object中定义,该方法一般由垃圾回收器来调用,当我们调用System的gc()方法的时候,由垃圾回收器调用finalize(),回收垃圾。