网站首页 > 技术文章 正文
码仔,今天就给大家带来了《每日一道面试题》的第六期:
01
ART和Dalvik区别
什么是Dalvik: Dalvik是Google公司自己设计用于Android平台的Java虚拟机。 它可以支持已转换为.dex(即Dalvik Executable)格式的Java应用程序的运行。 .dex格式是专为Dalvik应用设计的一种压缩格式,适合内存和处理器速度有限的系统。 Dalvik经过优化,允许在有限的内存中同时运行多个虚拟机的实例,并且每一个Dalvik应用作为独立的Linux进程执行。 独立的进程可以防止在虚拟机崩溃的时候所有程序都被关闭。
什么是ART: 与Dalvik不同,ART使用预编译(AOT,Ahead-Of-Time)。 也就是在APK运行之前,就对其包含的Dex字节码进行翻译,得到对应的本地机器指令,于是就可以在运行时直接执行了。 ART应用安装的时候把dex中的字节码将被编译成本地机器码,之后每次打开应用,执行的都是本地机器码。 去除了运行时的解释执行,效率更高,启动更快。
区别:
Dalvik每次都要编译再运行,Art只会首次启动编译
Art占用空间比Dalvik大(原生代码占用的存储空间更大),就是用“空间换时间”
Art减少编译,减少了CPU使用频率,使用明显改善电池续航
Art应用启动更快、运行更快、体验更流畅、触感反馈更及时
02
简单算法题
解题思路分析: 1、n=0 和 n=1 的时候 并没有其他可选择的,所以可以得出f(0)=0;f(1)=1; 2、n>=2时情况就变复杂起来,但是这个时候可以操作的步骤也就2种 也就是走1步(n-1)与走2步(n-2)。所以可以得到f(n)=f(n-1)+f(n-2); 从当前状态转为下一状态的通用算法既可。 3、 验证,使用2以上的数字验证几次。
答案: 1.递归
public static int f(int n){
if(n<=2) return n;
int x = f(n-1) + f(n-2);
return x;
}
2.迭代
public static int f(int n){
if(n<=2) return n;
if first=1,second=2;
int third=0;
for(int i=3;i<=n;i++){
third = first+second;
first = second;
second = third;
}
return third;
}
3.动态规划
public static int A = new int[100];
public static int f(int n){
if(n<=2){
A[n] = n;
}
if(A[n]>0){
return A[n];
} else {
A[n] = f(n-1)+f(n-2);
return A[n];
}
}
03
谈谈JDK8开始的双冒号::用法及详解
概念
类名::方法名,相当于对这个方法闭包的引用,类似 js 中的一个 function。比如:
Function<String,String> func = String::toUpperCase;
Function 在 java.util.function 包下,也是 jdk8 新加入的类,同级目录下有很多函数式编程模型接口,比如 Consumer/Predicate/Operator 等,func 相当于一个入参和出参都为 String 的函数,可以直接如下:
func.apply("abc")
接收一个参数,返回一个结果("ABC")。也可以用于代替下面的 Lambda 表达式:
List<String> l = Arrays.asList("a","b","c");
l.stream.map(s -> s.toUpperCase);
l.stream.map(func);
下面自定义一个函数式接口:
public class MyConsumer<String> implements Consumer<String> {
@Override
public void accept(String s) {
System.out.println(s);
}
}
下面这俩种写法等价:
List<String> l = Arrays.asList("a","b","c");
l.forEach(new MyConsumer<>);
l.forEach(s -> System.out.println(s));
但是,这种写法却不行,编译失败:
l.forEach(MyConsumer::accept);
因为 MyConsumer 的 accept 方法不是静态的,如果想使用这个方法,需要一个实例,还需要一个入参,共俩个参数。而 List.forEach 中需要的是 consumer 类型,相当于 s -> {...},只有一个参数。
下面详细分析双冒号使用的各种情况
新建一个类,里面声明四个代表各种情况的方法:
public class DoubleColon {
public static void printStr(String str) {
System.out.println("printStr : " + str);
}
public void toUpper{
System.out.println("toUpper : " + this.toString);
}
public void toLower(String str){
System.out.println("toLower : " + str);
}
public int toInt(String str){
System.out.println("toInt : " + str);
return 1;
}
}
把它们用::提取为函数,再使用:
Consumer<String> printStrConsumer = DoubleColon::printStr;
printStrConsumer.accept("printStrConsumer");
Consumer<DoubleColon> toUpperConsumer = DoubleColon::toUpper;
toUpperConsumer.accept(new DoubleColon);
BiConsumer<DoubleColon,String> toLowerConsumer = DoubleColon::toLower;
toLowerConsumer.accept(new DoubleColon,"toLowerConsumer");
BiFunction<DoubleColon,String,Integer> toIntFunction = DoubleColon::toInt;
int i = toIntFunction.apply(new DoubleColon,"toInt");
非静态方法的第一个参数为被调用的对象,后面是入参。静态方法因为 jvm 已有对象,直接接收入参。再写一个方法使用提取出来的函数:
public class TestBiConsumer {
public void test(BiConsumer<DoubleColon,String> consumer){
System.out.println("do something ...");
}
}
下面这俩种传入的函数是一样的:
TestBiConsumer obj = new TestBiConsumer;
obj.test((x,y) -> System.out.println("do something ..."));
obj.test(DoubleColon::toLower);
总结
用::提取的函数,最主要的区别在于静态与非静态方法,非静态方法比静态方法多一个参数,就是被调用的实例。
04
Android平台的优势和不足
Android平台手机 5大优势:
1、开放性:Android平台首先就是其开放性,开发的平台允许任何移动终端厂商加入到Android联盟中来。显著的开放性可以使其拥有更多的开发者;
2、挣脱运营商的束缚:在过去很长的一段时间,手机应用往往受到运营商制约,使用什么功能接入什么网络,几乎都受到运营商的控制,而Android用户可以更加方便地连接网络,运营商的制约减少;
3、丰富的硬件选择:由于Android的开放性,众多的厂商会推出千奇百怪,功能特色各具的多种产品。功能上的差异和特色,却不会影响到数据同步、甚至软件的兼容;
4、开发商不受任何限制:Android平台提供给第三方开发商一个十分宽泛、自由的环境,不会受到各种条条框框的阻扰;
5、无缝结合的Google应用: Android平台手机将无缝结合这些优秀的Google服务如地图、邮件、搜索等;
Android平台手机几大不足:
1、安全和隐私:由于手机与互联网的紧密联系,个人隐私很难得到保守。除了上网过程中经意或不经意留下的个人足迹,Google这个巨人也时时站在你的身后,洞穿一切;
2、过分依赖开发商缺少标准配置:在Android平台中,由于其开放性,软件更多依赖第三方厂商,比如Android系统的SDK中就没有内置音乐播放器,全部依赖第三方开发,缺少了产品的统一性;
3、同类机型用户很少:在不少手机论坛都会有针对某一型号的子论坛,对一款手机的使用心得交流,并分享软件资源。而对于Android平台手机,由于厂商丰富,产品类型多样,这样使用同一款机型的用户越来越少,缺少统一机型的程序强化。
05
谈谈Static关键字的用法
Static 修饰的方法/变量等资源是静态资源 在内存中存放在方法区,所有允许访问的对象都可以访问(参考变量的修饰符 public protected等)
static修饰的变量只存在一份,所有可以访问的对象都允许进行修改
static 修饰的变量/方法在内存中被root引用,因此不会被GC回收,
static修饰的变量在类被加载的时候就会被加载
被static修饰的方法/代码块只能引用被static修饰的方法/变量
static的主要用法
用来修饰变量 可以不需要实例化对象就可以直接引用变量,引用方法ClassName.field;
修饰方法 可以不需要实例化对象就可以直接引用方法,引用方法 ClassName.method;
静态块 用来实现需要在类加载时就需要加载的逻辑
06
结束语
如果你有好的答案可以提交至:
https://github.com/codeegginterviewgroup/CodeEggDailyInterview
往期文章:
Android 面试题:Handler、自定义View、Java三大特性、分发机制、动画(第1期)
《每日一道面试题》 第二期
《每日一道面试题》 第三期
《每日一道面试题》—— 第四期
Java垃圾回收机制、系统设计、Android异步、排序算法(第五期)
今日问题:
周末大家都学习吗?
快来码仔社群解锁新姿势吧!社群升级:Max你的学习效率
猜你喜欢
- 2024-09-26 Java学习:基础(static、单例)(java里static用法)
- 2024-09-26 代码区、常量区、静态区(全局区)、堆区、栈区不得不了解
- 2024-09-26 “静态”之静——深入解析C++中的static关键字
- 2024-09-26 java基础3种变量类型(详解、区别)
- 2024-09-26 Java static关键字你了解多少?(java中static关键字有什么作用)
- 2024-09-26 再也不要说不知道static了(ip route-static命令详解)
- 2024-09-26 夯实基础:详解static关键字和5类场景应用
- 2024-09-26 Java学习:static 关键字概述(static关键字的作用 java)
- 2024-09-26 Java基础:static关键字作用总结(javastatic关键字详解)
- 2024-09-26 JAVA 泛型中的通配符 T,E,K,V,?你都弄懂了吗?我都总结在这
- 1514℃桌面软件开发新体验!用 Blazor Hybrid 打造简洁高效的视频处理工具
- 573℃Dify工具使用全场景:dify-sandbox沙盒的原理(源码篇·第2期)
- 513℃MySQL service启动脚本浅析(r12笔记第59天)
- 486℃服务器异常重启,导致mysql启动失败,问题解决过程记录
- 486℃启用MySQL查询缓存(mysql8.0查询缓存)
- 469℃「赵强老师」MySQL的闪回(赵强iso是哪个大学毕业的)
- 449℃mysql服务怎么启动和关闭?(mysql服务怎么启动和关闭)
- 447℃MySQL server PID file could not be found!失败
- 最近发表
- 标签列表
-
- cmd/c (90)
- c++中::是什么意思 (83)
- 主键只能有一个吗 (66)
- c#console.writeline不显示 (75)
- pythoncase语句 (81)
- es6includes (73)
- windowsscripthost (67)
- apt-getinstall-y (86)
- node_modules怎么生成 (76)
- c++int转char (75)
- static函数和普通函数 (76)
- el-date-picker开始日期早于结束日期 (70)
- js判断是否是json字符串 (67)
- checkout-b (67)
- c语言min函数头文件 (68)
- asynccallback (71)
- localstorage.removeitem (74)
- vector线程安全吗 (70)
- & (66)
- java (73)
- js数组插入 (83)
- mac安装java (72)
- eacces (67)
- 查看mysql是否启动 (70)
- 无效的列索引 (74)