美文网首页
知识点梳理2 Java 基础

知识点梳理2 Java 基础

作者: 48d1753082c0 | 来源:发表于2018-07-26 22:25 被阅读13次

    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.png

    Android中的源码分析
    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来。
    同样,我们可以创建另外类似的工厂,生产某种专门的线程,非常容易扩展。

    参考:https://www.jianshu.com/p/e6c02a54f447

    相关文章

      网友评论

          本文标题:知识点梳理2 Java 基础

          本文链接:https://www.haomeiwen.com/subject/hwkimftx.html