如何拿到大厂offer,有些宝典还会难吗?


        终于进入码农乐园,今天我把之前面试过一些题目和收集的题目在这里和大家探讨一下,请小伙伴们笑纳~

面试怎么玩?

Java基础试题

1、接口的意义-(百度 面试题)

1)、重要性:在Java语言中, abstract class 和interface 是支持抽象类定义的两种机制。正是由于这两种机制的存在,才赋予了Java强大的 面向对象能力。

2)、简单、规范性:如果一个项目比较庞大,那么就需要一个能理清所有业务的架构师来定义一些主要的接口,这些接口不仅告诉开发人员你需要实现那些业务,而且也将命名规范限制住了(防止一些开发人员随便命名导致别的程序员无法看明白)。

3)、维护、拓展性:比如有一个类,实现了某个功能,突然有一天,发现这个类满足不了需求了,然后又要重新设计这个类,更糟糕是你可能要放弃这个类,那么其他地方可能有引用他,这样修改起来很麻烦。

如果一开始定义一个接口,把功能放在接口里,然后定义类时实现这个接口,然后只要用这个接口去引用实现它的类就行了,以后要换的话只不过是引用另一个类而已,这样就达到维护、拓展的方便性。比如有个method1的方法,如果用接口,【接口名】 【对象名】=new 【实现接口的类】,这样想用哪个类的对象就可以new哪个对象了,new a();就是用a的方法,new b()就是用b的方法,就和USB接口一样,插什么读什么,就是这个原理。

你要做一个画板程序,其中里面有一个面板类,主要负责绘画功能,然后你就这样定义了这个类。

4)、安全、严密性:接口是实现软件松耦合的重要手段,它描叙了系统对外的所有服务,而不涉及任何具体的实现细节。这样就比较安全、严密一些(一般软件服务商考虑的比较多,jdk中很多方法就是实现了某个接口)。

2、抽象类的意义-(百度面试题) 

1),为子类提供一个公共的类型;

2),封装子类中重复内容(成员变量和方法);

3),定义有抽象方法,子类虽然有不同的实现,但该方法的定义是一致的

3、内部类的作用-(乐视面试题)

1).内部类可以很好的实现隐藏, 一般的非内部类,是不允许有 private 与protected权限的,但内部类可以

2).内部类拥有外围类的所有元素的访问权限

3).可以实现多重继承

4).可以避免修改接口而实现同一个类中两种同名方法的调用。

4、Java 虚拟机的特性-百度-(乐视面试题)

1)、移植性

无论是GC还是Hotspot都可以用在任何Java可用的地方。比方说,JRuby可以运行在其他平台上,Rails应用就可以运行在IBM主机上的JRuby上,而且这台IBM主机运行的是CP/CMS。实际上,由于Java和OpenJDK项目的开源,我们正在看到越来越多的平台的衍生,因此JVM的移植性也将越来越棒。

2)、成熟

JVM已有超过15年的历史,在过去的这些年里,许多开发者为它做出了许多贡献,使得它的性能一次又一次地提升,让JVM变得更加稳定、快速和广泛。

3)、覆盖面

JRuby和JVM上的其他语言项目已经被开发者所承认,一个典型的例子是invokedynamic specification (aka JSR292)。JSR越来越配合新的语言,JVM已不再是Java一个人定制规则。JVM正在构建成为类如JRuby等项目的优良平台。

5、哪些情况下的对象会被垃圾回收机制处理掉-(美团-小米面试题)

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

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

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

6、进程和线程的区别-(猎豹-美团面试题)

简而言之,一个程序至少有一个进程,一个进程至少有一个线程. 

线程的划分尺度小于进程,使得多线程程序的并发性高。

另外,进程在执行过程中拥有独立的内存单元,而多个线程共享内存,从而极大地提高了程序的运行效率。

线程在执行过程中与进程还是有区别的。每个独立的线程有一个程序运行的入口、顺序执行序列和程序的出口。但是线程不能够独立执行,必须依存在应用程序中,由应用程序提供多个线程执行控制。

从逻辑角度来看,多线程的意义在于一个应用程序中,有多个执行部分可以同时执行。但操作系统并没有将多个线程看做多个独立的应用,来实现进程的调度和管理以及资源分配。这就是进程和线程的重要区别。

进程是具有一定独立功能的程序关于某个数据集合上的一次运行活动,进程是系统进行资源分配和调度的一个独立单位.

线程是进程的一个实体,是CPU调度和分派的基本单位,它是比进程更小的能独立运行的基本单位.线程自己基本上不拥有系统资源,只拥有一点在运行中必不可少的资源(如程序计数器,一组寄存器和栈),但是它可与同属一个进程的其他的线程共享进程所拥有的全部资源.

一个线程可以创建和撤销另一个线程;同一个进程中的多个线程之间可以并发执行.

7、java中==和equals和hashCode的区别-(乐视面试题)

== :该操作符生成的是一个boolean结果,它计算的是操作数的值之间的关系

equals :Object 的 实例方法,比较两个对象的content是否相同

hashCode :Object 的 native方法 , 获取对象的哈希值,用于确定该对象在哈希表中的索引位置,它实际上是一个int型整数

equals方法是基类Object中的实例方法,因此对所有继承于Object的类都会有该方法

先比较引用是否相同(是否为同一对象),

再判断类型是否一致(是否为同一类型),

最后比较内容是否一致

8、HashMap的实现原理-(美团面试题)

1),先对table的非空检查,为空就初始化

2),对key的非空检查,如果key是null,会被存储到table[0],因为null的hash值总是0

3),对key的hashCode()做hash,然后再通过indexFor()计算index,这个就是table数组的索引;

4),如果在刚才计算出来的索引位置中table没有元素,直接把Entry对象放在那个索引上

5),如果索引上有元素,然后会进行迭代,在迭代的过程中,会调用equals()方法来检查key的相等性(key.equals(k)),如果这个方法返回true,它就会用当前Entry的value来替换之前的value。如果返回false就一直到Entry->next是null,把当前的Entry对象变成链表的下一个节点

6),如果table的长度超过了loadFactor *current capacity,就要重新resize一个原来长度两倍的HashMap

7),对key进行null检查。如果key是null,table[0]这个位置的元素将被返回。

8),key的hashcode()方法被调用,然后计算hash值。

9),indexFor(hash,table.length)用来计算要获取的Entry对象在table数组中的精确的位置,使用刚才计算的hash值。在获取了table数组的索引之后,会迭代链表,调用equals()方法检查key的相等性,如果equals()方法返回true,get方法返回Entry对象的value,否则,返回null。

10),HashMap中数据是用一个叫table的数组来存的,table的索引在逻辑上叫做“桶”(bucket),它存储了链表的第一个元素。

11),HashMap有一个叫做Entry的内部类,它用来存储key-value对。table数组存的就是它。Entry用一个next属性实现多个Entry以单向链表存放,插入元素时,如果两条Key落在同一个桶,并且这两条key不equals,后入桶的Entry将next指向桶当前的Entry,否则后入桶的会将前面的给覆盖(确保key的唯一性);

12),使用HashMap的时候最好使用泛型,如果key放的是自己的对象,最好重写equals()和hashcode()。

哈希表是一个数组+链表的存储结构。HashMap存储结构文字解释:

 table[0] →[index=1,Entry<K,V>] 

 table[1] →[index=2,Entry<K,V>]

  ...

 依次类推

9、string-stringbuffer-stringbuilder区别-(小米-乐视-百度面试题)

String 字符串常量

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

StringBuilder 字符串变量(非线程安全)

String 类型和 StringBuffer 类型的主要性能区别其实在于 String 是不可变的对象, 因此在每次对 String 类型进行改变的时候其实都等同于生成了一个新的 String 对象,然后将指针指向新的 String 对象,所以经常改变内容的字符串最好不要用 String ,因为每次生成对象都会对系统性能产生影响,特别当内存中无引用对象多了以后, JVM 的 GC 就会开始工作,那速度是一定会相当慢的

StringBuffer 类则结果就不一样了,每次结果都会对 StringBuffer 对象本身进行操作,而不是生成新的对象,再改变对象引用。所以在一般情况下我们推荐使用 StringBuffer ,特别是字符串对象经常改变的情况下。而在某些特别情况下, String 对象的字符串拼接其实是被 JVM 解释成了 StringBuffer 对象的拼接,所以这些时候 String 对象的速度并不会比 StringBuffer 对象慢,而特别是以下的字符串对象生成中, String 效率是远要比 StringBuffer 快的:

java.lang.StringBuilder一个可变的字符序列是5.0新增的。此类提供一个与 StringBuffer 兼容的 API,但不保证同步。该类被设计用作 StringBuffer 的一个简易替换,用在字符串缓冲区被单个线程使用的时候(这种情况很普遍)。如果可能,建议优先采用该类,因为在大多数实现中,它比 StringBuffer 要快。两者的方法基本相同

10、什么导致线程阻塞-58-美团

1)、线程执行了Thread.sleep(int n)方法,线程放弃CPU,睡眠n毫秒,然后恢复运行。

2)、线程要执行一段同步代码,由于无法获得相关的同步锁,只好进入阻塞状态,等到获得了同步锁,才能恢复运行。

3)、线程执行了一个对象的wait()方法,进入阻塞状态,只有等到其他线程执行了该对象的notify()或notifyAll()方法,才可能将其唤醒。

4)、线程执行I/O操作或进行远程通信时,会因为等待相关的资源而进入阻塞状态。例如,当线程执行System.in.read()方法时,如果用户没有向控制台输入数据,则该线程会一直等读到了用户的输入数据才从read()方法返回。进行远程通信时,在客户程序中,线程在以下情况可能进入阻塞状态。

5)、请求与服务器建立连接时,即当线程执行Socket的带参数的构造方法,或执行Socket的connect()方法时,会进入阻塞状态,直到连接成功,此线程才从Socket的构造方法或connect()方法返回。

6)、线程从Socket的输入流读取数据时,如果没有足够的数据,就会进入阻塞状态,直到读到了足够的数据,或者到达输入流的末尾,或者出现了异常,才从输入流的read()方法返回或异常中断。输入流中有多少数据才算足够呢?这要看线程执行的read()方法的类型。

int read(); 只要输入流中有一个字节,就算足够。

int read(byte[] buff); 只要输入流中的字节数目与参数buff数组的长度相同,就算足够。

String readLine(); 只要输入流中邮一行字符串,就算足够。值得注意的是,InputStream类并没有readLine方法,在过滤流BufferedReader类中才有此方法。

7)、线程向Socket的输出流写一批数据时,可能会进入阻塞状态,等到输出了所有的数据,或者出现异常,才从输出流的write()方法返回或异常中断。

8)、调用Socket的setSoLinger()方法设置了关闭Socket的延迟时间,那么当线程执行Socket的close方法时,会进入阻塞状态,直到底层Socket发送完所有剩余数据,或者超过了setSoLinger()方法设置的延迟时间,才从close()方法返回。

11、多线程同步机制-(猎豹面试题)

volatile和synchronized的区别

1)、volatile通过变量的可见性,指定线程必须从主存中读取变量的最新值;synchronized通过阻塞线程的方式,只有当前线程能访问该变量,锁定了当前变量。

2)、volatile使用在变量级别;synchronized可以使用在变量、方法、类级别

3)、volatile不会造成线程阻塞;synchronized可能会造成线程阻塞

4)、volatile不能保证原子性;synchronized能保证原子性

5)、volatile标记的变量不会被编译器优化;synchronized标记的变量有可能会被编译器优化(指令重排)

12、ArrayMap对比HashMap

如果hashmap和Arraymap在内存优化方面,肯定会选择ArrayMap,因为ArrayMap占用空间小,但是ArrayMap以时间换空间,速度也是慢了很多。

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

ArrayMap的存储中没有Entry这个东西,他是由两个数组来维护的,mHashes数组中保存的是每一项的HashCode值,mArray中就是键值对,每两个元素代表一个键值对,前面保存key,后面的保存value

添加数据时扩容时的处理不一样

HashMap 是创建一个新的容量是之前二倍的对象,然后将之前的数据移动到新的。

ArrayMap用的是copy数据,所以效率相对要高,ArrayMap提供了数组收缩的功能,在clear或remove后,会重新收缩数组,是否空间,

13、hashmap和hashtable的区别-(乐视-小米-360面试题)

HashMap 不是线程安全的

HashMap 是 map 接口的实现类,是将键映射到值的对象,其中键和值都是对象,并且不能包含重复键,但可以包含重复值。HashMap 允许 null key 和 null value,而 HashTable 不允许。

HashTable 是线程安全 Collection。

HashMap 是 HashTable 的轻量级实现,他们都完成了Map 接口,主要区别在于 HashMap 允许 null key 和 null value,由于非线程安全,效率上可能高于 Hashtable。

区别如下:

HashMap允许将 null 作为一个 entry 的 key 或者 value,而 Hashtable 不允许。

HashMap 把 Hashtable 的 contains 方法去掉了,改成 containsValue 和 containsKey。因为 contains 方法容易让人引起误解。

HashTable 继承自 Dictionary 类,而 HashMap 是 Java1.2 引进的 Map interface 的一个实现。

HashTable 的方法是 Synchronize 的,而 HashMap 不是,在多个线程访问 Hashtable 时,不需要自己为它的方法实现同步,而 HashMap 就必须为之提供外同步。

Hashtable 和 HashMap 采用的 hash/rehash 算法都大概一样,所以性能不会有很大的差异

■ ■■■■

Androi试题

16、如何导入外部数据库?

1). 把原数据库包括在项目源码的 res/raw 目录下,然后建立一个DBManager类

InputStream is = this.context.getResources().openRawResource(

                        R.raw.countries); //欲导入的数据库

                FileOutputStream fos = new FileOutputStream(dbfile);

                byte[] buffer = new byte[BUFFER_SIZE];

                int count = 0;

                while ((count = is.read(buffer)) > 0) {

                    fos.write(buffer, 0, count);

                }

                fos.close();

                is.close();

            }

            SQLiteDatabase db = SQLiteDatabase.openOrCreateDatabase(dbfile,

                    null);

17、本地广播和全局广播有什么差别?

1)、本地广播:发送的广播事件不被其他应用程序获取,也不能响应其他应用程序发送的广播事件。本地广播只能被动态注册,不能静态注册。动态注册或方法时需要用到LocalBroadcastManager。

2)、全局广播:发送的广播事件可被其他应用程序获取,也能响应其他应用程序发送的广播事件(可以通过 exported–是否监听其他应用程序发送的广播 在清单文件中控制) 全局广播既可以动态注册,也可以静态注册。

18、intentService作用是什么,AIDL解决了什么问题-(小米面试题)

1),生成一个默认的且与主线程互相独立的工作者线程来执行所有传送至onStartCommand() 方法的Intetnt。

2),生成一个工作队列来传送Intent对象给你的onHandleIntent()方法,同一时刻只传送一个Intent对象,这样一来,你就不必担心多线程的问题。在所有的请求(Intent)都被执行完以后会自动停止服务,所以,你不需要自己去调用stopSelf()方法来停止。

3),该服务提供了一个onBind()方法的默认实现,它返回null

4),提供了一个onStartCommand()方法的默认实现,它将Intent先传送至工作队列,然后从工作队列中每次取出一个传送至onHandleIntent()方法,在该方法中对Intent对相应的处理。

5),AIDL (Android Interface Definition Language) 是一种IDL 语言,用于生成可以在Android设备上两个进程之间进行进程间通信(interprocess communication, IPC)的代码。如果在一个进程中(例如Activity)要调用另一个进程中(例如Service)对象的操作,就可以使用AIDL生成可序列化的参数。AIDL IPC机制是面向接口的,像COM或Corba一样,但是更加轻量级。它是使用代理类在客户端和实现端传递数据。

19、Ubuntu编译安卓系统-(百度面试题)

https://mp.weixin.qq.com/s/a6q2YBlW_H6YaaENWgtcTw

20、LaunchMode应用场景-百度-(小米-乐视面试题)

1),standard 模式

这是默认模式,每次激活Activity时都会创建Activity实例,并放入任务栈中。使用场景:大多数Activity。

2),singleTop 模式

如果在任务的栈顶正好存在该Activity的实例,就重用该实例( 会调用实例的>

3),singleTask 模式

如果在栈中已经有该Activity的实例,就重用该实例(会调用实例的>

4),singleInstance 模式

在一个新栈中创建该Activity的实例,并让多个应用共享该栈中的该Activity实例。一旦该模式的Activity实例已经存在于某个栈中,任何应用再激活该Activity时都会重用该栈中的实例( 会调用实例的>

21、Touch事件传递流程-(小米面试题)

分发(dispatchTouchEvent):方法返回值为true表示事件被当前视图消费掉;返回为super.dispatchTouchEvent表示继续分发该事件。

拦截(onInterceptTouchEvent):方法返回值为true表示拦截这个事件并交由自身的onTouchEvent方法进行消费;返回false表示不拦截,需要继续传递给子视图。

如果return super.onInterceptTouchEvent(ev), 事件拦截分两种情况:  

1).如果该View(ViewGroup)存在子View且点击到了该子View, 则不拦截, 继续分发

给子View 处理, 此时相当于return false。

2).如果该View(ViewGroup)没有子View或者有子View但是没有点击中子View(此时ViewGroup

相当于普通View), 则交由该View的onTouchEvent响应,此时相当于return true。 

注意:一般的LinearLayout、 RelativeLayout、FrameLayout等ViewGroup默认不拦截, 而

ScrollView、ListView等ViewGroup则可能拦截,得看具体情况。

消费(onTouchEvent):方法返回值为true表示当前视图可以处理对应的事件;返回值为false表示当前视图不处理这个事件,它会被传递给父视图的onTouchEvent方法进行处理。如果return super.onTouchEvent(ev),事件处理分为两种情况:

3).如果该View是clickable或者longclickable的,则会返回true, 表示消费

了该事件, 与返回true一样;

4).如果该View不是clickable或者longclickable的,则会返回false, 表示不

消费该事件,将会向上传递,与返回false一样.

注意:在Android系统中,拥有事件传递处理能力的类有以下三种。

Activity:拥有分发和消费两个方法。

ViewGroup:拥有分发、拦截和消费三个方法。

View:拥有分发、消费两个方法。

22、View绘制流程-(百度面试题)

Measured

layout

23、多线程-(360面试题)

编写的代码则是穿插在这些逻辑中间,比如对用户触摸事件的检测和响应,对用户输入的处理,自定义View的绘制等。如果我们插入的代码比价耗时,如网络请求或数据库读取,就会阻塞UI线程其他逻辑的执行,从而导致界面卡顿。如果卡顿时间超过5秒,系统就会报ANR错误。所以,如果要执行耗时的操作,我们需要另起线程执行。

在新线程执行完耗时的逻辑后,往往需要将结果反馈给界面,进行UI更新。Android的UI toolkit不是线程安全的,不能在非UI线程进行UI的更新,所有对界面的更新必须在UI线程进行。

Android提供了四种常用的操作多线程的方式,分别是:

1). Handler+Thread

2). AsyncTask

3). ThreadPoolExecutor

4). IntentService

24、Handler,Thread和HandlerThread的差别-(小米面试题)

①Handler:在android中负责发送和处理消息,通过它可以实现其他支线线程与主线程之间的消息通讯。

②Thread:Java进程中执行运算的最小单位,亦即执行处理机调度的基本单位。某一进程中一路单独运行的程序。

③HandlerThread:一个继承自Thread的类HandlerThread,Android中没有对Java中的Thread进行任何封装,而是提供了一个继承自Thread的类HandlerThread类,这个类对Java的Thread做了很多便利的封装。

25、线程同步-(百度面试题)

1),synchronized关键字修饰的方法。 

由于java的每个对象都有一个内置锁,当用此关键字修饰方法时, 

内置锁会保护整个方法。在调用该方法前,需要获得内置锁,否则就处于阻塞状态

2),使用特殊域变量(volatile)实现线程同步

    a.volatile关键字为域变量的访问提供了一种免锁机制, 

    b.使用volatile修饰域相当于告诉虚拟机该域可能会被其他线程更新, 

    c.因此每次使用该域就要重新计算,而不是使用寄存器中的值 

    d.volatile不会提供任何原子操作,它也不能用来修饰final类型的变量使用重入锁实现线程同步

3), ReentrantLock类是可重入、互斥、实现了Lock接口的锁, 

    它与使用synchronized方法和快具有相同的基本行为和语义,并且扩展了其能力

ReenreantLock类的常用方法有:

ReentrantLock() : 创建一个ReentrantLock实例 

        lock() : 获得锁 

        unlock() : 释放锁 

注:ReentrantLock()还有一个可以创建公平锁的构造方法,但由于能大幅度降低程序运行效率,不推荐使用 

4),ThreadLocal() : 创建一个线程本地变量 

    get() : 返回此线程局部变量的当前线程副本中的值 

    initialValue() : 返回此线程局部变量的当前线程的"初始值" 

    set(T value) : 将此线程局部变量的当前线程副本中的值设置为value    

5),LinkedBlockingQueue 类常用方法 

 LinkedBlockingQueue() : 创建一个容量为Integer.MAX_VALUE的LinkedBlockingQueue 

    put(E e) : 在队尾添加一个元素,如果队列满则阻塞 

    size() : 返回队列中的元素个数 

    take() : 移除并返回队头元素,如果队列空则阻塞 

26、什么情况导致内存泄漏-(美团面试题)

1). 资源释放问题

程序代码的问题,长期保持某些资源,如 Context、Cursor、IO 流的引用,资源得不到释放 造成内存泄露。

2). 对象内存过大问题

保存了多个耗用内存过大的对象(如 Bitmap、XML 文件),造成内存超出限制。

3). static关键字的使用问题

static 是 Java 中的一个关键字,当用它来修饰成员变量时,那么该变量就属于该类,而不是 该类的实例。所以用 static 修饰的变量,它的生命周期是很长的,如果用它来引用一些资源耗费 过多的实例(Context 的情况最多),这时就要谨慎对待了。

public class ClassName { 

    private static Context mContext; 

    //省略 

以上的代码是很危险的,如果将 Activity 赋值到 mContext 的话。那么即使该 Activity 已经>

我们举 Android 文档中的一个例子。

private static Drawable sBackground; 

@Override

protected void>

    super.onCreate(state); 

    TextView label = new TextView(this); 

    //getApplicationContext         

    if (sBackground == null) { 

        sBackground = getDrawable(R.drawable.large_bitmap);

    }

    label.setBackgroundDrawable(sBackground);

    setContentView(label);

sBackground 是一个静态的变量,但是我们发现,我们并没有显式的保存 Contex 的引用, 但是,当 Drawable 与 View 连接之后,Drawable 就将 View 设置为一个回调,由于 View 中是 包含 Context 的引用的,所以,实际上我们依然保存了 Context 的引用。这个引用链如下: 

Drawable->TextView-> Context 

所以,最终该 Context 也没有得到释放,发生了内存泄露。

针对 static 的解决方案 

 1) 应该尽量避免 static 成员变量引用资源耗费过多的实例,比如 Context。 

 2) Context尽量使用ApplicationContext,因为Application的Context的生命周期比较长,引用它不会出现内存泄露的问题。 

3) 使 用 WeakReference 代 替 强 引 用 。比 如 可 以 使 用 WeakReference mContextRef;

27. 线程导致内存溢出

线程产生内存泄露的主要原因在于线程生命周期的不可控。我们来考虑下面一段代码。

public class MyActivity extends Activity { 

    @Override 

    public void>

        super.onCreate(savedInstanceState);     

        setContentView(R.layout.main);  

        new MyThread().start();              

    } 

    private class MyThread extends Thread{ 

        @Override 

        public void run() { 

            super.run(); 

            //do somthing while(true) 

        } 

    } 

这段代码很平常也很简单,是我们经常使用的形式。我们思考一个问题:假设 MyThread 的 run 函数是一个很费时的操作,当我们开启该线程后,将设备的横屏变为了竖屏,一 般情况下当屏幕转 换时会重新创建 Activity,按照我们的想法,老的 Activity 应该会被销毁才对,然而事实上并非如此。 

由于我们的线程是 Activity 的内部类,所以 MyThread 中保存了 Activity 的一个引用,当 MyThread 的 run 函数没有结束时,MyThread 是不会被销毁的,因此它所引用的老的 Activity 也 不会被销毁,因此就出现了内存泄露的问题。 

有些人喜欢用 Android 提供的 AsyncTask,但事实上 AsyncTask 的问题更加严重,Thread 只有 在 run 函数不结束时才出现这种内存泄露问题,然而 AsyncTask 内部的实现机制是运用了 ThreadPoolExcutor,该类产生的 Thread 对象的生命周期是不确定的,是应用程序无法控制的,因此 如果 AsyncTask 作为 Activity 的内部类,就更容易出现内存泄露的问题。

针对这种线程导致的内存泄露问题的解决方案: 

(一) 将线程的内部类,改为静态内部类(因为非静态内部类拥有外部类对象的强引用,而静 态类则不拥有)。 

(二) 在线程内部采用弱引用保存 Context 引用

28,跨平台主要使用哪些方式
Cordova
Cordova通过对HTML、CSS、JS封装为原生APP。Cordova将不同设备的功能,按标准进行了统一封装,开发人员不需要了解设备的原生实现细节,并且提供了一组统一的JavaScript类库,以及为这些类库所使用的设备相关的原生后台代码。因此实现了“write>React Native
React Native支持标准平台组件使用,在iOS平台我们可以使用UITaBar控件,在Android平台我们可以使用rawer控件。这样App从使用上和视觉上拥有像原生App一样的体验

Flutter
Flutter是面向iOS和Android应用,提供一套基础代码(使用Dart语言)的高性能高可靠软件开发工具包,使开发者能够在iOS和Android两个主要的移动平台上,打造统一代码的高性能应用。
Flutter能够在iOS和Android上运行起来,依靠的是一个叫Flutter Engine的虚拟机,Flutter Engine是Flutter应用程序的运行环境,开发人员可以通过Flutter框架和API在内部进行交互

29,项目中的保活是怎么做到的
1),前台服务,startForeground

2),双进程保活

3),使用WakefulBroadcastReceiver,WakefulBroadcastReceiver是BroadcastReceiver的一种特例。它会为你的APP创建和管理一个PARTIAL_WAKE_LOCK 类型的WakeLock。WakefulBroadcastReceiver把工作交接给service(通常是IntentService),并保证交接过程中设备不会进入休眠状态。如果不持有WakeLock,设备很容易在任务未执行完前休眠。最终结果是你的应用不知道会在什么时候能把工作完成;

4),JobService

5),开启自启动权限及允许后台允许 针对不同的机型做不同的处理,小米是神隐模式 华为锁屏清理应用等等

30,笔试,两个int 分别是a,b 不使用临时变量的情况下 如何交换a,b的值
1),#python下,只要下面两行
a = 1,b = 2
a , b = b , a

2),通用的方法

int a = 1, b=2;
a = a+b;
b = a-b;
a = a-b;

int a=2=010(二进制);
int b=4=100(二进制);
异或运算如下:
a=ab=010100=110(此时,a的值改变为二进制的110)
b=ab=110100=010(此时,b的值改变为二进制的010,即十进制的2)
a=ab=110010=100(此时,a的值改变为二进制的100,即十进制的4)

31,activity转换屏幕的生命周期
1),运行Activity,得到如下信息

onCreate-->
onStart-->
onResume-->

2)、按crtl+f12切换成横屏时
onSaveInstanceState-->
onPause-->
onStop-->
onDestroy-->
onCreate-->
onStart-->
onRestoreInstanceState-->
onResume-->

3),再次切换竖屏
onSaveInstanceState-->
onPause-->
onStop-->
onDestroy-->
onCreate-->
onStart-->
onRestoreInstanceState-->
onResume-->
onSaveInstanceState-->
onPause-->
onStop-->
onDestroy-->
onCreate-->
onStart-->
onRestoreInstanceState-->
onResume-->

32,launcher的属性,和普通APP的区别
launcher和APP区别:
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.HOME" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.MONKEY" />
</intent-filter>


33,tcp/ip的理解 每一层是否了解,知道数据抓包吗?Tcp/ip和udp的区别是什么?
物理层
数据链路层
传输层
网络层
会话层
表示层
应用层

34,为什么要内部类,你是在什么情况用到?
1).一个内部类的对象能够访问创建它的对象的实现,包括私有数据。
2). 对于同一个包中的其他类来说,内部类能够隐藏起来。
3).匿名内部类可以很方便的定义回调。
4).使用内部类可以非常方便的编写事件驱动程序
5).一个内部类对象可以访问创建它的外部类对象的内容,甚至包括私有变量

匿名内部类的

public class JavaTest2 {
public static void main(String[] args) {
new Person() {
public void say() {// 匿名内部类自定义的方法say
System.out.println("say方法调用");
} @Override
        public void speak() {// 实现接口的的方法speak
            System.out.println("speak方法调用");
        }
    }.say();// 直接调用匿名内部类的方法
}
interface Person {
public void speak();
}}

35,字符串转int,int转字符串
String s = String.valueOf( value); // 其中 value 为任意一种数字类型。

String s = "test";
byte b = Byte.parseByte( s );
short t = Short.parseShort( s );
int i = Integer.parseInt( s );
long l = Long.parseLong( s );
Float f = Float.parseFloat( s );
Double d = Double.parseDouble( s );

■ ■■■■

上补习

其实我们需要拿到大厂的offer远不止这些呢,真正拿到offer需要不断的积累,掌握原理及底层的实现方式,这样才能回答上面试官想要的结果。

毕竟学好知识,掌握技能才是你现在最主要的任务啊~

分享一波技术视频和面试宝典,让大家都能拿到心仪的offer和薪资!!!

链接:

https://pan.baidu.com/s/1FYIagjmQPK8JRySq96pHog 

提取码:juyx

点击更多视频

■ ■■■■

  end 

Android /关注公众号:QXF069

微信865618770

长按二维码关注我们吧

点击文末推荐

不要错过

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

码农乐园

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值