个人复习面试题

 

Java中基本类型占用字节数

在Java中一共有8种基本数据类型,其中有4种整型,2种浮点类型,1种用于表示Unicode编码的字符单元的字符类型和1种用于表示真值的boolean类型。(一个字节等于8个bit)

1.整型

类型              存储需求     bit数    取值范围      备注

int                 4字节           4*8 

short             2字节           2*8    -32768~32767

long              8字节           8*8

byte              1字节           1*8     -128~127

2.浮点型

类型              存储需求     bit数    取值范围      备注

float              4字节           4*8                  float类型的数值有一个后缀F(例如:3.14F)

double          8字节           8*8                       没有后缀F的浮点数值(如3.14)默认为double类型

3.char类型

类型              存储需求     bit数     取值范围      备注

char              2字节          2*8

4.boolean类型

类型              存储需求    bit数    取值范围      备注

boolean        1字节          1*8      false、true

 

1、java中==和equals和hashCode的区别 

基本数据类型的==比较的值相等. 

类的==比较的内存的地址,即是否是同一个对象,在不覆盖equals的情况下,同比较内存地址,原实现也为 == ,如String等重写了equals方法.

hashCode也是Object类的一个方法。返回一个离散的int型整数。在集合类操作中使用,为了提高查询速度。(HashMap,HashSet等比较是否为同一个)

如果两个对象equals,Java运行时环境会认为他们的hashcode一定相等。

如果两个对象不equals,他们的hashcode有可能相等。

如果两个对象hashcode相等,他们不一定equals。

如果两个对象hashcode不相等,他们一定不equals。

 

2、int与integer的区别 

int 基本类型 

integer 对象 int的封装类

(1)Integer是int的包装类;int是基本数据类型; 

(2)Integer变量必须实例化后才能使用;int变量不需要; 

(3)Integer实际是对象的引用,指向此new的Integer对象;int是直接存储数据值 ; 

(4)Integer的默认值是null;int的默认值是0。

 

3、String、StringBuffer、StringBuilder区别 

String:字符串常量 不适用于经常要改变值得情况,每次改变相当于生成一个新的对象

StringBuffer:字符串变量 (线程安全)

StringBuilder:字符串变量(线程不安全) 确保单线程下可用,效率略高于StringBuffer

 

4、进程和线程的区别 

1)进程是cpu资源分配的最小单位,线程是cpu调度的最小单位。

进程之间不能共享资源,而线程共享所在进程的地址空间和其它资源。

一个进程内可拥有多个线程,进程可开启进程,也可开启线程。

一个线程只能属于一个进程,线程可直接使用同进程的资源,线程依赖于进程而存在。

2)线程是进程的子集,一个进程可以有很多线程,每条线程并行执行不同的任务。不同的进程使用不同的内存空间,而所有的线程共享一片相同的内存空间。别把它和栈内存搞混,每个线程都拥有单独的栈内存用来存储本地数据。

5、final,finally,finalize的区别 

final:修饰类、成员变量和成员方法,类不可被继承,成员变量不可变,成员方法不可重写

finally:与try...catch...共同使用,确保无论是否出现异常都能被调用到

finalize:类的方法,垃圾回收之前会调用此方法,子类可以重写finalize()方法实现对资源的回收

6、Serializable 和Parcelable 的区别 

相同点:都是Android中自定义对象的序列化

不同点:

1)      Serializable序列化时会产生大量的临时变量,因而频繁调用GC,

使用内存时Parcelable比Serializable性能高

2)      Parcelable不能使用在要将数据存储在磁盘上的情况,因为Parcelable不能很好的保证数据的持续性在外界有变化的情况下。尽管Serializable效率低点,也不提倡用,但在这种情况下,还是建议用Serializable

3)    Serializable 的实现,只需要继承  implements Serializable 即可

 Parcelabel 的实现,需要在类中实现实现writeToParcel、describeContents函数以及静态成员变量 CREATOR,这个变量需要继承 Parcelable.Creator 接口

4)       Serializable的作用是为了保存对象的属性到本地文件、数据库、网络流、rmi以方便数据传输,当然这种传输可以是程序内的也可以是两个程序间的。而Android的Parcelable的设计初衷是因为Serializable效率过慢,为了在程序内不同组件间以及不同Android程序间(AIDL)高效的传输数据而设计,这些数据仅在内存中存在,Parcelable是通过IBinder通信的消息的载体。

 

7、静态属性和静态方法是否可以被继承?是否可以被重写?以及原因? 

可继承 不可重写 而是被隐藏如果子类里面定义了静态方法和属性,那么这时候父类的静态方法或属性称之为"隐藏"。如果你想要调用父类的静态方法和属性,直接通过父类名.方法或变量名完成。

 

8、什么是内部类?内部类的作用 

内部类可直接访问外部类的属性

Java中内部类主要分为成员内部类、局部内部类(嵌套在方法和作用域内)、匿名内部类(没构造方法)、静态内部类(static修饰的类,不能使用任何外围类的非static成员变量和方法, 不依赖外围类)

9、成员内部类、静态内部类、局部内部类和匿名内部类的理解,以及项目中的应用 

java中内部类主要分为成员内部类、局部内部类(嵌套在方法和作用域内)、匿名内部类(没构造方法)、静态内部类(static修饰的类,不能使用任何外围类的非static成员变量和方法, 不依赖外围类)

使用内部类最吸引人的原因是:每个内部类都能独立地继承一个(接口的)实现,所以无论外围类是否已经继承了某个(接口的)实现,对于内部类都没有影响。

因为Java不支持多继承,支持实现多个接口。但有时候会存在一些使用接口很难解决的问题,这个时候我们可以利用内部类提供的、可以继承多个具体的或者抽象的类的能力来解决这些程序设计问题。可以这样说,接口只是解决了部分问题,而内部类使得多重继承的解决方案变得更加完整。

10、哪些情况下的对象会被垃圾回收机制处理掉?

1.所有实例都没有活动线程访问。

2.没有被其他任何实例访问的循环引用实例。 

3.Java 中有不同的引用类型。判断实例是否符合垃圾收集的条件都依赖于它的引用类型。 

要判断怎样的对象是没用的对象。这里有2种方法:

1.采用标记计数的方法:

给内存中的对象给打上标记,对象被引用一次,计数就加1,引用被释放了,计数就减一,当这个计数为0的时候,这个对象就可以被回收了。当然,这也就引发了一个问题:循环引用的对象是无法被识别出来并且被回收的。所以就有了第二种方法:

2.采用根搜索算法:

从一个根出发,搜索所有的可达对象,这样剩下的那些对象就是需要被回收的

11.Java中实现多态的机制是什么? 

答:方法的重写Overriding和重载Overloading是Java多态性的不同表现

重写Overriding是父类与子类之间多态性的一种表现

重载Overloading是一个类中多态性的一种表现.

 

12、说说你对Java反射的理解 

JAVA反射机制是在运行状态中, 对于任意一个类, 都能够知道这个类的所有属性和方法; 对于任意一个对象, 都能够调用它的任意一个方法和属性。        从对象出发,通过反射(Class类)可以取得取得类的完整信息(类名 Class类型,所在包、具有的所有方法 Method[]类型、某个方法的完整信息(包括修饰符、返回值类型、异常、参数类型)、所有属性 Field[]、某个属性的完整信息、构造器 Constructors),调用类的属性或方法自己的总结: 在运行过程中获得类、对象、方法的所有信息。

 

13、String为什么要设计成不可变的? 

1、字符串池的需求

字符串常量池(String pool, String intern pool, String保留池) 是Java堆内存中一个特殊的存储区域, 当创建一个String对象时,假如此字符串值已经存在于常量池中,则不会创建一个新的对象,而是引用已经存在的对象。

如下面的代码所示,将会在堆内存中只创建一个实际String对象.

String s1 = "abcd";

String s2 = "abcd";

2、允许字符串缓存哈希码

在java中常常会用到字符串的哈希码,例如: HashMap 。String的不变性保证哈希码始终一,因此,他可以不用担心变化的出现。 这种方法意味着不必每次使用时都重新计算一次哈希码——这样,效率会高很多。

3、安全

String广泛的用于java 类中的参数,如:网络连接(Network connetion),打开文件(opening files )等等。如果String不是不可变的,网络连接、文件将会被改变——这将会导致一系列的安全威胁。操作的方法本以为连接上了一台机器,但实际上却不是。由于反射中的参数都是字符串,同样,也会引起一系列的安全问题。

 

13、List,Set,Map的区别

  1. 集合的实现类与区别

答:Collection接口,集合结构总的父接口,有两个子接口list和set

List接口元素有序可重复.

 实现类有:ArrayList 数组实现轻量级,运行快,线程不安全。JDK1.2 查询快

                    Vector 数组实现重量级,运行慢,线程安全。JDK1.0

                    LinkedList链表实现常用语堆栈与队列的实现增删操作快

 

Set 接口元素无序不可重复

实现类有:HashSet,底层用hashCode()算法实现,保证元素的无序唯一,自定义对象存进HashSet为了保证元素内容不重复需要覆盖hashCode()与equals()方法。

 SortedSet(不重要) 元素有序(Unicode升序)唯一

 TreeSet要求元素有序,自定义的对象需要实现Comparable接口的 compareTo(object o)方法

 Map(接口): 与Collection接口无关,有一个子接口SortedMap特点: 元素是key-value, key

 唯一,无序; value可重复

         实现类:

HashMap 轻量级线程不安全的,允许key或value为null JDK1.2

 HashTable 重量级线程安全的不允许key或value为null JDK1.0

          Properties是HashTable的子类,主键和值都是字符串

         SortedMap:(不重要)

         特点: key唯一,有序(Unicode升序)

         实现类:TreeMap

TreeMap : 基于红黑树数据结构的实现。查看“键”或“键值对”时,它们会被排序(次序由Comparabel或Comparator决定)。TreeMap的特点在 于,你得到的结果是经过排序的。TreeMap是唯一的带有subMap()方法的Map,它可以返回一个子树。

LinkedHashMap: 类似于HashMap,但是迭代遍历它时,取得“键值对”的顺序是其插入次序,或者是最近最少使用(LRU)的次序。只比HashMap慢一点。而在迭代访问时发而更快,因为它使用链表维护内部次序。

WeakHashMap :弱键(weak key)Map,Map中使用的对象也被允许释放: 这是为解决特殊问题设计的。如果没有map之外的引用指向某个“键”,则此“键”可以被垃圾收集器回收。

 

14、ArrayMap和HashMap的对比 

1、存储方式不同

HashMap内部有一个HashMapEntry<K, V>[]对象,每一个键值对都存储在这个对象里,当使用put方法添加键值对时,就会new一个HashMapEntry对象,

2、添加数据时扩容时的处理不一样,进行了new操作,重新创建对象,开销很大。ArrayMap用的是copy数据,所以效率相对要高。

3、ArrayMap提供了数组收缩的功能,在clear或remove后,会重新收缩数组,是否空间

4、ArrayMap采用二分法查找;

 

15、HashSet与HashMap怎么判断集合元素重复? 

HashSet不能添加重复的元素,当调用add(Object)方法时候,

首先会调用Object的hashCode方法判hashCode是否已经存在,如不存在则直接插入元素;如果已存在则调用Object对象的equals方法判断是否返回true,如果为true则说明元素已经存在,如为false则插入元素。

 

16、数组和链表的区别

数组:是将元素在内存中连续存储的;它的优点:因为数据是连续存储的,内存地址连续,所以在查找数据的时候效率比较高;它的缺点:在存储之前,我们需要申请一块连续的内存空间,并且在编译的时候就必须确定好它的空间的大小。在运行的时候空间的大小是无法随着你的需要进行增加和减少而改变的,当数据两比较大的时候,有可能会出现越界的情况,数据比较小的时候,又有可能会浪费掉内存空间。在改变数据个数时,增加、插入、删除数据效率比较低。

 

链表:是动态申请内存空间,不需要像数组需要提前申请好内存的大小,链表只需在用的时候申请就可以,根据需要来动态申请或者删除内存空间,对于数据增加和删除以及插入比数组灵活。还有就是链表中数据在内存中可以在任意的位置,通过应用来关联数据(就是通过存在元素的指针来联系)

 

17、run()和start()方法区别 

这个问题经常被问到,但还是能从此区分出面试者对Java线程模型的理解程度。start()方法被用来启动新创建的线程,而且start()内部调用了run()方法,这和直接调用run()方法的效果不一样。当你调用run()方法的时候,只会是在原来的线程中调用,没有新的线程启动,start()方法才会启动新线程。

 

18、在Java中wait和seelp方法的不同; 

Java程序中wait 和 sleep都会造成某种形式的暂停,它们可以满足不同的需要。wait()方法用于线程间通信,如果等待条件为真且其它线程被唤醒时它会释放锁,而sleep()方法仅仅释放CPU资源或者让当前线程停止执行一段时间,但不会释放锁。

 

19、线程有几种状态;

答:1)新建状态(New):新创建了一个线程对象。

2)就绪状态(Runnable):线程对象创建后,其他线程调用了该对象的start()方法。该状态的线程位于可运行线程池中,变得可运行,等待获取CPU的使用权。

3)运行状态(Running):就绪状态的线程获取了CPU,执行run()方法。

4)阻塞状态(Blocked):阻塞状态是线程因为某种原因放弃CPU使用权,暂时停止运行。直到线程进入就绪状态,才有机会转到运行状态。阻塞的情况分三种:

①等待阻塞:运行的线程执行wait()方法,JVM会把该线程放入等待池中。

②同步阻塞:运行的线程在获取对象的同步锁时,若该同步锁被别的线程占用,则JVM会把该线程放入锁池中。

③其他阻塞:运行的线程执行sleep()或join()方法,或者发出了I/O请求时,JVM会把该线程置为阻塞状态。当sleep()状态超时、join()等待线程终止或者超时、或者I/O处理完毕时,线程重新转入就绪状态。

5)死亡状态(Dead):线程执行完了或者因异常退出了run()方法,该线程结束生命周期。

当调用start方法的时候,该线程就进入就绪状态。等待CPU进行调度执行,此时还没有真正执行线程。

当调用run方法的时候,是已经被CPU进行调度,执行线程的主要任务。

  1. 线程的实现方式

答:线程的实现有两种方式,一是继承Thread类,二是实现Runnable接口

  1. sleep() 与 wait()的区别

答:①这两个方法来自不同的类分别是,sleep来自Thread类,和wait来自Object

         类。

         ②最主要是sleep方法没有释放锁,而wait方法释放了锁,使得其他线程可

         以使用同步控制块或者方法。sleep不出让系统资源;wait是进入线程等待池

         等待,出让系统资源,其他线程可以占用CPU。一般wait不会加时间限制,

         因为如果wait线程的运行资源不够,再出来也没用,要等待其他线程调用

         notify/notifyAll唤醒等待池中的所有线程,才会进入就绪队列等待OS分配系

         统资源。sleep(milliseconds)可以用时间指定使它自动唤醒过来,如果时间不到

         只能调用interrupt()强行打断。

3.wait,notify和notifyAll只能在同步控制方法或者同步控制块里面使用,而

sleep可以在任何地方使用

4. Sleep需要捕获异常,而wait不需要

  1. 线程中wait,join,sleep,yield, notify,notifyall,synchronized,区别及联系

答:1).sleep()方法

在指定时间内让当前正在执行的线程暂停执行,但不会释放“锁标志”。不推荐使用。sleep()使当前线程进入阻塞状态,在指定时间内不会执行。

2).wait()方法

在其他线程调用对象的notify或notifyAll方法前,导致当前线程等待。线程会释放掉它所占有的“锁标志”,从而使别的线程有机会抢占该锁。

唤醒当前对象锁的等待线程使用notify或notifyAll方法,waite() 和notify()必须在synchronized函数或synchronizedblock中进行调用。3.yield方法

暂停当前正在执行的线程对象。yield()只是使当前线程重新回到可执行状态,所以执行3)yield()的线程有可能在进入到可执行状态后马上又被执行。yield()只能使同优先级或更高优先级的线程有执行的机会。

4).join方法

等待该线程终止。等待调用join方法的线程结束,再继续执行。如:t.join();//主要用于等待t线程运行结束,若无此句,main则会执行完毕,导致结果不可预测

 

20、synchronized 和volatile 关键字的区别 

1.volatile本质是在告诉jvm当前变量在寄存器(工作内存)中的值是不确定的,需要从主存中读取;synchronized则是锁定当前变量,只有当前线程可以访问该变量,其他线程被阻塞住。

2.volatile仅能使用在变量级别;synchronized则可以使用在变量、方法、和类级别的

3.volatile仅能实现变量的修改可见性,不能保证原子性;而synchronized则可以保证变量的修改可见性和原子性

4.volatile不会造成线程的阻塞;synchronized可能会造成线程的阻塞。

5.volatile标记的变量不会被编译器优化;synchronized标记的变量可以被编译器优化

 

21、死锁的四个必要条件? 

死锁产生的原因

1. 系统资源的竞争

系统资源的竞争导致系统资源不足,以及资源分配不当,导致死锁。

2. 进程运行推进顺序不合适

1)互斥条件:一个资源每次只能被一个进程使用,即在一段时间内某 资源仅为一个进程所占有。此时若有其他进程请求该资源,则请求进程只能等待。

2)请求与保持条件:进程已经保持了至少一个资源,但又提出了新的资源请求,而该资源 已被其他进程占有,此时请求进程被阻塞,但对自己已获得的资源保持不放。

3)不可剥夺条件:进程所获得的资源在未使用完毕之前,不能被其他进程强行夺走,即只能 由获得该资源的进程自己来释放(只能是主动释放)。

4)循环等待条件: 若干进程间形成首尾相接循环等待资源的关系

这四个条件是死锁的必要条件,只要系统发生死锁,这些条件必然成立,而只要上述条件之一不满足,就不会发生死锁。

死锁的避免与预防:

死锁避免的基本思想:

系统对进程发出每一个系统能够满足的资源申请进行动态检查,并根据检查结果决定是否分配资源,如果分配后系统可能发生死锁,则不予分配,否则予以分配。这是一种保证系统不进入死锁状态的动态策略。

理解了死锁的原因,尤其是产生死锁的四个必要条件,就可以最大可能地避免、预防和解除死锁。所以,在系统设计、进程调度等方面注意如何让这四个必要条件不成立,如何确定资源的合理分配算法,避免进程永久占据系统资源。此外,也要防止进程在处于等待状态的情况下占用资源。因此,对资源的分配要给予合理的规划。

死锁避免和死锁预防的区别:

死锁预防是设法至少破坏产生死锁的四个必要条件之一,严格的防止死锁的出现,而死锁避免则不那么严格的限制产生死锁的必要条件的存在,因为即使死锁的必要条件存在,也不一定发生死锁。死锁避免是在系统运行过程中注意避免死锁的最终发生。

 

22、Java中堆和栈有什么不同?

为什么把这个问题归类在多线程和并发面试题里?因为栈是一块和线程紧密相关的内存区域。每个线程都有自己的栈内存,用于存储本地变量,方法参数和栈调用,一个线程中存储的变量对其它线程是不可见的。而堆是所有线程共享的一片公用内存区域。对象都在堆里创建,为了提升效率线程会从堆中弄一个缓存到自己的栈,如果多个线程使用该变量就可能引发问题,这时volatile 变量就可以发挥作用了,它要求线程从主存中读取变量的值。

 

23.线程间通信 handler原理

 我们知道线程是CPU调度的最小单位。在Android中主线程是不能够做耗时操作的,子线程是不能够更新UI的。而线程间通信的方式有很多,比如广播,Eventbus,接口回掉,在Android中主要是使用handler。handler通过调用sendmessage方法,将保存消息的Message发送到Messagequeue中,而looper对象不断的调用loop方法,从messageueue中取出message,交给handler处理,从而完成线程间通信。

 

24.线程池常见的线程池有四种

 Android中常见的线程池有四种,FixedThreadPool、CachedThreadPool、ScheduledThreadPool、SingleThreadExecutor。

1) FixedThreadPool线程池是通过Executors的new FixedThreadPool方法来创建。它的特点是该线程池中的线程数量是固定的。即使线程处于闲置的状态,它们也不会被回收,除非线程池被关闭。当所有的线程都处于活跃状态的时候,新任务就处于队列中等待线程来处理。注意,FixedThreadPool只有核心线程,没有非核心线程。

 2)CachedThreadPool线程池是通过Executors的newCachedThreadPool进行创建的。它是一种线程数目不固定的线程池,它没有核心线程,只有非核心线程,当线程池中的线程都处于活跃状态,就会创建新的线程来处理新的任务。否则就会利用闲置的线程来处理新的任务。线程池中的线程都有超时机制,这个超时机制时长是60s,超过这个时间,闲置的线程就会被回收。这种线程池适合处理大量并且耗时较少的任务。这里得说一下,CachedThreadPool的任务队列,基本都是空的。

 3)ScheduledThreadPool线程池是通过Executors的newScheduledThreadPool进行创建的,它的核心线程是固定的,但是非核心线程数是不固定的,并且当非核心线程一处于空闲状态,就立即被回收。这种线程适合执行定时任务和具有固定周期的重复任务。

 4)SingleThreadExecutor线程池是通过Executors的newSingleThreadExecutor方法来创建的,这类线程池中只有一个核心线程,也没有非核心线程,这就确保了所有任务能够在同一个线程并且按照顺序来执行,这样就不需要考虑线程同步的问题。

 

25.Android中性能优化

由于手机硬件的限制,内存和CPU都无法像pc一样具有超大的内存,Android手机上,过多的使用内存,会容易导致oom,过多的使用CPU资源,会导致手机卡顿,甚至导致anr。我主要是从一下几部分进行优化:

布局优化,绘制优化,内存泄漏优化,响应速度优化,listview优化,bitmap优化,线程优化

布局优化:工具 hierarchyviewer,解决方式:

1、删除无用的空间和层级。

2、选择性能较低的viewgroup,如Relativelayout,如果可以选择Relativelayout也可以使用LinearLayout,就优先使用LinearLayout,因为相对来说Relativelayout功能较为复杂,会占用更多的CPU资源。

3、使用标签<include/>重用布局,<Merge/>减少层级,<viewStub/>进行预加载,使用的时候才加载。

绘制优化

绘制优化指view在ondraw方法中避免大量的耗时操作,由于ondraw方法可能会被频繁的调用。

1、ondraw方法中不要创建新的局部变量,ondraw方法被频繁的调用,很容易引起GC。

2、ondraw方法不要做耗时操作。

内存优化:参考内存泄漏。

响应优化

主线程不能做耗时操作,触摸事件5s,广播10s,service20s。

Bitmap优化:

1、等比例压缩图片。

2、不用的图片,及时recycler掉

线程优化

线程优化的思想是使用线程池来管理和复用线程,避免程序中有大量的Thread,同时可以控制线程的并发数,避免相互抢占资源而导致线程阻塞。

其他优化

1、少用枚举,枚举占用空间大。

2、使用Android特有的数据结构,如SparseArray来代替hashMap。

3、适当的使用软引用和弱引用。

26.MVC作用?

答: Android中界面部分也采用了当前比较流行的MVC框架。

在Android中:

1) 视图层(View):一般采用XML文件进行界面的描述,使用的时候可以非常方

便的引入。也可以使用JavaScript+HTML等的方式作为View层,通过WebView组

件加载,同时可以实现Java和JavaScript之间的通信。    

2) 控制层(Controller):这句话也就暗含了不要在Acitivity中写代码,要通过Activity

交割Model业务逻辑层处理,这样做的另外一个原因是Android中的Acitivity的响

应时间是5s,如果耗时的操作放在这里,Android的控制层的重任通常落在了众多

的Acitvity的肩上,程序就很容易被回收掉。

3)       模型层(Model):对数据库的操作、对网络等的操作都应该在Model里面处理,

当然对业务计算等操作也是必须放在的该层的。

      在Android SDK中的数据绑定,也都是采用了与MVC框架类似的方法来显示数据。在控制层上将数据按照视图模型的要求(也就是Android SDK中的Adapter)封装就可以直接在视图模型上显示了,从而实现了数据绑定。比如显示Cursor中所有数据的ListActivity,其视图层就是一个ListView,将数据封装为ListAdapter,并传递给ListView,数据就在ListView中显示。

27.面向对象的特征有哪些方面?

面向对象的三个基本特征是:封装、继承、多态。

         封装:封装最好理解了。封装是面向对象的特征之一,是对象和类概念的主要特性。封装,也就是把客观事物封装成抽象的类,并且类可以把自己的数据和方法只让可信的类或者对象操作,对不可信的进行信息隐藏。

继承:面向对象编程 (OOP) 语言的一个主要功能就是“继承”。继承是指这样一种能力:它可以使用现有类的所有功能,并在无需重新编写原来的类的情况下对这些功能进行扩展。

通过继承创建的新类称为“子类”或“派生类”。

被继承的类称为“基类”、“父类”或“超类”。

继承的过程,就是从一般到特殊的过程。

要实现继承,可以通过“继承”(Inheritance)和“组合”(Composition)来实现。

在某些 OOP 语言中,一个子类可以继承多个基类。但是一般情况下,一个子类只能有一个基类,要实现多重继承,可以通过多级继承来实现。

多态:多态性(polymorphisn)是允许你将父对象设置成为和一个或更多的他的子对象相等的技术,赋值之后,父对象就可以根据当前赋值给它的子对象的特性以不同的方式运作。简单的说,就是一句话:允许将子类类型的指针赋值给父类类型的指针。

实现多态,有二种方式,覆盖,重载。

覆盖,是指子类重新定义父类的虚函数的做法。

重载,是指允许存在多个同名函数,而这些函数的参数表不同(或许参数个数不同,或许参数类型不同,或许两者都不同)。

那么,多态的作用是什么呢?我们知道,封装可以隐藏实现细节,使得代码模块化;继承可以扩展已存在的代码模块(类);它们的目的都是为了——代码重用。而多态则是为了实现另一个目的——接口重用!多态的作用,就是为了类在继承和派生的时候,保证使用“家谱”中任一类的实例的某一属性时的正确调用

26 .MVC模式和MVP模式的区别

MVC模式:

  1. MVC的所有通信都是单向的。

    2. view传送指令到controller(用户也可以直接将指令传到controller)。

    3. controller完成业务逻辑后要求model改变状态。

    4. model将新的数据发送到view,用户得到反馈。

MVP模式:

    MVP模式将Controller改名为Presenter,同时改变了通信方向。

1. 各部分之间的通信都是双向的。

2. View与Model不发生联系,都通过Presenter传递

3.  View非常薄,不部署任何业务逻辑,称为“被动视图”,即没有任何主动性,而Presenter非常厚,所有逻辑都部署在这里。

 

  1. Overload和Override的区别

Overloaded的方法是否可以改变返回值的类型?

方法的重写Overriding和重载Overloading是Java多态性的不同表现。重写Overriding是父类与子类之间多态性的一种表现,重载Overloading是一个类中多态性的一种表现。如果在子类中定义某方法与其父类有相同的名称和参数,我们说该方法被重写 (Overriding)。子类的对象使用这个方法时,将调用子类中的定义,对它而言,父类中的定义如同被"屏蔽"了。如果在一个类中定义了多个同名的方法,它们或有不同的参数个数或有不同的参数类型,则称为方法的重载(Overloading)。Overloaded的方法是可以改变返回值的类型。

  1. String 和StringBuffer的区别

答: STRING的长度是不可变的,STRINGBUFFER的长度是可变的。如果你对字符串中的内容经常进行操作,特别是内容要修改时,那么使用StringBuffer,如果最后需要String,那么使用StringBuffer(缓存)的toString()方法。

StringBuilder:节约内存,创建字符串;

  1. 实现一个字符串倒序

字符串“abcde”通过写一个函数不让调用第三方的字符串,实现一个字符串倒序,比如字符串“abcde” 变成“edcba”

答: String src = "ABCDEF ";

String dst = new StringBuffer(src).reverse().toString();

  1. 抽象类与接口的区别(abstract与interface的区别)

答:abstract可以修饰抽象方法,而一个类只要有一个抽象方法,就必须用abstract定义该类,即抽象类。抽象类,被继承,实现它里面的方法,可以只有普通方法

用interface修饰的类,里面的方法都是抽象方法(不能实例化),因此在定义接口的时候,可以直接不加那些修饰,系统会默认的添上去。接口里面的字段都是公有常量,即public static final修饰的字段。可以没有函数原型,里面可以是空的

  1. 集合的实现类与区别

答:Collection接口,集合结构总的父接口,有两个子接口list和set

List接口元素有序可重复.

 实现类有:ArrayList 数组实现轻量级,运行快,线程不安全。JDK1.2 查询快

                    Vector 数组实现重量级,运行慢,线程安全。JDK1.0

                    LinkedList链表实现常用语堆栈与队列的实现增删操作快

Set 接口元素无序不可重复

实现类有:HashSet,底层用hashCode()算法实现,保证元素的无序唯一,自定义对象存进HashSet为了保证元素内容不重复需要覆盖hashCode()与equals()方法。

 SortedSet(不重要) 元素有序(Unicode升序)唯一

 TreeSet要求元素有序,自定义的对象需要实现Comparable接口的 compareTo(object o)方法

 Map(接口): 与Collection接口无关,有一个子接口SortedMap特点: 元素是key-value, key

 唯一,无序; value可重复

         实现类: HashMap 轻量级线程不安全的,允许key或value为null JDK1.2

 HashTable 重量级线程安全的不允许key或value为null JDK1.0

          Properties是HashTable的子类,主键和值都是字符串

         SortedMap:(不重要)

         特点: key唯一,有序(Unicode升序)

         实现类:TreeMap

 

Collections是针对集合类的一个帮助类,他提供一系列静态方法实现对各种集合的搜索、排序、线程安全等操作

然后还有混排(Shuffling)、反转(Reverse)、替换所有的元素(fill)、拷贝(copy)、返回Collections中最小元素(min)、返回Collections中最大元素(max)、返回指定源列表中最后一次出现指定目标列表的起始位置(lastIndexOfSubList)、返回指定源列表中第一次出现指定目标列表的起始位置(IndexOfSubList)、根据指定的距离循环移动指定列表中的元素(Rotate)如图:

  1. 常用设计模式及应用场景

常用设计模式及应用场景,用两种方式实现单例模式,要求线程安全

答: 常用设计模式:

 单例模式: Calendar实例的获取

 适配器模式: Adapter 为ListView GridView等添加数据

工厂模式: Spring IOC 反转控制

代理模式: Spring AOP 面向切面编程

观察者模式: ContentObserver监听内容改变

(懒汉式)程序执行过程中需要这个类的对象时再实例化该类的对象

步骤

1)定义静态私有对象

2)构造方法私有化保证在类的外部无法实例化该类的对象

3)定义对外开放的静态方法在调用方法是判断对象是否为空,为空再创建对象返回

 

 

  1. Android的四大组件是什么?它们的作用是什么

答:

Android有四大组件:Activity、Service、Broadcast Receiver、Content Provider。

Activity :应用程序中,一个Activity通常就是一个单独的屏幕,它上面可以显示一些控件也可以监听并处理用户的事件做出响应。Activity之间通过Intent进行通信。

Service 服务:一个Service 是一段长生命周期的,没有用户界面的程序,可以用来开发如监控类程序。

BroadcastReceive广播接收器:你的应用可以使用它对外部事件进行过滤只对感兴趣的外部事件(如当电话呼入时,或者数据网络可用时)进行接收并做出响应。广播接收器没有用户界面。然而,它们可以启动一个activity或serice 来响应它们收到的信息。

Content Provider内容提供者 :主要用于多个应用间数据共享。这些数据可以存储在文件系统中或SQLite数据库。

 

  1. Activity生命周期?保存activity的一些信息在哪个生命周期方法中

横竖屏切换activity的生命周期

答:共有七个周期函数:

void onCreate(Bundle savedInstanceState) 第一次创建时调用

void onStart() 被用户可见时调用

void onRestart() 当Activity处于stop状态又被重新启动时调用

void onResume() 当获得焦点即可与用户交互时调用

void onPause() 当失去焦点时调用

void onStop() 当不可见时调用

void onDestroy() 当销毁时调用

 

  1. Android中的五种存储方式及其应用场景

答:1)SharedPreferences

存储路径:(data/data/packagename/shares_prefs), 轻量级存储,以键值对的形式存储在xml中,一般用来保存应用中的设置属性

 2)文件存储 SD卡存储多媒体文件, 文件缓存

 3) Sqlite数据库 存储路径:(data/data/packagename/databases), 一种嵌入式数据库,支持sql语言,存储大量结构性数据

 4)ContentProvider 进程(应用程序)间数据共享,数据源可以是sqlite,也可以是xml,相关类: ContentResolver(内容解析器), ContentObserver(数据 观察者)

 5) 网络存储 天气数据的xml,json格式等等,通过HttpUrlConnection,HttpClient,或者SOAP协议获取数据

 

  1. 简述Android中的IPC机制

IPC(Inter-Process Communication,进程间通信),aidl是 Android Interface definition language的缩写,它是一种android内部进程通信接口的描述语言,通过它我们可以定义进程间的通信接口.编译器可以通过扩展名为aidl的文件生成一段代码,通过预先定义的接口达到两个进程内部通信进程的目的.

BroadcastReceiver也可以实现进程间通信

ContentProvider 提供进程间数据共享

 

  1. 请介绍下ContentProvider是如何实现数据共享的。

一个程序可以通过实现一个Content provider的抽象接口将自己的数据完全暴露出去,而且Content providers是以类似数据库中表的方式将数据暴露。Content providers存储和检索数据,通过它可以让所有的应用程序访问到,这也是应用程序之间唯一共享数据的方法。

要想使应用程序的数据公开化,可通过2种方法:创建一个属于你自己的Content provider或者将你的数据添加到一个已经存在的Content provider中,前提是有相同数据类型并且有写入Content provider的权限。

如何通过一套标准及统一的接口获取其他应用程序暴露的数据

    Android提供了ContentResolver,外界的程序可以通过ContentResolver接口访问ContentProvider提供的数据。

 

  1. Activity

如果后台的Activity由于某原因被系统回收了,如何在被系统回收之前保存当前状态?

答:重写onSaveInstanceState()方法,在此方法中保存需要保存的数据,该方法将会在activity被回收之前调用。通过重写onRestoreInstanceState()方法可以从中提取保存好的数据

 

1)强引用

平时我们编程的时候例如:Object object=new Object();那object就是一个强引用了。如果一个对象具有强引用,那就类似于必不可少的生活用品,垃圾回收器绝不会回收它。当内存空间不足,Java虚拟机宁愿抛出OutOfMemoryError错误,使程序异常终止,也不会靠随意回收具有强引用的对象来解决内存不足问题。

2)软引用(SoftReference)

如果一个对象只具有软引用,那就类似于可有可物的生活用品。如果内存空间足够,垃圾回收器就不会回收它,如果内存空间不足了,就会回收这些对象的内存。只要垃圾回收器没有回收它,该对象就可以被程序使用。软引用可用来实现内存敏感的高速缓存。软引用可以和一个引用队列(ReferenceQueue)联合使用,如果软引用所引用的对象被垃圾回收,Java虚拟机就会把这个软引用加入到与之关联的引用队列中。

3)弱引用(WeakReference)

如果一个对象只具有弱引用,那就类似于可有可物的生活用品。弱引用与软引用的区别在于:只具有弱引用的对象拥有更短暂的生命周期。在垃圾回收器线程扫描它所管辖的内存区域的过程中,一旦发现了只具有弱引用的对象,不管当前内存空间足够与否,都会回收它的内存。不过,由于垃圾回收器是一个优先级很低的线程,因此不一定会很快发现那些只具有弱引用的对象。弱引用可以和一个引用队列(ReferenceQueue)联合使用,如果弱引用所引用的对象被垃圾回收,Java虚拟机就会把这个弱引用加入到与之关联的引用队列中。

4)虚引用(PhantomReference)

"虚引用"顾名思义,就是形同虚设,与其他几种引用都不同,虚引用并不会决定对象的生命周期。如果一个对象仅持有虚引用,那么它就和没有任何引用一样,在任何时候都可能被垃圾回收。虚引用主要用来跟踪对象被垃圾回收的活动。虚引用与软引用和弱引用的一个区别在于:虚引用必须和引用队列(ReferenceQueue)联合使用。当垃圾回收器准备回收一个对象时,如果发现它还有虚引用,就会在回收对象的内存之前,把这个虚引用加入到与之关联的引用队列中。程序可以通过判断引用队列中是否已经加入了虚引用,来了解被引用的对象是否将要被垃圾回收。程序如果发现某个虚引用已经被加入到引用队列,那么就可以在所引用的对象的内存被回收之前采取必要的行动。

27.android中的动画有哪几类,它们的特点和区别是什么?

答:Android中动画可以分为两大类:帧动画、补间动画

1)补间动画:(你定义一个开始和结束,中间的部分由程序运算得到。就是对场景里的对象不断的进行图像变化来产生动画效果(旋转、平移、放缩和渐变))AlphaAnimation(渐变型动画)、scaleAnimation(缩放型动画)、 TranslateAnimation(平移型动画)、 RotateAnimation(旋转型动画)、

2)逐帧动画:Frame(把一连串的图片进行系列化连续播放,如同放电影的效果),它是通过播放一张一张图片来达到动画的效果;

3)属性动画(Property Animation):通过改变对象的属性值来实现的动画效果,不局限使用在View上。

由于补间动画的局限性,Android团队在3.0版本中引入了属性动画,它的功能相当强大,弥补了补间动画的不足,几乎可以完全替代补间动画了。

ValueAnimator是整个属性动画机制中最核心的一个类,因为属性动画就是通过不断的改变对象的属性值来实现的动画效果,初始值和结束值之间的动画过渡就是由ValueAnimator这个类来完成计算的。

28.handler机制的原理,looper通过什么方法开始的?

一个Handler允许你发送和处理Message和Runable对象,每个线程都有自己的Looper,每个Looper中封装着MessageQueue。Looper负责不断的从自己的消息队列里取出队头的任务或消息执行。每个handler也和线程关联,Handler负责把Message和Runable对象传递给MessageQueue(用到post ,sendMessage等方法),而且在这些对象离开MessageQueue时,Handler负责执行他们(用到handleMessage方法)。

其中Message类就是定义了一个信息,这个信息中包含一个描述符和任意的数据对象,这个信息被用来传递给Handler.Message对象提供额外的两个int域和一个Object域。

默认情况下一个线程是不存在消息循环(message loop)的,需要调用Looper.prepare()来给线程创建一个消息循环,调用Looper.loop()来使消息循环起作用,从消息队列里取消息,处理消息。调用Looper.loop()之后循环已经开始,下一个由handler发的message将会被这个handler的handleMessage方法处理,这是一个----循环。

Looper从MessageQueue中取出Message之后,交由Handler的handleMessage进行处理。处理完成后,调用Message.recycle()将其放入Message Pool中。

30.如何让Activity变成一个窗口?

答:在清单文件AndroidManifest.xml中相应的<activity>标签内设置属性android:theme=”@android:style/Theme.Dialog”

34.View如何刷新?

安卓要更新界面不要在主线程中去做

如果是在线程thread中获取到了新的数据,需要配合使用hanlder进行刷新.

在线程中刷新View用postinvalidate();

在UI线程中刷新View的方法是invalidate()函数,

当调用线程处于空闲状态时,调onDraw()刷新界面

 

如果是listView刷新数据,用adapter.notifyDataSetInvalidated();

adapter.notifyDataSetChanged();

37.链表和数组的区别?

数组是将元素在内存中连续存放,由于每个元素占用内存相同,可以通过下标迅速访问数组中任何元素。但是如果要在数组中增加一个元素,需要移动大量元素,在内存中空出一个元素的空间,然后将要增加的元素放在其中。同样的道理,如果想删除一个元素,同样需要移动大量元素去填掉被移动的元素。如果应用需要快速访问数据,很少或不插入和删除元素,就应该用数组。

链表恰好相反,链表中的元素在内存中不是顺序存储的,而是通过存在元素中的指针联系到一起。比如:上一个元素有个指针指到下一个元素,以此类推,直到最后一个元素。如果要访问链表中一个元素,需要从第一个元素开始,一直找到需要的元素位置。但是增加和删除一个元素对于链表数据结构就非常简单了,只要修改元素中的指针就可以了。如果应用需要经常插入和删除元素你就需要用链表数据结构了。

二者都属于一种数据结构

  (1) 从逻辑结构角度来看

     a, 数组必须事先定义固定的长度(元素个数),不能适应数据动态地增减的情况。当数据增加时,可能超出原先定义的元素个数;当数据减少时,造成内存浪费。

     b,链表动态地进行存储分配,可以适应数据动态地增减的情况,且可以方便地插入、删除数据项。(数组中插入、删除数据项时,需要移动其它数据项)

  (2)从内存存储角度来看

     a,(静态)数组从栈中分配空间, 对于程序员方便快速,但自由度小。

     b, 链表从堆中分配空间, 自由度大但申请管理比较麻烦.

 

46.常用的排序法?

答: 冒泡排序O(n^2) : 冒泡排序也是最简单最基本的排序方法之一。冒泡排序的思想很简单,就是以此比较相邻的元素大小,将小的前移,大的后移,就像水中的气泡一样,最小的元   素经过几次移动,会最终浮到水面上。

for (int i = 0; i < num.length; i++) {     

// 内循环控制比较后移位     

for (int j = num.length-1; j > i ; j--) {     

                if (num[j-1]>num[j]) {     

                    temp = num[j-1];     

                    num[j-1] = num[j];     

                    num[j] = temp;     

                }     

            }  

快速排序O(n log n)  : 快速排序采用的思想是分治思想。快速排序算法的核心算法是分区操作,即如何调整基准的位置以及调整返回基准的最终位置以便分治递归。

插入排序 O(n^2) :将新来的元素按顺序放入一个已有的有序序列当中。

选择排序 O(n^2) :第i趟简单选择排序是指通过n-i次关键字的比较,从n-i+1个记录中选出关键字最小的记录,并和第i个记录进行交换。共需进行i-1趟比较,直到所有记录排序完成为止。

 

87.请说出使用equal和==比较对象时的区别?

答:“==”比较的是2个对象的地址,而equals比较的是2个对象的内容。例如两个String类型的对象:String s1 = new String(“str”);

String s2 = new String(“str”);

用“==”比较的时候返回的是false,因为创建了两个对象,在内存中的地址不一样,用equals则返回true。

4.Activity的启动方式 

    1. standard

        模式启动模式,每次激活Activity时都会创建Activity,并放入任务栈中。

    2. singleTop

        如果在任务的栈顶正好存在该Activity的实例, 就重用该实例,否者就会创建新的实例并放入栈顶(即使栈中已经存在该Activity实例,只要不在栈顶,都会创建实例)。

    3. singleTask

       如果在栈中已经有该Activity的实例,就重用该实例(会调用实例的onNewIntent())。重用时,会让该实例回到栈顶,因此在它上面的实例将会被移除栈。如果栈中不存在该实例,将会创建新的实例放入栈中。  

    4. singleInstance

        在一个新栈中创建该Activity实例,并让多个应用共享改栈中的该Activity实例。一旦改模式的Activity的实例存在于某个栈中,任何应用再激活改Activity时都会重用该栈中的实例,其效果相当于多个应用程序共享一个应用,不管谁激活该Activity都会进入同一个应用中。

 

80.UDP和TCP的区别?

首先我们看一下UDP和TCP的特点:

TCP(Transmission Control Protocol,传输控制协议)提供的是面向连接,可靠的字节流服务。即客户和服务器交换数据前,必须现在双方之间建立一个TCP连接,之后才能传输数据。并且提供超时重发,丢弃重复数据,检验数据,流量控制等功能,保证数据能从一端传到另一端。

UDP(User Data Protocol,用户数据报协议)是一个简单的面向数据报的运输层协议。它不提供可靠性,只是把应用程序传给IP层的数据报发送出去,但是不能保证它们能到达目的地。由于UDP在传输数据报前不用再客户和服务器之间建立一个连接,且没有超时重发等机制,所以传输速度很快。
————————————————

1 无连接和面向连接

UDP:“无连接”

在网络中使用UDP协议时,只需要提供对端的IP地址和端口号PORT就可以与对端进行通信,并不需要和对端建立连接

TCP:“面向连接”“三次握手、四次挥手”

在网络中使用TCP协议时,不仅需要对端的IP地址和端口号PORT,还需要通过“三次握手”建立连接,“四次挥手”断开连接

 

ANR类型

Service Timeout: 前台服务20s, 后台服务200s

BroadcastQueue Timeout: 前台广播 10s,后台广播60s

ContentPrivider Timeout: 10s

InputDispatching Timeout: 5s

 

LeakCanary是怎样实现内存泄露的检测。
利用Application#registerActivityLifecycleCallbacks Activity生命周期回调onActivityDestroyed方法通过调用RefWatcher#wather方法来检测对象是否回收,通过removeWeaklyReachableReferences--->gcTrigger.runGc--->removeWeaklyReachableReferences--->heapdumpListener.analyze 三步二次检测来确定内存泄露,最终dump 内存信息来分析到最终显示分析出的泄露信息。

 

HTTP与HTTPS的区别
  1、http是超文本传输协议,信息是明文传输,https则是具有安全性的ssl加密传输协议。
  2、https协议需要到ca申请证书,一般免费证书较少,因而需要一定费用。
  3、http和https使用的是完全不同的连接方式,用的端口也不一样,前者是80,后者是443。
  4、http的连接很简单,是无状态的;HTTPS协议是由SSL+HTTP协议构建的可进行加密传输、身份认证的网络协议,比http协议安全。

HTTPS的优缺点

优点:

1、使用HTTPS协议可认证用户和服务器,确保数据发送到正确的客户机和服务器;

2、HTTPS协议是由SSL+HTTP协议构建的可进行加密传输、身份认证的网络协议,要比http协议安全,可防止数据在传输过程中不被窃取、改变,确保数据的完整性。

3、HTTPS是现行架构下最安全的解决方案,虽然不是绝对安全,但它大幅增加了中间人攻击的成本。

缺点:

1、HTTPS协议握手阶段比较费时,会使页面的加载时间延长近50%,增加10%到20%的耗电;

2、HTTPS连接缓存不如HTTP高效,会增加数据开销和功耗,甚至已有的安全措施也会因此而受到影响;

3、SSL证书需要钱,功能越强大的证书费用越高,个人网站、小网站没有必要一般不会用。

4、SSL证书通常需要绑定IP,不能在同一IP上绑定多个域名,IPv4资源不可能支撑这个消耗。

5、HTTPS协议的加密范围也比较有限,在黑客攻击、拒绝服务攻击、服务器劫持等方面几乎起不到什么作用。最关键的,SSL证书的信用链体系并不安全,特别是在某些国家可以控制CA根证书的情况下,中间人攻击一样可行。


 

 

 

 

 

 

1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 、4下载使用后,可先查看README.md或论文文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。 5、资源来自互联网采集,如有侵权,私聊博主删除。、可私 6信博主看论文后选择购买源代码。 1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 、4下载使用后,可先查看README.md或论文文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。 5、资源来自互联网采集,如有侵权,私聊博主删除。、可 6私信博主看论文后选择购买源代码。 1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 、4下载使用后,可先查看README.md或论文文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。 5、资源来自互联网采集,如有侵权,私聊博主删除。、可私 6信博主看论文后选择购买源代码。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值