Android面试题总结(三)

十二、Java基础部分

12.1 什么是重载,什么是重写,有什么区别?
重载(Overloading):
(1)Overloading是一个类中多态性的一种表现,让类以统一的方式处理不同类型数据的一种手段。多个同名函数同时存在,具有不同的参数个数/类型。
(2)重载的时候,方法名要一样,但是参数类型和个数不一样,返回值类型可以相同,也可以不相同。无法以返回型别作为重载函数的区分标准。

重写(Overriding):
(1) 父类与子类之间的多态性,对父类的函数进行重新定义。即在子类中定义某方法与其父类有相同的名称和参数。
(2)若子类中的方法与父类中的某一方法具有相同的方法名、返回类型和参数表,则新方法将覆盖原有的方法。如需父类中原有的方法,可使用super关键字,该关键字引用了当前类的父类

12.2 Java的反射机制是怎样的
要让Java程序能够运行,就得让Java类被Java虚拟机加载。Java类如果不被Java虚拟机加载就不能正常运行。正常情况下,我们运行的所有的程序在编译期时候就已经把那个类被加载了。

Java的反射机制是在编译时并不确定是哪个类被加载了,而是在程序运行的时候才加载、探知、自审。使用的是在编译期并不知道的类。这样的编译特点就是java反射

Java的反射机制它知道类的基本结构,这种对Java类结构探知(此外学还有其它东西)的能力,我们称为Java类的“自审”。在Android Studio中编译工具就会自动的把该对象能够使用的所有的方法和属性全部都列出来,供用户进行选择。这就是利用了Java反射的原理,是对我们创建对象的探知、自审。

要正确使用Java反射机制就得使用java.lang.Class这个类,在反射api中有一些方法如forName,getClass,getPackage,getName,getDeclaredField,getDeclaredMethods等等来探知类信息。

有一个简单的例子来理解:
http://blog.csdn.net/ljphhj/article/details/12858767

12.3 String、StringBuffer和StringBuilder的区别
JAVA早期平台提供了两个类:String和StringBuffer,它们可以储存和操作字符串,即包含多个字符的字符数据。这个String类提供了数值不可改变的字符串。而这个StringBuffer类提供的字符串可以进行修改。当你知道字符数据要改变的时候你就可以使用StringBuffer。。String类是不可变类,任何对String的改变都会引发新的String对象的生成;而StringBuffer则是可变类,任何对它所指代的字符串的改变都不会产生新的对象。
StringBuilder是后面引入的,它与StringBuffer类的区别在于,新引入的StringBuilder类不是线程安全的,但其在单线程中的性能比StringBuffer高。 (有兴趣的可以去读下《Think in Java》描述HashTable和HashMap区别的那部分章节比较熟悉的话,就是支持线程同步保证线程安全而导致性能下降的问题)
典型地,你可以使用StringBuffers来动态构造字符数据。另外,String实现了equals方法,new String(“abc”).equals(newString(“abc”)的结果为true,而StringBuffer没有实现equals方法,所以,new StringBuffer(“abc”).equals(newStringBuffer(“abc”)的结果为false。

12.4 关键字final和static是怎么使用的
final有着“终态的”“这是无法改变的”含义,阻止了多态和继承。
具体使用有:
final类不能被继承,没有子类,final类中的方法默认是final的。
final方法不能被子类的方法覆盖,但可以被继承。
final成员变量表示常量,只能被赋值一次,赋值后值不再改变。
final不能用于修饰构造方法。
注意:父类的private成员方法是不能被子类方法覆盖的,因此private类型的方法默认是final类型的。

static表示“全局”或者“静态”的意思,用来修饰成员变量和成员方法,也可以形成静态static代码块,但是Java语言中没有全局变量的概念。
被static修饰的成员变量和成员方法独立于该类的任何对象,static对象可以在它的任何对象创建之前访问,无需引用任何对象。
static前面也可用public或private来修饰,其中private是访问权限限定,static表示不要实例化就可以使用
主要用于静态变量,静态方法,static代码块
静态变量:对于静态变量在内存中只有一个拷贝(节省内存),JVM只为静态分配一次内存,在加载类的过程中完成静态变量的内存分配,可用类名直接访问(方便),当然也可以通过对象来访问(但是这是不推荐的)。
静态方法: 静态方法可以直接通过类名调用,任何的实例也都可以调用,因此静态方法中不能用this和super关键字,不能直接访问所属类的实例变量和实例方法(就是不带static的成员变量和成员成员方法),只能访问所属类的静态成员变量和成员方法。因为实例成员与特定的对象关联!
static代码块:atic代码块也叫静态代码块,是在类中独立于类成员的static语句块,可以有多个,位置可以随便放,它不在任何的方法体内,JVM加载类时会执行这些静态的代码块,如果static代码块有多个,JVM将按照它们在类中出现的先后顺序依次执行它们,每个代码块只会被执行一次

static和final一起使用
static final用来修饰成员变量和成员方法,可简单理解为“全局常量”!
对于变量,表示一旦给值就不可修改,并且通过类名可以访问。
对于方法,表示不可覆盖,并且可以通过类名直接访问。
特别要注意一个问题:
对于被static和final修饰过的实例常量,实例本身不能再改变了,但对于一些容器类型(比如,ArrayList、HashMap)的实例变量,不可以改变容器变量本身,但可以修改容器中存放的对象,这一点在编程中用到很多。

十四、说一说观察者模式(设计模式)

(1)观察者模式
定义了对象之间的一对多的依赖,这样一来,当一个对象改变时,它的所有的依赖者都会收到通知并自动更新。(以实例来理解,如微信服务号,服务号就是主题(subject),业务就是推送消息,普通用户是观察者(observer),观察者订阅,服务号有新消息就会推送给他,如果没有取消订阅,服务号不再推送。如果没有用户订阅,服务号也是存在的)

观察者模式实现的关键是要建立观察者和被观察者之间的联系、比如在被观察者类(实例subject)中有个集合是用于存放观察者的、当被检测的东西发生改变的时候就要通知所有观察者。在观察者(observer)的构造方法中将被观察者传入、同时将本身注册到被观察者拥有的观察者名单中、即observers这个list中(即在observer实例构造方法中传入subject并将自身注册进去这个subject中,subject.registerObserver(this);)

对于JDK或者Andorid中都有很多地方实现了观察者模式,比如XXXView.addXXXListenter , 当然了 XXXView.setOnXXXListener不一定是观察者模式,因为观察者模式是一种一对多的关系,对于setXXXListener是1对1的关系,应该叫回调。

另外:java中已经帮我们实现了观察者模式,借助于java.util.Observable和java.util.Observer。

(2)工厂模式
工厂模式主要是为创建对象提供过渡接口,以便将创建对象的具体过程屏蔽隔离起来,达到提高灵活性的目的。
1.静态工厂模式
所谓的工厂就是使用Java代码实现的创建实例的一种方式、比如常用的单例模式就是一种静态工厂方法
2.简单工厂模式(Simple Factory)
定义了一个用于创建对象的接口,建立工厂类角色,抽象产品角色,具体产品角色的关系,简单工厂模式中只有一个工厂类来对应这些产品,增加产品都需要在工厂类中进行业务逻辑判断。
3.工厂方法模式(Factory Method)
总共有四个角色,抽象工厂,具体工厂,抽象产品,具体产品。在具体工厂角色中:它含有和具体业务逻辑有关的代码。由应用程序调用以创建对应的具体产品的对象。
4.抽象工厂模式(Abstract Factory)
抽象工厂模式的用意为:给客户端提供一个接口,可以创建多个产品族中的产品对象。换句话说就是:提供一个接口,用于创建相关的或依赖对象的家族,而不需要明确指定具体类。
抽象工厂模式与工厂方法模式的区别:
工厂方法模式只有一个抽象产品类,而抽象工厂模式有多个。
工厂方法模式的具体工厂类只能创建一个具体产品类的实例,而抽象工厂模式可以创建多个。
可参考鸿洋博客的例子理解:
http://blog.csdn.net/lmj623565791/article/details/24460585

十三、ANR是什么,产生的原因及如何避免

ANR的全称是Android Not Responding,表现是弹出无响应框,用户可以选择“等待”而让程序继续运行,也可以选择“强制关闭”。

原因:
在Android里,应用程序的响应性是由Activity ManagerWindowManager系统服务监视的 。当它监测到以下情况中的一个时,Android就会针对特定的应用程序显示ANR:
1.在5秒内没有响应输入的事件(例如,按键按下,屏幕触摸)
2.BroadcastReceiver在10秒内没有执行完毕
3.ServiceTimeout(20 seconds) –小概率类型 Service在特定的时间内无法处理完成
造成以上两点的原因有很多,比如在主线程中做了非常耗时的操作,比如说是下载,io异常等。

避免:
1、运行在主线程里的任何方法都尽可能少做事情。特别是,Activity应该在它的关键生命周期方法(如onCreate()和onResume())里尽可能少的去做创建操作。

2、应用程序应该避免在BroadcastReceiver里做耗时的操作或计算。但不再是在子线程里做这些任务(因为 BroadcastReceiver的生命周期短),替代的是,如果响应Intent广播需要执行一个耗时的动作的话,应用程序应该启动一个 Service。(此处需要注意的是可以在广播接受者中启动Service,但是却不可以在Service中启动broadcastEReceiver)

如何确定ANR
1. 根据CPU的使用情况确定:
如果CPU使用量接近100%,说明当前设备很忙,有可能是CPU饥饿导致了ANR。如果CPU使用量很少,说明主线程被BLOCK了。
如果IOwait很高,说明ANR有可能是主线程在进行I/O操作造成的
2.解决ANR还得需要trace.txt文件,

如何获取呢?可以用如下命令获取

$chmod 777 /data/anr

$rm /data/anr/traces.txt

$ps

$kill -3 PID

adbpull data/anr/traces.txt ./mytraces.txt
分析trace.txt文件得到相应的信息。

你可能感兴趣的:(Android面试题总结(三))