Fork me on GitHub
image frame

Spring2vue-my-code-life-3-about-java

从Spring 到Vue 3 关于Java

有什么事Java经常会被问到但是我一直记不住的呢.

基础

Java的基础类型?

int long short byte char boolean double float

声明基础类型的时候发生了什么?

例如

1
2
3
4
5
6
public class Main {
public int a;
//在栈中分配了空间给a
public int b = 0;
//在栈中分配了空间给b同时在常量区中查找变量0,如果有则栈中b指向该值
}

String 类型

1
2
3
4
5
6
public class Main {
public String c = "c";
public String d = "das";

public String e = c + d;
}

引用类型

关键字

transient

可序列化的对象中不需要进行序列化的变量

volatile

每次写的的时候从内存读取

atomic

####

其他

Java 链表

Java List

  • ArrayList
    • 数组
  • Vector
    • 数组
    • 线程安全
  • LinkedList
    • 链表

数组实现: 查找快,增删慢
链表实现: 查找慢,增删快

Java HashSet

    • 调用hashCode,计算存储位置
      • 进行equals比较
        • 没用元素/比较结果为false则存

Java Collection

Java HashMap

hash冲突

拉链法解决

初始容量,加载因子

线程不安全,

hashtable

线程安全

散列表

key value不能为空

支持Enumeration

ConcurrentHashMap

线程安全版HashMap

增加了segment层,每次针对单个segment加锁

LinkedHashMap

  • LinkedHashMap是继承于HashMap,是基于HashMap和双向链表来实现的。
  • HashMap无序;LinkedHashMap有序,可分为插入顺序和访问顺序两种。如果是访问顺序,那put和get操作已存在的Entry时,都会把Entry移动到双向链表的表尾(其实是先删除再插入)。
  • LinkedHashMap存取数据,还是跟HashMap一样使用的Entry[]的方式,双向链表只是为了保证顺序。
  • LinkedHashMap是线程不安全的

我看的这里

TreeMap

基于红黑树的NavigableMap,线程非安全,不允许null,存入需要实现comparable接口或实现comparator接口排序

JVM相关

jvm运行时数据区

  • 方法区 method area
  • 虚拟机栈 VM stack
  • 本地方法栈 native method stack
  • 堆 heap
  • 程序计数器 program counter register

###程序计数器

  • java 方法
    • 正在执行的虚拟机字节码的地址
  • 本地方法
    • undefined

java 虚拟机栈

  • 线程私有
  • java方法执行的内存模型。
  • 每个方法在执行时都会创建一个栈帧 Stack Frame
    • 局部变量表
      • 编译器可知的各种基本类型(boolean, int,long, short, byte, double, float, char)
      • 对象引用类型(refrence)
      • returnAddress类型
    • 操作数栈
    • 动态链接
    • 方法出口

本地方法栈

  • 线程共享

方法区

  • 共享内存
  • 包含
    • 已被虚拟机加载的类信息
    • 常量
    • 静态变量
    • 即时编译器编译后的代码等数据
  • 运行时常量池
    • 存放编译期间生成的各种字面量和符号引用。
    • 内存有限

直接内存

不知道

HotSpot

后续再研究吧

对象的创建

对象的布局

###对象的访问定位

GC

Java 反射

Java 类加载

双亲

线程

1
2
3
4
5
6
7
8
9
10
11

new Thread(new Runnable() {
@Override
public void run () {


}
}).start()

//run的话只是正常运行,不会启动新线程
//如何验证?

Callable

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
public interface Callable<V> {
V call() throws Exception;
}

public interface Future<V> {
boolean cancel(boolean mayInterruptIfRunning);
boolean isCancelled();
boolean isDone();

V get() throws InterruptedException, ExecutionException;

V get(long timeout, TimeUnit unit) throws InterruptedException, ExecutionException, TimeoutException;
}

public interface RunnableFuture<V> extends Runnable, Future<V> {
void run();
}

public class FutureTask<V> implements RunnableFuture<V> {
...
}

线程池

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
public interface Executor {
void execute(Runnable command);
}

public interface ExecutorService extends Executor {
void shutdown();
List<Runnable> shutdownNow();

boolean isShutdown();
boolean isTerminated();

<T> Future<T> submit(Callable<T> task);
<T> Future<T> submit(Runnable task, T result);
Future<?> submit(Runnable task);
}

public class Executors {
public static ExecutorService newCachedThreadPool() {
return new ThreadPoolExecutor(0, Integer.MAX_VALUE, 60L, TimeUnit.SECONDS,
new SynchronousQueue<Runnable>());
}
...
}

四种线程池

  • newCachedThreadPool
    • 如无线程则新建。
    • 一定时间无使用则销毁
  • newSingleThreadExecutor
    • 维持一个线程
  • newFixedThreadPool
    • 最大值前一个任务一个线程
  • newScheduledThreadPool
    • 大小无限

线程异常则再加一新的线程

关闭方法

  • shutdown
    • 不接受新任务,任务结束后停止
  • shutdownNow
    • 尝试停止,返回未执行任务

线程同步

  • 同步方法
  • 同步代码块
  • volatile
  • 重入锁
    • ReentrantLock()
  • ThreadLocal
  • LinkedBlockingQueue
  • 原子变量

equals

先判断类型,在判断值。可重写

hashCode

返回

Spring2vue-my-code-life-2

从Spring 到Vue 2 Spring IOC&AOP

  • 控制反转 IoC (Inversion of controll)
  • 切面编程 AOP Aspect Oriented Programming
    • Java 代理
      • 动态代理
      • 静态代理

IOC

IOC,Inversion of Controll ,控制反转。我一直无法理解这东西到底是什么,为什么起这么一个反人类的名字。

java简单例子介绍IOC和AOP

DI Dependency Inject 依赖注入

依赖注入和控制反转的理解,写的太好了。

DL Dependency Lookup 依赖查找

  • 依赖拖拽
  • 上下文查找

AOP 切面编程

切面编程的简单意思大概就是,把代码切成3层。中间的夹心层是原先的逻辑代码,前后的饼干层是由AOP方式实现的通用逻辑代码。

静态代理
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25

public interface AbcService {
public void doing();
}

public class AbcServiceImpl implements AbcService {
public void doing() {
System.out.println('doing');
}
}

public class AbcServiceProxy implments AbcService {
private AbcService abcService;

public AbcServiceProxy (AbcService service) {
abcService = service;
}

@Override
public void doing() {
System.out.println("doing start")
abcService.doing()
System.out.println("doing end")
}
}
动态代理

动态代理的实现方式就是通过

Proxy.newProxyInstance方法,将需要代理的类,方法,以及参数传递到对应的 InvocationHandler内,然后在调用方法的前后增加想要的逻辑代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
public class AbsServiceDynamicProxy {

public static AbcService (AbcServiceImpl serviceImpl) {
return new Proxy.newProxyInstance(serviceImpl.class.getClassLoader()
,logger.getClass().getInterfaces()
, new InvocationHandler() {
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("before proxy");
method.invoke(serviceImpl,args);
System.out.println("after proxy")
return null;
}
})
}
}
相关

Spring2vue-my code lift

从Spring 到Vue (一) Spring

从去年六月份开始使用Spring+Vue开发前后端,那么原理是什么呢?我还不知道,这是我对自身知识结构的梳理。

Spring 是什么东西

Spring 是一个后端框架,它用于开发后端。和他平级的还有 ktorexpress等。

当然Spring远不止此,但是从一个非java后端人士的角度来说,暂时就这样把。

使用Spring进行开发与使用原生Java的区别

我为什么需要使用Spring呢,假如我需要实现一个http服务。我为什么不使用原生的java api帮助我实现一个简单的http服务器呢?

HTTP服务器

由此,让我先梳理一下http服务器做了什么事情。

  • 响应网络请求,返回api接口内容
  • 响应网络请求,返回html资源
  • 与mysql等进行通信。
  • 从服务器端进行请求,获取内网数据

Java Api 实现HTTP服务器

使用 com.sun.net.httpserver 包进行相关操作。我本身没有尝试过进行这样的操作,因为以往实现简单HTTP服务时我更倾向于使用express等node相关的技术栈,因为他们更

总而言之,通过官方给予我们的com.sun.net.httpserver包,我们可以简单得实现一个REST API,但是关于:

  • 认证
  • xxxx我没想好得内容,使用Spring会更加方便。

Spring 帮我们做了什么呢

现如今我想要使用spring搭建一个http服务器

Retrofit 源码 part 1

Retrofit 源码 part 1

Retrofit 大致上就是动态代理+注释处理

简单来说

如果我们要进行一个像这样的网络请求

1
2
3
GitHubService service = retrofit.create(GitHubService.class);

Call<List<Repo>> repos = service.listRepos("octocat");

摘自retrofit

其内部的过程是这样的

  • retrofit.create()

    • Proxy.newProxyInstance 创建一个java动态代理
      • loadServiceMethod() 调用这个方法
        • parseAnnotations 对GithubService.class内的注释进行处理
          • RequestFactory.parseAnnotations (处理注释)
          • HttpServiceMethod.parseAnnotations (与Okhttp关联)
      • loadServiceMethod().invoke = HttpServiceMethod.invoke 方法调用时会对应调用
  • service.listRepos == Proxy.InvocationHandler.invoke

下面看看具体内容.

create()

Retrofit 的源码我们从Retrofit.create这个方法开始看

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
public <T> T create(final Class<T> service) {
Utils.validateServiceInterface(service);
if (validateEagerly) {
eagerlyValidateMethods(service);
}
return (T) Proxy.newProxyInstance(service.getClassLoader(), new Class<?>[] { service },
new InvocationHandler() {
private final Platform platform = Platform.get();
private final Object[] emptyArgs = new Object[0];

@Override public Object invoke(Object proxy, Method method, @Nullable Object[] args)
throws Throwable {
// If the method is a method from Object then defer to normal invocation.
if (method.getDeclaringClass() == Object.class) {
return method.invoke(this, args);
}
if (platform.isDefaultMethod(method)) {
return platform.invokeDefaultMethod(method, service, proxy, args);
}
return loadServiceMethod(method).invoke(args != null ? args : emptyArgs);
}
});
}

在craete()中,先对参数final Class service做一个校验,是否是一个interface,是否有继承自其他interface之类的。

这一部分的核心是返回了一个 Proxy.newProxyInstance(...) , 使用Java 动态代理。同时动态代理的 InvocationHandler 的 invoke()方法的实现与service的注释相关.

我们看到这一部分

1
return loadServiceMethod(method).invoke(args != null ? args : emptyArgs);

loadServiceMethod

每次执行代理的方法的时候,执行loadServiceMethod.invoke, 所以就是说 Retrofit.create()返回的结果由动态代理帮助实现。那么怎么样把service的方法调用之后就实现网络请求呢?这就由注释实现了。
loadserviceMethod的相关代码如下

1
2
3
4
5
6
7
8
9
10
11
12
13
ServiceMethod<?> loadServiceMethod(Method method) {
ServiceMethod<?> result = serviceMethodCache.get(method);
if (result != null) return result;

synchronized (serviceMethodCache) {
result = serviceMethodCache.get(method);
if (result == null) {
result = ServiceMethod.parseAnnotations(this, method);
serviceMethodCache.put(method, result);
}
}
return result;
}

这里面我们需要关注的是

1
resuslt = ServiceMethod.parseAnnotations(this, method);

parseAnnotations

很明显这个是对注释进行处理,那么我们需要关注parseAnnotations()做了怎么样的处理.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
abstract class ServiceMethod<T> {
static <T> ServiceMethod<T> parseAnnotations(Retrofit retrofit, Method method) {
RequestFactory requestFactory = RequestFactory.parseAnnotations(retrofit, method);

Type returnType = method.getGenericReturnType();
if (Utils.hasUnresolvableType(returnType)) {
throw methodError(method,
"Method return type must not include a type variable or wildcard: %s", returnType);
}
if (returnType == void.class) {
throw methodError(method, "Service methods cannot return void.");
}

return HttpServiceMethod.parseAnnotations(retrofit, method, requestFactory);
}

abstract T invoke(Object[] args);
}

ServiceMethod的源码很短,简单看来, ServiceMethod.parseAnnotations(…) 完成了两件事

  • 从 retrofit, method 中取得了RequestFactory类的示例retrofitFactory
  • 将 retrofitFactory作为参数交由 HttpServiceMethod处理.

RequestFactory.parseAnnotations(retrofit, method)

这里是真正的对parseAnnotation 进行处理,为什么这么说呢,read the fucking code.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
final class RequestFactory {
static RequestFactory parseAnnotations(Retrofit retrofit, Method method) {
return new Builder(retrofit, method).build();
}

RequestFactory(Builder builder) {
method = builder.method;
baseUrl = builder.retrofit.baseUrl;
httpMethod = builder.httpMethod;
relativeUrl = builder.relativeUrl;
headers = builder.headers;
contentType = builder.contentType;
hasBody = builder.hasBody;
isFormEncoded = builder.isFormEncoded;
isMultipart = builder.isMultipart;
parameterHandlers = builder.parameterHandlers;
}

...

static final class Builder {
...

Builder(Retrofit retrofit, Method method) {
this.retrofit = retrofit;
this.method = method;
this.methodAnnotations = method.getAnnotations();
this.parameterTypes = method.getGenericParameterTypes();
this.parameterAnnotationsArray = method.getParameterAnnotations();
}

RequestFactory build() {
for (Annotation annotation : methodAnnotations) {
parseMethodAnnotation(annotation);
}
...

return new RequestFactory(this);
}


private void parseMethodAnnotation(Annotation annotation) {
if (annotation instanceof DELETE) {
parseHttpMethodAndPath("DELETE", ((DELETE) annotation).value(), false);
} else if (annotation instanceof GET) {
parseHttpMethodAndPath("GET", ((GET) annotation).value(), false);
} else if (annotation instanceof HEAD) {
parseHttpMethodAndPath("HEAD", ((HEAD) annotation).value(), false);
} else if (annotation instanceof PATCH) {
parseHttpMethodAndPath("PATCH", ((PATCH) annotation).value(), true);
} else if (annotation instanceof POST) {
parseHttpMethodAndPath("POST", ((POST) annotation).value(), true);
} else if (annotation instanceof PUT) {
parseHttpMethodAndPath("PUT", ((PUT) annotation).value(), true);
} else if (annotation instanceof OPTIONS) {
parseHttpMethodAndPath("OPTIONS", ((OPTIONS) annotation).value(), false);
} else if (annotation instanceof HTTP) {
HTTP http = (HTTP) annotation;
parseHttpMethodAndPath(http.method(), http.path(), http.hasBody());
} else if (annotation instanceof retrofit2.http.Headers) {
String[] headersToParse = ((retrofit2.http.Headers) annotation).value();
if (headersToParse.length == 0) {
throw methodError(method, "@Headers annotation is empty.");
}
headers = parseHeaders(headersToParse);
} else if (annotation instanceof Multipart) {
if (isFormEncoded) {
throw methodError(method, "Only one encoding annotation is allowed.");
}
isMultipart = true;
} else if (annotation instanceof FormUrlEncoded) {
if (isMultipart) {
throw methodError(method, "Only one encoding annotation is allowed.");
}
isFormEncoded = true;
}
}

...
}
}

HttpServiceMethod

再 HttpServiceMethod.parseAnnotations中 再次将retrofit ,method进行处理

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
final class HttpServiceMethod<ResponseT, ReturnT> extends ServiceMethod<ReturnT> {

static <ResponseT, ReturnT> HttpServiceMethod<ResponseT, ReturnT> parseAnnotations(
Retrofit retrofit, Method method, RequestFactory requestFactory) {
CallAdapter<ResponseT, ReturnT> callAdapter = createCallAdapter(retrofit, method);

...
Converter<ResponseBody, ResponseT> responseConverter =
createResponseConverter(retrofit, method, responseType);

okhttp3.Call.Factory callFactory = retrofit.callFactory;
return new HttpServiceMethod<>(requestFactory, callFactory, callAdapter, responseConverter);
}
...
}

从这里开始 retrofit 和method转化为
requestFactory callFactory callAdapter responseConverter作为参数构建 HttpServiceMethod实例。
所以我们需要去查看HttpServiceMethod是来干什么的

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17

final class HttpServiceMethod<ResponseT, ReturnT> extends ServiceMethod<ReturnT> {
private HttpServiceMethod(RequestFactory requestFactory, okhttp3.Call.Factory callFactory,
CallAdapter<ResponseT, ReturnT> callAdapter,
Converter<ResponseBody, ResponseT> responseConverter) {
this.requestFactory = requestFactory;
this.callFactory = callFactory;
this.callAdapter = callAdapter;
this.responseConverter = responseConverter;
}

@Override ReturnT invoke(Object[] args) {
return callAdapter.adapt(
new OkHttpCall<>(requestFactory, args, callFactory, responseConverter));
}
...
}

可以看出,当 service里面的方法被执行的时候,是由callAdapter.adapt()处理一个OkHttoCall完成的。
到此为止,retrofit与okhttp之间的联系也就找到了.

我对动态代理也不熟悉,暂时到此为止,。

Android AppCompatActivity

Android AppCompatActivity

关系

  • extends FragmentActivity
  • implements AppCompatCallback, SupportParentable, DelegateProvider

与Activity 比较

setContentView

AppCompatActivity的setContentView ,调用this.getDelegate().setContentView(…)
而Acitivity的setContentView调用this.getWindow().setContentView(…)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
// AppCompatActivity
public void setContentView(View view, LayoutParams params) {
this.getDelegate().setContentView(view, params);
}

public void setContentView(@LayoutRes int layoutResID) {
this.getDelegate().setContentView(layoutResID);
}

// Activity
public void setContentView(@LayoutRes int layoutResID) {
getWindow().setContentView(layoutResID);
initWindowDecorActionBar();
}

AppCompatActivity的setContentView调用的时候会调用一个this.getDelegate()

quickapp 踩坑记(一) 入门坑与为什么踩这个坑

quickapp 踩坑记 (一) 入门坑与为什么踩这个坑

简介

主要讲了

  • ubuntu + atom 搭建快应用开发环境
  • 调试相关
    • 无法通过wifi调试以及可能原因
    • 由于调试导致的上传失败
  • 通过 adb 调试快应用
  • 闲话:为何入坑

正文

基本配置

我的ubuntu是 18.04,当然这并不重要,应该说我的系统是ubuntu。环境配置就是很正常的安装一些东西就好了。

目前快应用有3个IDE,一个官方的IDE和华为的两个版本的IDE,看上去都是基于VSCODE的,另外他们都没有linux的版本…

官方好像也有推荐使用:

  • sublxxx(一看我名字都记不住就知道我不喜欢用这个)
  • vscode (安装快应用对应的插件)
  • webstorm(好像没有免费版,我就没用了,尊重一下JetBrains)

首先 install node

然后 install atom

配置一下文本编辑工具

打开 atom

–> 菜单栏 Edit

–> 选择 Preferences (window下可能是File->Settings)

–> 点击按钮 Open Config Folder

–> 打开文件 config.cson

配置对ux文件的语法高亮

1
2
3
4
5
6
"*":
core:
customFileTypes:
"text.html.basic": [
"ux"
]

然后随意弄一下UI theme 和 Syntax theme

我的配置完之后是这样子的

然后就算很正常的npm install -g hap-toolkit

可以选择装一个emmet插件辅助自动补全

走起~

关于调试

无法在线更新

一开始的时候遇到过无法在线安装的问题,后来发现不止是快应用,其他用wifi调试的类似开发方式有时也会遇到。这里的其他开发方式指的是 Ionic 的 Ionic DevApp和React Native的Expo。这两者也是在手机上运行了一个’容器’,方便实现热加载,利用chrome dev tool进行调试等。

言归正传,快应用调试的时候运行

1
npm run server

会生成一堆东西:

这里生成ip地址不一定是对应的本机的地址(当然我图中的是正确的)。如果电脑上装了虚拟机/docker/其他容器,这里的服务器地址有可能会是虚拟机的网卡的ip,同时二维码对应的也是虚拟机的ip,这样扫码是不能在线更新的(因为连不上)

如果扫玛一直扫不出来的话,可以考虑换一个命令行终端。比如我之前用Win10的cmd.exe的时候就不像一个二维码(顺手安利一波cmder)。

当然直接手动输入地址也是ok的。

在这里顺带感谢一下在我遇到这个问题时群里通过ip地址看出是虚拟机ip的那个大哥

ps:这个问题在官方支持usb调试之后就与我绝缘了。

无法上传

在调用快应用的系统能力之网络之上传时,有可能会发生这样的错误

代码是这样子的:

1
2
3
4
5
6
7
8
9
10
11
12
13
import request from '@system.request' //正常的导入

/**
* 正常的使用
*/
request.upload({
url : "http://",
files : o.files,
data : o.data,
method:"POST",
success : onSuccess,
fail: onFetchFail
})

这通常是发生在开了调试工具的时候,一边进行调试一边上传就会报错:

1
2
发生了错误: 1000
Stream Closed
处理方法:

这时候只需要拔掉你的usb线,再次上传,一切ok。

其实就是退出调试模式,单纯运行快应用。

如果想要查看上传过程中的log的话可以使用adb。

adb 调试快应用

鉴于快应用开发的应该是前端的同学,可能不太了解adb是什么
adb = Android Debug Bridge ,android开发可能会用得比较多一点。

一般想要配置adb的话,下载一个android sdk tool就好了(把整个androidt stuido下载下来也是可以的),然后配置环境变量,
一般adb是在

1
$ANDROID_SDK_HOME/platform-tools/

这个目录下。

有时候不想打开chrome-dev-tool,只想在命令行查看log,就可以使用

1
2
3
4
console.info('你的log')
// 好像需要console.info()才可以
// console.log()的日志不能被下面的命令抓取
//(记得不清+不想做实验了)

然后在命令行输入:

1
adb logcat | grep JsConsole

adb logcat 是读取手机运行的日志,快应用运行的日志自然也包含在里面。

然后使用 grep JsConsole 进行筛选。之所以用JsConsole,是因为我目测得出快应用引擎(无论是官方的快应用预览器还是厂商自己的快应用引擎) 都是这个tag。

windows同学没有grep命令的话……可以使用windows上支持bash的终端工具。

最近在ubutn上 adb 有时会与 npm run server 冲突,需要关掉其中一个(或者会自动帮你关到其中一个)

一些闲(fei4)话

比起前端开发,我更加熟悉的可能是android端的开发。虽然也大概清楚前端开发是怎么一回事,但是完完整整地用标记语言+js+css开发一个东西的经验并不是很多。所以如有错漏的,不专业的地方(后续会很多)请轻喷。写这篇东西一是为了征文大赛,二是为了顺带梳理一番开发过程中遇到的问题。

同时最近忙成狗的我也没时间看别人的征文,如果有些内容已经有人指出了,如有巧合纯属雷同,啦啦啦啦啦啦。

在年初的时候学长让了解一下快应用和flutter,然后被flutter的语法劝退之后尝试写起了快应用。想着当时微信小程序封测的时候也对小程序浅尝辄止了一番(学校的小团体搞了比赛,赚了个androd高级进阶和鼠标让我甚是高兴,难以忘怀,特此讨打),但是那时候由于种种原因一直在AIDE上写app,也就没机会没能力继续接触。

而去年学校微信小程序比赛搞起来,发现小程序的IDE和开发流程都变了很多。(2333,无意义感慨)

刚好快应用出来,想着有机会从初期接触一个框架,然后了解这个东西是怎么一步步完善起来的,于是决定踩坑。

Android 面试经历吧,称不上经验

小米一面

  • 自我介绍
  • 算法
    • 整形重复数组找出出现奇数次的数字
    • (())字符串匹配
    • 二叉树从右看
  • java
    • 权限关键字
    • 进程与线程
  • Android
    • anr 情况,处理
    • 线程,进程
    • app一般有几个进程
    • 常用了解的讲一下
    • 网络请求

iso7层

5层

网络掩码

小米二面

  • 自我介绍
  • 数据库
    • 触发器
    • 事务
  • realm 线程安全吗
  • 事件分发机制
  • 单链表反转
  • 内存回收机制
  • kotlin 好处
  • kotlin 不需要findviewbyid原理
  • Android 源码看过吗
  • 布局
    • LinearLayout
    • RelativeLayout
  • 强引用 弱引用
  • java 内存泄露,处理
  • handler
  • 启动模式
  • 为什么listview要改成recyclerview
  • mvp与mvc区别
  • java怎么new 一个子类
  • 快应用怎么弄mvp

-

Android Context相关

Android Context 相关

Context 基本上就是Activity + Service + Application

Class Overview
Interface to global information about an application environment. This is an abstract class whose implementation is provided by the Android system. It allows access to application-specific resources and classes, as well as up-calls for application-level operations such as launching activities, broadcasting and receiving intents, etc.

Context是用于访问应用资源,类同时也进行application层的操作:启动activity广播以及接收广播

api文档上关于

再看看Context相关的子类.因为Context的父类就直接是java.lang.Object了。

Context的子类有

  • ContextWrapper
  • MockContext

Java Interface NavigableMap<K,V>

Java Interface NavigableMap

  • Map.Entry<K,V> lowerEntry(K key)
  • K lowerKey(K key);
  • Map.Entry<K,V> floorEntry(K key);
  • K floorKey(K key);
  • ceilingEntry
  • ceilingKey
  • higherEntry
  • higherKey
  • firstEntry
  • lastEntry
  • pollFirstEntry
  • pollLastEntry
  • NavigableMap<K,V> descendingMap();
  • NavigableSet navigableKeySet();
  • NavigableSet descendingKeySet();
  • NavigableMap<K,V> subMap(K fromKey, boolean fromInclusive,K toKey, boolean toInclusive);
  • NavigableMap<K,V> headMap(K toKey,boolean inclusive);
  • NavigableMap<K,V> tailMap(K fromKey, boolean inclusive);
  • SortedMap<K,V> subMap(K fromKey, K toKey);
  • SortedMap<K,V> headMap(K toKey);
  • SortedMao<K,V> tailMap(K fromKey);
  • © 2020 Kfdykme
  • Powered by Hexo Theme Ayer
  • PV: UV:

请我喝杯咖啡吧~

支付宝
微信