知识点梳理2 Java 基础
Lambda
原生版
button.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Toast.makeText( MainActivity.this,"AAA",Toast.LENGTH_SHORT ).show();
}
});
Lambda 版
button.setOnClickListener(v -> Toast.makeText( MainActivity.this,"AAA",Toast.LENGTH_SHORT ).show());
(parameters) -> { expression or statements }
// 无参数, 返回1+2的结果
() -> 1+2
// 接收一个参数(数字类型),返回其2倍的值
x -> 2 * x
// 接收2个参数(数字),返回表达式运算的结果
(x, y) -> x + y
// 多个语句要用大括号包裹, 并且返回值要用return指明
(x, y) -> {
int result = x + y;
System.out.print(result);
return result;
}
// 接收string 对象, 并在控制台打印
s -> System.out.print(s)
其中参数的类型可以不声明, 编译器会结合上下文智能推断, 比如这句
s -> System.out.print(s)
等价于
(String s) -> System.out.print(s)
注意: 无参数时()不能省略
lambda 的应用场景:
单实现的接口
条目点击事件
封装网络请求的回调
与RxJava的链式调用
1.view.setOnClickListener(v -> {
//dosomething
});
2. listview.setOnItemClickListener((parent, view, position, id) -> {
//dosomething
});
3.例如通过封装OkHttp或者Retrofit的回调方法,将其转变成单实现的回调接口进行调用
4.Integer[] list = {1,2,3,4,5};
Observable
.from(list)
.filter(integer->integer%2==0)//挑选出偶数
.map(integer -> "number is"+integer)//转换成String
.subscribe(s->System.out.println(s));//相当于forEach(s->System.out.println(s));
//forEach是同步的 subscribe是异步的
参考:https://www.jianshu.com/p/a3fd8e063f27
泛型
// 泛型类:把泛型定义在类上
public class ObjectTool<T> {
private T obj;
public T getObj() {
return obj;
}
public void setObj(T obj) {
this.obj = obj;
}
}
// 泛型方法:把泛型定义在方法上
public class ObjectTool {
public <T> void show(T t) {
System.out.println(t);
}
}
/* * 泛型接口:把泛型定义在接口上 */
public interface Inter<T> {
public abstract void show(T t);
}
List<String>[] ls = new ArrayList<String>[10];//编译报错
List<String>[] list = new ArrayList[10];//正确
List<?>[] ls = new ArrayList<?>[10];//正确
泛型学习的基础文章:
-
Java泛型(一)
- java是伪泛型,我们在代码写的是泛型,但是在编译时会擦除所有的泛型标记,用具体类型来替换泛型类型,这是在编译器在编译时干的事
- 泛型不能用在静态的方法和参数中,因为静态是属于类型加载器的,不是数据一个具体类型对象的,我们不在一个具体的对象中声明具体的类型,泛型怎么知道要转换成什么类型呢。除非你把这个静态方法声明为静态泛型方法
-
Java泛型(二)
- 具体师范了泛型 - 类,方法,泛型方法,对泛型的使用
- 明确了泛型的通配符的使用 List<? extends Number> / List<? super Integer>
- 明确了泛型逆变与协变应该怎么写,这个很重要的,用的 list 做的例子
设计模式
1.单一职责原则(Single Responsibility Principle, SRP)
定义:一个类应只包含单一的职责。
2.开放封闭原则(Open - Closed Principle, OCP)
定义:一个模块、类、函数应当是对修改关闭,扩展开放。
3.里氏代换原则( Liskov Substitution Principle, LSP)
定义:使用父类的地方能够使用子类来替换,反过来,则不行。
4.依赖倒转原则( Dependence Inversion Principle, DIP)
定义:抽象不应该依赖于细节,细节应当依赖于抽象。
5.接口隔离法则(Interface Segregation Principle, ISL)
定义:一个类对另一个类的依赖应该建立在最小的接口上。
6.迪米特法则(Law of Demeter, LoD)
定义:一个类尽量不要与其他类发生关系
设计模式一般分为三类:创建型模式、结构型模式、行为型模式。
创建型模式
创建型模式简单来说就是用来创建对象的。一共有五种:单例模式、建造者模式、工厂方法模式、抽象工厂模式、原型模式。
单例模式 :确保某一个类只有一个实例,并且提供一个全局访问点。
建造者模式 : 用来创建复杂的复合对象。
工厂方法模式 :让子类来决定要创建哪个对象。
抽象工厂模式 :创建多个产品族中的产品对象。
原型模式 :通过复制原型来创建新对象。
行为型模式
行为型模式主要是描述类或者对象是怎样交互和怎样分配职责的。一共有十一种:策略模式、模板方法模式、观察者模式、迭代器模式、责任链模式、命令模式、备忘录模式、状态模式、访问者模式、中介者模式、解释器模式。
策略模式 :封装不同的算法,算法之间能互相替换。
状态模式 :根据不同的状态做出不同的行为。
责任链模式 :将事件沿着链去处理。
观察者模式 :状态发生改变时通知观察者,一对多的关系。
模板方法模式 :定义一套流程模板,根据需要实现模板中的操作。
迭代器模式 :提供一种方法顺序访问一个聚合对象中的各个元素。
备忘录模式 :保存对象的状态,在需要时进行恢复。
访问者模式 :稳定数据结构中,定义新的操作行为。
中介者模式 :将网状结构转变为星型结构,所有行为都通过中介。
解释器模式 :定义语法,并对其进行解释。
命令模式 :将请求封装成命令,并记录下来,能够撤销与重做。
结构型模式
结构型模式主要是用于处理类或者对象的组合。一共有七种:适配器模式、装饰模式、代理模式、外观模式、桥接模式、组合模式、享元模式。
代理模式 :控制客户端对对象的访问。
组合模式 :将整体与局部(树形结构)进行递归组合,让客户端能够以一种的方式对其进行处理。
适配器模式 :将原来不兼容的两个类融合在一起。
装饰者模式 :为对象添加新功能。
享元模式 :使用对象池来减少重复对象的创建。
外观模式 :对外提供一个统一的接口用来访问子系统。
桥接模式 :将两个能够独立变化的部分分离开来。
参考:https://www.jianshu.com/p/a3e844619ed2
单例:
public class Singleton {
private volatile static Singleton singleton;
private Singleton() {
}
public static Singleton getSingleton() {
if (singleton == null) {
synchronized (Singleton.class) {
if (singleton == null) {
singleton = new Singleton();
}
}
}
return singleton;
}
}
public class Singleton {
private Singleton() {
}
public static Singleton getSingleton() {
return SingletonHolder.sInstance;
}
private static class SingletonHolder {
private static final Singleton sInstance = new Singleton();
}
}
使用反射能够破坏单例模式,所以应该慎用反射
可以通过当第二次调用构造函数时抛出异常来防止反射破坏单例,以懒汉式为例:
反序列化时也会破坏单例模式,可以通过重写readResolve方法避免,以饿汉式为例:
建造者:
image.pngAndroid中的源码分析
Android中的AlertDialog.Builder就是使用了Builder模式来构建AlertDialog的。
AlertDialog.Builder的简单用法
AlertDialog.Builder builder = new AlertDialog.Builder(activity);//创建一个Builder对象
builder.setIcon(R.drawable.icon);
builder.setTitle("标题");
builder.setMessage("信息");
builder.setPositiveButton("确定",
new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
}
});
AlertDialog alertDialog = builder.create();//创建AlertDialog对象
alertDialog.show();//展示AlertDialog
通过Builder对象来构建Icon、Title、Message等,将AlertDialog的构建过程和细节隐藏了起来。
AlertDialog相关源码分析
//AlertDialog源码
public class AlertDialog extends Dialog implements DialogInterface {
private AlertController mAlert;//接受Builder成员变量P的参数
AlertDialog(Context context, @StyleRes int themeResId, boolean createContextThemeWrapper) {
super(context, createContextThemeWrapper ? resolveDialogTheme(context, themeResId) : 0, createContextThemeWrapper);
mWindow.alwaysReadCloseOnTouchAttr();
mAlert = AlertController.create(getContext(), this, getWindow());//创建AlertController对象
}
@Override
public void setTitle(CharSequence title) {//设置Title
super.setTitle(title);
mAlert.setTitle(title);//保存在AlertController对象中
}
public void setMessage(CharSequence message) {//设置Message
mAlert.setMessage(message);//保存在AlertController对象中
}
public void setIcon(@DrawableRes int resId) {//设置Icon
mAlert.setIcon(resId);//保存在AlertController对象中
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
mAlert.installContent();//安装AlertDialog的内容
}
//AlertDialog其他代码略
public static class Builder {
private final AlertController.AlertParams P;//构建AlertDialog对象所需要的参数都存放在P中
public Builder(Context context) {
this(context, resolveDialogTheme(context, 0));
}
public Builder(Context context, int themeResId) {
P = new AlertController.AlertParams(new ContextThemeWrapper(
context, resolveDialogTheme(context, themeResId)));//初始化AlertParams对象
}
public Context getContext() {
return P.mContext;
}
public android.app.AlertDialog.Builder setTitle(CharSequence title) {
P.mTitle = title;//保存title到P中
return this;
}
public android.app.AlertDialog.Builder setMessage(CharSequence message) {
P.mMessage = message;//保存message
return this;
}
public android.app.AlertDialog.Builder setIcon(@DrawableRes int iconId) {
P.mIconId = iconId;//保存IconId
return this;
}
//Builder其他代码略
public android.app.AlertDialog create() {//构建AlertDialog
final android.app.AlertDialog dialog = new android.app.AlertDialog(P.mContext, 0, false);//创建一个AlertDialog对象
P.apply(dialog.mAlert);//将P中的参数设置到AlertController中
//其他设置代码略
return dialog;
}
}
}
//Dialog源码
public class Dialog implements DialogInterface, Window.Callback, KeyEvent.Callback, View.OnCreateContextMenuListener, Window.OnWindowDismissedCallback {
//其他代码略
public void show() {
//前面代码略
if (!mCreated) {
dispatchOnCreate(null);//分发onCreate
} else {
final Configuration config = mContext.getResources().getConfiguration();
mWindow.getDecorView().dispatchConfigurationChanged(config);
}
onStart();//调用onStart()
mDecor = mWindow.getDecorView();
//设置参布局参数略
mWindowManager.addView(mDecor, l);//添加到WindowManager
mShowing = true;
sendShowMessage();
}
void dispatchOnCreate(Bundle savedInstanceState) {//分发onCreate
if (!mCreated) {
onCreate(savedInstanceState);//调用AlertDialog的onCreate方法,创建AlertDialog视图
mCreated = true;
}
}
}
//AlertController源码
public class AlertController {
//其他代码略
public void installContent() {//安装内容
int contentView = selectContentView();//选择合适的布局
mWindow.setContentView(contentView);//布局添加到Window中
setupView();//把dialog.mAlert对象中需要构建的元素逐个添加设置到Window上,即构建我们设置的布局发生在这一步中
}
}
简单流程说明:
1.通过AlertDialog.Builder设置各种属性后(如:setTitle()),这些属性信息会保存在P变量中,P变量的类型为AlertController.AlertParams。
2.调用builder.create()即可返回一个AlertDialog对象。
2.1 builder.create()方法中首先会创建一个AlertDialog对象,AlertDialog对象构造时会初始化WindowManager和Window。
2.2 builder.create()创建完AlertDialog对象后,会调用 P.apply(dialog.mAlert);即把P变量中所存储的用来构建AlertDialog对象的元素设置到了dialog.mAlert中,dialog.mAlert的类型为AlertController。
3.调用AlertDialog的show()方法,展示界面。
3.1 show()方法中会调用 dispatchOnCreate(null),dispatchOnCreate(null)调起onCreate(),onCreate()会调起mAlert.installContent();即安装AlertDialog的内容。
3.2 installContent()中会调用mWindow.setContentView(mAlertDialogLayout);即把mAlertDialogLayout这个布局加到Window中去。
3.3 调完mWindow.setContentView(mAlertDialogLayout)后会调用setupView(),setupView()中会把dialog.mAlert对象中需要构建的元素逐个添加设置到mWindow上。
3.4 最后通过把view添加到mWindowManager上展示出来。
总结:
builder模式隐藏了这种复杂的构建过程,只需几行简单的代码就把AlertDialog给展示出来了。
AlertDialog的builder中并没有抽象建造者(Builder)、Director(指挥者类)等角色。AlertDialog.Builder同时扮演了Builder、ConcreteBuilder、Director等角色,这是Android中的一种简化,也值得我们去学习使用。
参考:https://www.jianshu.com/p/154948d5adc6
工厂方法:
image.png
Android中的源码分析
Android中的ThreadFactory就是使用了工厂方法模式来生成线程的,线程就是ThreadFactory的产品。
ThreadFactory相关源码分析
//抽象产品:Runnable
public interface Runnable {
public abstract void run();
}
//具体产品:Thread
public class Thread implements Runnable {
//构造方法
public Thread(Runnable target, String name) {
init(null, target, name, 0);
}
@Override
//实现抽象产品的抽象方法
public void run() {
if (target != null) {
target.run();
}
}
//其他代码略
}
//抽象工厂:ThreadFactory
public interface ThreadFactory {
Thread newThread(Runnable r);
}
//具体工厂:AsyncTask中的实现
private static final ThreadFactory sThreadFactory = new ThreadFactory() {
private final AtomicInteger mCount = new AtomicInteger(1);
//实现抽象工厂的抽象方法
public Thread newThread(Runnable r) {
return new Thread(r, "AsyncTask #" + mCount.getAndIncrement());//返回Thread这个产品
}
};
总结:
这里只要是介绍Android系统中工厂方法模式的应用,线程和AsyncTask的原理就不说了。
通过ThreadFactory,我们可以创建出不同的Thread来。
同样,我们可以创建另外类似的工厂,生产某种专门的线程,非常容易扩展。