Android 面试之java 篇

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/qq_28334473/article/details/88016208

Java方面

1、如何理解Java的多态?其中,重载和重写有什么区别?

多态是一个行为具有多个不同表现形式或形态的能力,多态是同一个接口,使用不同的实例执行不同的操作,多态就是程序运行期间才能确定,一个引用变量到底会指向哪个类的实例对象,该引用变量发出的方法调用到底是哪个类中实现的方法。

多态存在的三个必要条件:集成,重写,父类引用指向子类的引用

重写(Override)和重载(OverLoad) 的区别

2、谈一下JVM内存区域划分?哪部分是线程公有的,哪部分是私有 的?

JVM的内存区域可以分为两类:线程的私有的区域和线程共有的区域。线程私有的区域:程序计数器、JVM虚拟机、本地方法栈;线程共有区域:堆、方法区、运行时常量池。

程序计数器,也有称作PC寄存器。每个线程都有一个私有的程序计数器,任何时间一个线程都只会有一个方法正在执行,也就是所谓的当前方法。程序计数器存放的就是这个当前方法的JVM指令地址。当cpu需要执行指令时,需要从程序计数器中得到当前需要执行的指令所在的存储单元的地址,然后根据得到的地址获取到指令,在得到指令之后,程序计数器便自动加1或者根据转移指针得到下一条指令的地址,如此循环,直至执行完所有的指令。

JVM虚拟机栈。创建线程的时候会创建线程内的虚拟机栈,栈中存放着一个个的栈帧,对应着一个个方法的调用。JVM虚拟机栈有两种操作,分别是压栈和出栈。 栈帧中存放着局部变量表(Local Variables)、操作数栈(Operand Stack)、指向当前方法所属的类的运行时常量池的引用(Reference to runtime constant pool)、方法返回地址(Return Address)和一些额外的附加信息。

本地方法栈。本地方法栈与Java栈的作用和原理非常的相似。区别只不过是Java栈是为执行Java方法服务的,而本地方法栈则是为了执行本地的方法(Native Method)服务的。在JVM规范中,并没有对本地方法栈的具体实现方法以及数据结构作强制规定,虚拟机可以自由实现它。在HotPost虚拟机中直接把本地方法栈和Java栈合二为一。

堆。 堆是内存管理的核心区域,用来存放对象实例。几乎所有创建的对象实例都会直接分配到堆上。所以堆也是垃圾回收的主要区域,垃圾收集器会对堆有着更细的划分,最常见的是新生代和老年代。Java堆允许处于不连续的物理地址空间中,只要逻辑连续即可。堆中如果没有空间完成实例分配无法扩展时将会抛出OutOfMemoryError异常。

方法区。方法区和堆区一样是所有线程所共享的内存区域,它用于存储已被虚拟机加载的类信息、常量、静态变量、即时编译后的代码等数据。在class文件中除了类的字段、方法、接口等描述信息外,还有一项信息是常量池,用来存储编译期间生产的字面量和符号引用。

其实除了程序计数器,其他部分都会发生OOM。

堆。通常发生的OOM都会发生在堆中,最常见的可能导致OOM的原因就是内存泄漏。

JVM虚拟机栈和本地方法栈。当我们写一个递归方法,这个递归方法没有循环的终止条件,最终会导致Stack Overflow的错误。当然如果栈空间扩展失败,也是会发生OOM的。

方法区。方法区现在基本上不会发生OOM。但是在早期的内存中加载的类信息过多的情况下也会发生。

3、final关键字的用法?

final可以修饰类、变量和方法。修饰类代表这个类不可被继承。修饰变量代表此变量不可改变。修饰方法表示此方法不可被重写。

4、死锁怎么导致的?如何定位死锁。

某个任务在等待另一个任务,而后者又等待别的任务,这样一直下去,直到整个链条上的任务又在等待第一个任务释放锁。这得到了一个任务之间互相等待的连续循环,没有哪个线程能继续。这就就被称为死锁。以下四个条件同时满足会产生死锁:

(1)、互斥条件。任务所使用的资源中至少有一个是不能共享的。

(2)、任务必须持有一个资源,同时等待获取另一个被别的任务占用的资源。

(3)、资源不能被强占。

(4)、必须循环等待。一个任务正在等待另一个任务所持有的资源,后者又在等待别的任务所持有的资源,这样一直等待下去,直到一个任务在等待第一个任务所持有的资源,使得大家都被锁住。

要解决死锁的问题,就是打破上面的四个条件的其中一个条件,而在程序中,最容易打破的是第四个条件。

5、数据库如何升级?SQLite增删改查的基础sql语句?

  public SQLiteOpenHelper(Context context, String name, CursorFactory factory, int version) {
        this(context, name, factory, version, null);
    }

    public SQLiteDatabase getWritableDatabase() {
        synchronized (this) {
            return getDatabaseLocked(true);
        }
    }

  private SQLiteDatabase getDatabaseLocked(boolean writable) {
      .......
      db.beginTransaction();
      try {
              if (version == 0) {
                   onCreate(db);
              } else {
                   if (version > mNewVersion) {
                         onDowngrade(db, version, mNewVersion);
                   } else {
                         onUpgrade(db, version, mNewVersion);
                   }
              }
               db.setVersion(mNewVersion);
                db.setTransactionSuccessful();
              } finally {
                 db.endTransaction();
              }
  }

在SQLiteOpenHelper的构造函数中,包含了一个version的参数。这个参数胡即是数据库的版本。所以,我们可以通过修改version来实现数据库的升级,当version大于原数据库的版本之时,onUpgrade()会被触发,可以在该方法中编写数据库升级逻辑。

常用的SQL增删改查:

增:INSERT INTO table_name (列1,列2...)Value (值1,值2 ...)

删:DELETE FROM table_name where 列名称 = 值

改: UPDATE table SET 列名称  = 新值  WHERE 列名称 = 值

查: SELECT 列名称 (通配符 *符号) FROM 表名称 

ps:操作数据表是ALTER TABLE 。该语句用于在已有的表中添加、修改或删除列。

ALTER TABLE table_name ADD column_name datatype

ALTER TABLE table_name DROP COLUMN column_name 

ALTER TABLE table_name _old RENAME TO table_name_new

猜你喜欢

转载自blog.csdn.net/qq_28334473/article/details/88016208