Android&java基础面试题总结(一)

java 创建对象的几种方式

  1. 采用new
  2. 通过反射
  3. 采用clone:注意深度可能和浅度克隆
  4. 通过序列化机制
  • 面向对象的三个特征
    封装,继承,多态
    封装:把对象特征数据化封装起来
    继承:继承父类,复用数据和方法
    多态:重载和重写的时候,对相同方法(方法名相同)做出不同的操作

  • 成员变量,

  1. 成员变量也称为实例变量,成员变量存储在堆内存的对象中,所以也叫对象的特有数据。
  2. 静态变量也称为类变量,静态变量数据存储在方法区(共享数据区)的静态区,所以也叫对象的共享数据
  3. 局部变量只定义在局部范围内,局部变量存在于栈内存中,作用的范围结束,变量空间会自动释放。

method(方法区)又叫静态区,存放所有的①类(class),②静态变量(static变量),③静态方法,④常量和⑤成员方法。被所有的线程共享。方法区中存放的都是在整个程序中永远唯一的元素。这也是方法区被所有的线程共享的原因。

String对象的intern()

public class Test1 {
    public static void main(String[] args) {
        String s11 = new String("aa");
        String s2 = s11.intern();
        String s3 = s11;
        String s1 = "aa";
        System.out.println(s1 == s2);//返回true
        System.out.println(s1 == s3);//返回false
    }
}

返回具体常量池里具有相同值的字符串对象.
intern方法首先会查找常量池是否有相同值的字符串,如果有就返回,没有就在常量池上创建对应字符串并返回.注意:如果本身这个字符串就在常量池里,就返回对象本身,否则返回在常量池上新创建的对象,

String s1=”ab”, String s2=”a”+”b”, String s3=”a”, String s4=”b”, s5=s3+s4请问s5==s2返回什么?

返回false。在编译过程中,编译器会将s2直接优化为”ab”,会将其放置在常量池当中,s5则是被创建在堆区,相当于s5=new String(“ab”);

public class Test2 {
    public static void main(String[] args) {
    
        String s1 = "ab";
        String s2 = "a" + "b";
        String s3 = "a";
        String s4 = "b";
        String s5 = s3 + s4;//
        // 请问s5 == s2\

        System.out.println(s5 == s1);//false
        System.out.println(s2 == s1);//true
        System.out.println(s5 == s2);//false
    }
}

String s1=”ab” ;位于常量池
String s2=”a”+”b”;编译的时候转化成 s2=”ab”,类似s1,在常量池
String s3=”a”, String s4=”b”;在常量池,类似s1
String s5=s3+s4;位于堆,编译器不知道这个s3,s4是否在常量池上,字符串实例化在堆上.

java中==和eqauls()的区别,equals()和hashcode相等的区别

==是一个比较运算符,基本数据类型比较的是值,引用数据类型比较的是地址值。
(比较地址值即是指是否为同一个对象的引用)。

equals()是一个方法,只能比较引用数据类型。重写前比较的是地址值,重写后比一般是比较对象的属性。
如果equals,那么hashcode也要设计为相等,否则会找出list的contains错误。所以在重写eqauls方法的时候一定要重写hashcode方法

深拷贝和浅拷贝的区别是什么?

浅拷贝:被复制对象的所有变量都含有与原来的对象相同的值,而所有的对其他对象的引用仍然指向原来的对象。换言之,浅拷贝仅仅复制所考虑的对象,而不复制它所引用的对象。

深拷贝:被复制对象的所有变量都含有与原来的对象相同的值,而那些引用其他对象的变量将指向被复制过的新对象,而不再是原有的那些被引用的对象。换言之,深拷贝把要复制的对象所引用的对象都复制了一遍。

JAVA中的几种基本数据类型是什么,各自占用多少字节

  • byte(1),char(2),short(2),int(4),boolean(4),float(4),long(8),double(8),boolean由环境虚拟机决定
  • 单例模式的几种实现
    懒汉,饿汉,双重检验,静态内部类,枚举
  • 在自己的代码中,如果创建一个java.lang.String类,这个类是否可以被类加载器加
    载?
    不会,java类加载顺序,优先加载系统的类

Java中字占用字节

取决于java的编码,linux里面java默认编码是utf-8,所占字节有下面几种情况:

  1. 占2个字节的:带有附加符号的拉丁文、希腊文、西里尔字母、亚美尼亚语、希伯来文、阿拉伯文、叙利亚文及它拿字母则需要二个字节编码
  2. 占3个字节的:基本等同于GBK,含21000多个汉字
  3. 占4个字节的:中日韩超大字符集里面的汉字,有5万多个;少数是汉字每个占用3个字节,多数占用4个字节。
  4. 一个utf8数字占1个字节
  5. 一个utf8英文字母占1个字节

JAVA运行时异常及常见的5中RuntimeExecption

ClassCastException(类转换异常)
IndexOutOfBoundsException(数组越界)
NullPointerException(空指针)
SecurityException
数学上除以0的异常

hashmap 和hashtable;StringBuilder和StringBuffer的区别

  • hashmap key可以null,value 可以null,hashtable均不能为null
  • hashtable线程安全,效率低,hashmap线程不安全,效率高
  • StringBuffer线程安全,效率低,StringBuilder线程不安全,效率高

hashSet,linkhashset,TreeSet

  • hashSet 效率最高,无序
  • linkhashset效率略低,有序
  • TreeSet效率最低,可以排序

Parcelable与Serializable的

序列化的目的:

  • 持久保存对象数据;讲对象保存在文件中
  • 将对象数据序列化通过网络以字节流方式进行传输
  • 序列化后进程间通讯

实现的两种方式Serializable,Parcelable

  • Implements Serializable 接口 (声明一下即可)
  • Implements Parcelable 接口(不仅仅需要声明,还需要实现内部的相应方法)

Parcelable与Serializable的性能比较
Parcelable性能明显高于Serializable

Serializable是通过ObjectOutputStram把序列化数据保存在磁盘,Parcelable一般跨进程传递保存在内存的数据,Parcelable如果也要保存到本地,需要利用Parcel方法marshall 和 unmarshall,把对数转换为byte数组。
Parcelable不能使用在要将数据存储在磁盘上的情况,因为Parcelable不能很好的保证数据的持续性在外界有变化的情况下。尽管Serializable效率低点,但此时还是建议使用Serializable 。

如何理解在外界发生改变后,Parcelable不能使用在要将数据存储在磁盘上的情况不能很好的保证数据的持续性?
应该是磁盘序列化后在改变Parcelable实现类之后(外界发生改变后),Parcelable反序列会出现问题(不能保证数据的持续性).

java类中serialversionuid 作用 是什么?举个例子说明

serialVersionUID适用于Java的序列化机制。简单来说,Java的序列化机制是通过判断类的serialVersionUID来验证版本一致性的。在进行反序列化时,JVM会把传来的字节流中的serialVersionUID与本地相应实体类的serialVersionUID进行比较,如果相同就认为是一致的,可以进行反序列化,否则就会出现序列化版本不一致的异常,即是InvalidCastException。

具体的序列化过程是这样的:序列化操作的时候系统会把当前类的serialVersionUID写入到序列化文件中,当反序列化时系统会去检测文件中的serialVersionUID,判断它是否与当前类的serialVersionUID一致,如果一致就说明序列化类的版本与当前类版本是一样的,可以反序列化成功,否则失败。

几种情况A端序列化,B端反序列化,参考https://www.cnblogs.com/duanxz/p/3511695.html:

  • 情况一:A端和B端都需要存在一个相同的类。如果两处的serialVersionUID不一致,异常java.io.InvalidClassException

  • 情况二:假设两处serialVersionUID一致,如果A端增加一个字段,然后序列化,而B端不变,然后反序列化;执行序列化,反序列化正常,但是A端增加的字段丢失(被B端忽略)

  • 情况三:serialVersionUID一致,如果B端减少一个字段,A端不变;序列化,反序列化正常,B端字段少于A端,A端多的字段值丢失(被B端忽略)。

  • 情况四:假设两处serialVersionUID一致,如果B端增加一个字段,A端不变;说明序列化,反序列化正常,B端新增加的int字段被赋予了默认值

    情况三四五就是最终反序列化总是得到a和b两最少的数据

静态变量序列化:
序列化保存的是对象的状态(成员变量的值),静态变量属于类的状态,因此 序列化并不保存静态变量
父类的序列化与 Transient 关键字
问题:一个子类实现了 Serializable 接口,它的父类都没有实现 Serializable 接口,序列化该子类对象,然后反序列化后输出父类定义的某变量的数值,该变量数值与序列化时的数值不同.
解决:要想将父类对象也序列化,就需要让父类也实现Serializable 接口。如果父类不实现的话的,就 需要有默认的无参的构造函数。在父类没有实现 Serializable 接口时,虚拟机是不会序列化父对象的,而一个 Java 对象的构造必须先有父对象,才有子对象,反序列化也不例外。所以反序列化时,为了构造父对象,只能调用父类的无参构造函数作为默认的父对象。因此当我们取父对象的变量值时,它的值是调用父类无参构造函数后的值。如果你考虑到这种序列化的情况,在父类无参构造函数中对变量进行初始化,否则的话,父类变量值都是默认声明的值,如 int 型的默认是 0,string 型的默认是 null。

Transient 关键字的作用是控制变量的序列化,在变量声明前加上该关键字,可以阻止该变量被序列化到文件中,在被反序列化后,transient 变量的值被设为初始值,如 int 型的是 0,对象型的是 null。

特性使用案例

我们熟悉使用 Transient 关键字可以使得字段不被序列化,那么还有别的方法吗?根据父类对象序列化的规则,我们可以将不需要被序列化的字段抽取出来放到父类中,子类实现 Serializable 接口,父类不实现,根据父类序列化规则,父类的字段数据将不被序列化

View的绘制流程(工作流程)

measure过程、layout过程、draw过程
measure:测量VIew的高度,宽度
layout:确定view的位置
draw:绘制view

service生命周期

startservice:onCreate->onstarCommand->onDestory
onbindeService:onCreate->onbind->onUnbide->onDestory

如何理解Activity,View,Window三者之间的关系?

这个问题真的很不好回答。所以先比较恰当的比喻来形容下它们的关系,Activity像一个工匠(控制单元),Window像窗户(承载模型),View像窗花(显示视图)LayoutInflater像剪刀,Xml配置像窗花图纸。

1:Activity构造的时候会初始化一个Window,准确的说是PhoneWindow。

2:这个PhoneWindow有一个“ViewRoot”,这个“ViewRoot”是一个View或者说ViewGroup,是最初始的根视图。

3:“ViewRoot”通过addView方法来一个个的添加View。比如TextView,Button等

4:这些View的事件监听,是由WindowManagerService来接受消息,并且回调Activity函数。比如onClickListener,onKeyDown等。

什么情况下Activity走了onCreat(),而不走onStart()

直接在onCreate就finish掉activity、

Activity生命周期

  • onCreate:activity创建
  • onstart:显示出界面,但是还不可以交互
  • onResume:可以交互,获取焦点
  • onPaushe失去焦点
  • onStop:界面完全消失
  • onDestory:activity销毁

请问Android中跨进程通讯有几种方式

  • AIDL,binder
  • 广播
  • 调用其他应用Activity
  • ContentProvider

ACtivity四种状态

graph LR
开始 --> onCreate,onStart,onRestart,onResume
onCreate,onStart,onRestart,onResume --> 运行
运行 --> onpause
onpause --> 暂停
暂停 --> onstop
onstop --> 停止
停止 --> onDestory
onDestory --> 销毁

你可能感兴趣的:(android,java)