Android每天10道面试题02
- 介绍:
- Java部分
- 1.Java中jvm,jre,jdk的区别?
- 2.Java面向对象的特征以及讲讲你代码中凸显这些特征的经验?
- 3.抽象类和接口的区别?
- 4.静态属性和静态方法是否可以被继承?是否可以被重写?以及原因?
- 5.try{}catch{}finally{}可以没有finally吗?
- Android部分
- 6.Handler的消息机制及其原理?
- 7.Handler中looper死循环为什么不导致应用卡死?
- 8.Handler导致的内存泄露你是如何解决的?
- 计算机网络
- 9.http和https的区别?
- 算法
- 10.统计一个数字在排序数组中出现的次数
介绍:
10道面试题=5 java + 3 Android + 1(计网+数据结构+操作系统选择式)+ 1 算法题
主要以我自己的回答方式总结,小伙伴们欢迎指教奥~
Java部分
1.Java中jvm,jre,jdk的区别?
jvm:java虚拟机,顾名思义——虚拟的机器 虚拟机,之所以称为虚拟机,是因为他实际上不存在,他是一个规范,提供一个java字节码可以运行的环境,它也可以运行其它语言编写的编译成java字节码的程序 jre,jdk,jvm依赖于平台~因为每个操作系统的配置彼此不相同,但是java语言是跨平台的。 jvm有三个概念:规范,实现,实例。
jvm的实现被称作jre 当你运行一个java类的时候,一个jvm的实例就被创建了。
jre:java运行时环境,顾名思义——运行时的环境 jvm是虚拟机,而jre就是他的实现 它是用于开发java应用程序的一组软件工具,这组软件工具用于提供运行时的环境,它是jvm(java虚拟机的实现),它实际上存在,它包含jvm运行时使用的一些实际存在的库和文件。
JDK:java开发工具包,顾名思义——开发工具包 JDK不仅能够实现JVM实际运行时所需要的软件库和文件还包含开发工具等,所以JDK也是一个软件开发环境,他实际上存在,它包含JVM+jre+开发工具!
Jdk>jre>jvm
2.Java面向对象的特征以及讲讲你代码中凸显这些特征的经验?
java面向对象的三大特征是 封装,继承,和 多态
封装是保证软件部件具有优良的模块性的基础,封装的目标就是要实现软件部件的“高内聚、低耦合”,防止程序相互依赖性而带来的 变动影响。在面向对象的编程语言中,对象是封装的最基本单位,面向对象的封装比传统语言的封装更为清晰、更为有力。
面向对象的封装就 是把描述一个对象的属性和行为的代码封装在一个类中,属性用变量定义,行为用方法进行定义,方法可以直接访问同 一个对象中的属性。把握一个原则:把对同一事物进行操作的方法和相关的方法放在同一个类中,把方法和它操作的数据放在同一个类中。
继承是在定义和实现一个类的时候,可以在一个已经存在的类的基础之上来进行,把这个已经存在的类所定义的内容作为自己的内容,并可以加入 若干新的内容,或修改原来的方法使之更适合特殊的需要,这就是继承。继承是子类自动共享父类数据和方法的机制,这是类之间的一种关 系,提高了软件的可重用性和可扩展性。
多态是指程序中定义的引用变量所指向的具体类型和通过该引用变量发出的方法调用在编程时并不确定,而是在程序运行期间才确定,即 一个引用变量倒底会指向哪个类的实例对象,该引用变量发出的方法调用到底是哪个类中实现的方法,必须在由程序运行期间才能决定。 因为在程序运行时才确定具体的类,这样,不用修改源程序代码,就可以让引用变量绑定到各种不同的类实现上,从而导致该引用调用的 具体方法随之改变,即不修改程序代码就可以改变程序运行时所绑定的具体代码,让程序可以选择多个运行状态,这就是多态性。多态性 增强了软件的灵活性和扩展性。
多态的实现:
继承在为多态的实现做了准备。子类Child继承父类Father,我们可以编写一个指向子类的父类类型引用,该引用既 可以处理父类Father对象,也可以处理子类Child对象,当相同的消息发送给子类或者父类对象时,该对象就会根据自己所属的引用而执行 不同的行为,这就是多态。即多态性就是相同的消息使得不同的类做出不同的响。
Java实现多态有三个必要条件:继承、重写、向上转型。
继承:在多态中必须存在有继承关系的子类和父类。 重写:子类对父类中某些方法进行重新定义,在调用这些方法时就会调用子类的方法。 向上转型:在多态中需要将子类的引用赋给父类对象,只有这样该引用才能够具备技能调用父类的方法和子类的方法。
实现形式:继承和接口
基于继承的实现机制主要表现在父类和继承该父类的一个或多个子类对某些方法的重写,多个子类对同一方法的重写可以表现出不同的行为。 继承都是单继承,只能为一组相关的类提供一致的服务接口。但是接口可以是多继承多实现,它能够利用一组相关或者不相关的接口进行组合与扩充, 能够对外提供一致的服务接口。所以它相对于继承来说有更好的灵活性。
抽象:
抽象就是找出一些事物的相似和共性之处,然后将这些事物归为一个类,这个类只考虑这些事物的相似和共性之处,并且会忽略与当前主 题和目标无关的那些方面,将注意力集中在与当前目标有关的方面。例如,看到一只蚂蚁和大象,你能够想象出它们的相同之处,那就是抽 象。抽象包括行为抽象和状态抽象两个方面。例如,定义一个Person类,定义他们的共有的一些属性,name\age\sex等等
3.抽象类和接口的区别?
1.默认的实现方法:
(1)抽象类可以有默认的方法实现完全是抽象的。
抽象类中可以有已经实现了的方法,也可以有被abstract修饰的方法(抽象方法),因为存在抽象方法,所以该类必须是抽象类。
(2)接口根本不存在方法的实现。
但是接口要求只能包含抽象方法,抽象方法是指没有实现的方法。接口就根本不能存在方法的实现。
2.子类使用的关键词不一样:
(1)实现抽象类使用extends关键字来继承抽象类。如果子类不是抽象类的话,它需要提供抽象类中所有声明的方法的实现。
抽象类虽然不能实例化来使用,但是可以被继承,让子类来具体实现父类的所有抽象方法。但是如果子类将抽象方法没有全部实现,就必须把自己也修饰成抽象类,交于继承它的子类来完成实现。以此类推,直到没有抽象函数。
(2)子类使用关键字implements来实现接口。它需要提供接口中所有声明的方法的实现。
接口的实现,通过implements关键字。实现该接口的类,必须把接口中的所有方法给实现。不能再推给下一代。(和抽象类相比,抽象类是将梦想传给家族,一代一代去完成。那么接口就是掌门人找大师兄来完成帮派的鸿星伟业,这时候就只有一次希望,要么有能力就实现,没能力就不要接。
3.是否有构造器:
(1)抽象类可以有构造器
抽象类是属于类,享有类的所有特性(但是不能实例化),当然包括类的构造方法,也就是构造器。
(2)接口不能有构造器
接口是所有抽象方法的集合,注意,是集合,不是类。当然没有构造方法一说,更别提什么构造器了。
4.可使用的修饰符:
(1)抽象方法可以有public、protected和default这些修饰符
抽象类的目的就是被继承,抽象方法就是为了被重写,所以肯定不能用private修饰符,肯定是可以用public的。但是protected和default也是可以的。
(2)接口方法默认修饰符是public。你不可以使用其它修饰符。
接口就有且只有一个public修饰。(感觉抽象类像小儿子各种耍无赖,接口就像私生子,说什么只能是什么
5.速度方面:
(1)抽象方法比接口速度要快
(2)接口是稍微有点慢的,因为它需要时间去寻找在类中实现的方法。
6.增加新方法对子类的影响:
(1)如果你往抽象类中添加新的方法,你可以给它提供默认的实现。因此你不需要改变你现在的代码。
抽象类可以有一些非抽象方法的存在,这些方法被称为默认实现。如果添加一个默认实现方法(不能是抽象方法),就不需要在子类中去实现,所以继承这个抽象类的子类无须改动。如果你往接口中添加方法,那么你必须改变实现该接口的类。
(2)接口中只能添加抽象方法,当你添加了抽象方法,实现该接口的类就必须实现这个新添加的方法。
因为,定义中说的很清楚,接口的实现必须实现所有的方法。所有,当然包括新添加的方法。
7.子类能继承的数量:
抽象类在java语言中所表示的是一种继承关系,一个子类只能存在一个父类,但是可以存在多个接口。
java在类的继承上并没有多继承。抽象类属于类,所以可以被继承。但子类只能继承一个父类。
java为了实现多继承,使用了接口。一个类可以实现多个接口。继承就好比生了孩子,只能有一个爹,但是这个孩子可以学语文,学数学,学英语等等很多东西,而语文、数学、英语就相当于接口。
抽象类和接口区别
4.静态属性和静态方法是否可以被继承?是否可以被重写?以及原因?
首先静态属性和静态方法是可以被子类继承的,但静态属性不能被子类重写。
重写的本质是动态绑定,即根据运行时对象的类型来决定调用哪个方法,而不是根据编译时的类型。静态方法属于类的,在编译阶段已经静态绑定到类上,表现出来就是通过类名.方法名进行访问;所以静态方法无法被子类重写。
5.try{}catch{}finally{}可以没有finally吗?
try { //执行的代码,其中可能有异常。一旦发现异常,则立即跳到catch执行。否则不会执行catch里面的内容 }
catch { //除非try里面执行代码发生了异常,否则这里的代码不会执行 }
finally { //不管什么情况都会执行,包括try catch 里面用了return ,可以理解为只要执行了try或者catch,就一定会执行 finally }
正常情况下,先执行try里面的代码,捕获到异常后执行catch中的代码,最后执行finally中代码,但当在try catch中执行到return时,要判断finally中的代码是否执行,如果没有,应先执行finally中代码再返回。
return在try catch finally中的执行顺序(最通俗易懂的总结)
Android部分
6.Handler的消息机制及其原理?
首先在UI线程我们创建了一个Handler实例对象,无论是匿名内部类还是自定义类生成的Handler实例对象,我们都需要对handleMessage方法进行重写,在handleMessage方法中我们可以通过参数msg来写接受消息过后UIi线程的逻辑处理,接着我们创建子线程,在子线程中需要更新UI的时候,新建一个Message对象,并且将消息的数据记录在这个消息对象Message的内部,比如arg1,arg2,obj等,然后通过前面的Handler实例对象调用sendMessge方法把这个Message实例对象发送出去,之后这个消息会被存放于MessageQueue中等待被处理,此时MessageQueue的管家Looper正在不停的把MessageQueue存在的消息取出来,通过回调dispatchMessage方法将消息传递给Handler的handleMessage方法,最终前面提到的消息会被Looper从MessageQueue中取出来传递给handleMessage方法,最终得到处理。这就是Handler机制整个的工作流程。
Handler的理解、用法以及运行机制原理
7.Handler中looper死循环为什么不导致应用卡死?
loop无限循环用于取出消息并将消息分发出去,没有消息时会阻塞在queue.next()里的nativePollOnce()方法里,并释放CPU资源进入休眠。Android的绝大部分操作都是通过Handler机制来完成的,如果没有消息,则不需要程序去响应,就不会有ANR。ANR一般是消息的处理过程中耗时太长导致没有及时响应用户操作。
Looper死循环为什么不会导致应用卡死?Handler.postDelayed()的原理
8.Handler导致的内存泄露你是如何解决的?
引起内存泄漏的原因:
handler发送的消息在当前handler的消息队列中,如果此时activity finish掉了,那么消息队列的消息依旧会由handler进行处理,若此时handler声明为内部类(非静态内部类),我们知道内部类天然持有外部类的实例引用,那么就会导致activity无法回收,进而导致activity泄露。
解决方法
handler定义为static,因为静态内部类不持有外部类的引用,所以使用静态的handler不会导致activity的泄露
handler要定义为static的同时,还要用WeakReference 包裹外部类的对象
这是因为我们需要使用外部类的成员,可以通过"activity. "获取变量方法等,如果直接使用强引用,显然会导致activity泄露。
总结:
避免handler内存泄露的办法
- 1.使用static 修饰的handler,但是一般会弱引用activity对象,因为要使用activity对象中的成员
- 2.单独定义handler,同样可以弱引用activity
- 3.使用内部类的handler,在onDestroy方法中removeCallbacksAndMessages
第一种方法代码
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_handleroom);
findViewById(R.id.btn_send).setOnClickListener(this);
tv = findViewById(R.id.tv);
// 延时5min发送一个消息,此时handler是持有activity引用的
// mHandler.sendEmptyMessageDelayed(1, 5 * 60 * 1000);
handler.sendEmptyMessageDelayed(0, 5 * 60 * 1000);
}
/**
* 避免handler内存泄露的写法
* handler为何会导致内存泄露:
* 如果handler为内部类(非静态内部类),那么会持有外部类的实例,
* 若在handler.sendMessage的时候,activity finish掉了,那么此时activity将无法得到释放
* <p>
* 如果申明handler为静态内部类,则不会含有外部类的引用,
* 但是需要在handler中更新UI(注意此时handler为static),则需要引入一个activity引用,
* 显然必须是弱引用,否则会导致和上面一样的结果
* <p>
* 使用activity弱引用
* 之所以使用弱引用,是因为handler为static,使用activity的弱引用来访问activity对象内的成员
*/
private static class MyHandler extends Handler {
private WeakReference<HandlerOOMActivity> weakReference;
// private HandlerOOMActivity activity;
public MyHandler(HandlerOOMActivity activity) {
weakReference = new WeakReference<>(activity);
// this.activity = activity;
}
@Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
Log.e(TAG, "handleMessage: ");
// HandlerOOMActivity activity = weakReference.get();
switch (msg.what) {
case 0:
// if (activity != null) {
// activity.tv.setText("我是更改后的文字");
// }
// activity.tv.setText("我是更改后的文字");
break;
}
}
}
计算机网络
9.http和https的区别?
HTTPS和HTTP的区别主要如下:
1、https协议需要到ca申请证书,一般免费证书较少,因而需要一定费用。
2、http是超文本传输协议,信息是明文传输,https则是具有安全性的ssl加密传输协议。
3、http和https使用的是完全不同的连接方式,用的端口也不一样,前者是80,后者是443。
4、http的连接很简单,是无状态的;HTTPS协议是由SSL+HTTP协议构建的可进行加密传输、身份认证的网络协议,比http协议安全。
http和https的加密方式
算法
10.统计一个数字在排序数组中出现的次数
统计一个数字在排序数组中出现的次数
“面朝大海,春暖花开”