├── Android ├── Activity生命周期和启动模式.md ├── Android性能优化.md ├── Android的消息机制.md ├── Android的线程和线程池.md ├── Bitmap的加载和Caches.md ├── Drawable.md ├── IPC机制.md ├── JNI和NDk编程.md ├── RemoteViews.md ├── View的事件体系.md ├── View的工作原理.md ├── 动画.md ├── 四大组件的工作流程.md ├── 理解Windows和WindowManger.md └── 综合技术.md ├── DesignPattern ├── chapter01 - 面向对象六大原则 ├── chapter02 - 单例模式 ├── chapter03 - Builder模式 └── chapter04 - 原型模式 ├── Http ├── test.md └── test2.md ├── Java ├── Java 反射.md ├── java String.md ├── java io.md ├── java 异常.md ├── java基础知识.md ├── java多线程.md ├── java注解.md ├── java集合.md ├── java面向对象.md ├── jvm.md └── 线程池.md └── README.md /Android/Activity生命周期和启动模式.md: -------------------------------------------------------------------------------- 1 | ### 生命周期的几种普通情况 2 | * 针对一个特定的Activity,第一次启动,回调如下,onCreate->onStart->onResume 3 | * 用户打开新的Activity的时候原来的Activity的回调 onPause->onStop 4 | * 再次回到原来的activity的时候onRestart->onStart->onResume 5 | * 一个Activity中打开另外一个Activity再返回的全部生命周期 AonPause->BonCreate->BonStart->BonResume->AonStop->BonPause-AonReStart->AonStart->AonResume->BonStop->BOnDestroy 6 | * 按back回退的时候onPause->onStop->onDestroy 7 | * 按home切换到桌面又回到activity onPause->onStop->onRestart->onStart->onResume 8 | * 调用finish之后onDestroy 9 | #### 特殊情况下的生命周期 10 | ##### 横竖屏切换 11 | 首先了解两个回调方法onSaveInstanceState和onRestoreInstanceState,save是调用在onStop之前的和onPause没有先后顺序,,这个方法只在Activity方法被异常终止的情况下调用,当异常终止的Activity倍被重新建立之后,系统会调用onRestoreInstance和onCreate方法 12 | onRestoreInstanceState回调方法调用的时候表明Bundle对象非空,不用加非空判断,onCreate择需要加非空 13 | ###### 生命周期 14 | onPause->onSaveInstanceState->onStop->onDestroy->onCreate->onStart->onRestoreInstanceState->onResume 15 | 为了防止Activity的销毁和重建,可以在AndroidManifest中制定activity中指定如下属性 16 | ``` 17 | android : configChanges = "orientation|screenSize" 18 | //这样,销毁和重建的时候,会调用下面的方法,onConfigurationChanged 19 | ``` 20 | ##### 资源不足导致优先级地的被杀死 21 | (1) 前台Activity——正在和用户交互的Activity,优先级最高。
22 | (2) 可见但非前台Activity——比如Activity中弹出了一个对话框,导致Activity可见但 23 | 是位于后台无法和用户交互。
24 | (3) 后台Activity——已经被暂停的Activity,比如执行了onStop,优先级最低。
25 | 当系统内存不足时,会按照上述优先级从低到高去杀死目标Activity所在的进程。我 26 | 们在平常使用手机时,能经常感受到这一现象。这种情况下数组存储和恢复过程和 27 | 上述情况一致,生命周期情况也一样 28 | 29 | 30 | -------------------------------------------------------------------------------- /Android/Android性能优化.md: -------------------------------------------------------------------------------- 1 | #### 布局优化 2 | 在既可以使用linearlayout和relativelayout的时候使用linearlayout,如果布局优点复杂,简单的linearlayout不能满足的时候,使用过relativelayout,尽量多实用include,merger标签,还有可以延迟加载的场景使用viewstub; 3 | #### 绘制优化1 4 | 在draw方法中,尽量不要新建变量,防止oom, 5 | #### 响应速度优化 6 | 主要真的anr出现,activity5 秒钟,broadcastreceiver10秒,service20秒。可以创建线程或者使用acynctask,或者intentService或者handlerThread来完成一些耗时操作。 7 | #### 内存优化 8 | 内存溢出 9 | 内存泄漏 10 | #### 线程优化 11 | 使用线程池 12 | 13 | 14 | -------------------------------------------------------------------------------- /Android/Android的消息机制.md: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /Android/Android的线程和线程池.md: -------------------------------------------------------------------------------- 1 | #### 直接继承Thread 2 | #### 实现Runnable 3 | #### handler 4 | #### handlerThread 5 | 本质上是一个thread只不过内部维护了自己的looper,我们都知道handler的运行和环境需要一个looper,在该thread的run方法中我们会先初始化一个looper并且设置线程的优先级以及我们的messagequeue,然后通过notify和wait机制,把我们的工作handler成功放入该looper中,然后开始我们的消息循环,为什么要把start方法放到前面也是这个原因吧。如果我们需要更新ui的话还可以配合一个handler使用,在耗时操作完成之后使用handler的post方法 6 | ``` 7 | HandelrThread是一个自带Looper的线程,因此只能作为子线程使用 8 | HandlerThread必须配合Handler使用,HandlerThread线程中做具体事情,必须要在Handler的callback接口中进行,他自己的run方法被写死了。 9 | 子线程中的Handler与HandlerThread的联系是通过childHandler = new Handler(handlerThread.getLooper(), mSubCallback);这句来进行的,也就是你说,childHandler获得HandlerThread线程的Looper,这样,他们两个就在同一阵营了。这也就是在创建Handler作为HandlerThread线程消息执行者,必须在调用start()方法之后的原因——HandlerThread.start()之后,run()方法才能跑起来,Looper才能得以创建,handlerThread.getLooper()才不会出错 10 | ``` 11 | #### asynctask 12 | 内部维护了两个线程池和一个handler对象,SerialExucutors,这个相当于一个线程任务队列,通过锁机制来保证asynctask中的任务是顺序执行的,Thread_Pool_Executor内部封装的才是真正执行任务的线程池,在asynctask的构造方法中,初始化一个worker和Futuretask对象,worker实质上是callable,,worker的call方法的话负责执行我们的耗时操作的任务,doInbackgroud以及之后的返回结果操作postResult,最终将这个future添加到任务队列serialexecutor中,最终执行,当我们使用executor方法的时候需要调用executor方法,这个方法中首先会实现调用我们的onPreExecutor方法,也就是我们重写的方法,之后的话就是将future传入我们的任务队列,通过锁来保证顺序执行,当然更新我们ui线程的操作还是我们的handler去执行的 13 | #### intentService 14 | 继承自service,内部通过handlerThread+handler机制进行一步操作,在create方法中进行handlerthread,然后将handler和handlerthread进行绑定,的初始化,这样就保证了异步操作。在startCommand方法中把intent封装到message里面,一次插入到任务队列,然后发送给我们的handler,handler中调用了一个handlerIntent传入intent,这是一个抽象方法,也就是我们要重写的,所以异步操作在这里面重写。 15 | ``` 16 | 类似于后台线程,但是他是服务,不容易被系统杀死,从而保证任务的执行,对于后台线程,如果进行中没有活动的四大组件,则该线程的优先级特比的低 17 | ``` 18 | #### 线程池 19 | -------------------------------------------------------------------------------- /Android/Bitmap的加载和Caches.md: -------------------------------------------------------------------------------- 1 | #### 首先我们了解一下lrucatch算法,最近未使用算法,他会把最近未使用的从列表中去除掉,底层采用limkedhashmap,其中可以设置我们知道linkedhashmap可以保证输出的时候按照插入顺序,他有一个构造方法可以设置链表的顺序是插入顺序还是访问顺序,true是访问顺序,就是把最近访问的放在表头,然后如果有新的元素添加进来的话,看看是不是缓存已经满了,如果已经满了的话,就按照底层linkedlist的访问顺序进行删除,如果使用get方法的话,就会把他放到队首,表示最近使用过了。 2 | -------------------------------------------------------------------------------- /Android/Drawable.md: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /Android/IPC机制.md: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /Android/JNI和NDk编程.md: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /Android/RemoteViews.md: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /Android/View的事件体系.md: -------------------------------------------------------------------------------- 1 | 2 | ### 事件 3 | * ACTION_DOWN 手指初次触摸到屏幕时候触发 4 | * ACTION_MOVE 手指在屏幕上华东的时候触发,会多次触发 5 | * ACTIOM_UP 手指离开屏幕的时候触发 6 | * ACTION_CANCEL 事件被上层拦截的时候触发 7 | * ACTION_OUTSIDE手指不再控件区域的时候触发 8 | 9 | ##### 方法 10 | * getAction() 获取事件类型。 11 | * getX() 获得触摸点在当前 View 的 X 轴坐标。 12 | * getY() 获得触摸点在当前 View 的 Y 轴坐标。 13 | * getRawX() 获得触摸点在整个屏幕的 X 轴坐标。 14 | * getRawY() 获得触摸点在整个屏幕的 Y 轴坐标。 15 | 16 | #### 单点触控一次简单的交互流程 17 | * 手指落下(ACTION_DOWN)------>多次移动(ACTION_MOVE)------>离开(ACTION_UP) 18 | * 如果只是单击事件不会触发ACTION_MOVE 19 | ![](http://onf44qqgp.bkt.clouddn.com/17-4-4/53392735-file_1491296114912_10c53.gif) 20 | 21 | #### 伪代码 22 | ```java 23 | @Override 24 | public boolean onTouchEvent(MotionEvent event) { 25 | switch (event.getAction()){ 26 | case MotionEvent.ACTION_DOWN: 27 | //手指第一次解除屏幕 28 | break; 29 | case MotionEvent.ACTION_MOVE: 30 | //手指移动 31 | break; 32 | case MotionEvent.ACTION_UP: 33 | //手指抬起 34 | break; 35 | case MotionEvent.ACTION_CANCEL: 36 | //事件被拦截 37 | break; 38 | case MotionEvent.ACTION_OUTSIDE: 39 | //超出区域 40 | break; 41 | } 42 | return super.onTouchEvent(event); 43 |    } 44 | ``` 45 | 46 | #### ACTION_CANCEL 47 | 48 | 上层View回收事件处理权限是后,ChildView会受到一个ACTION_CANCLE事件
49 | eg:
50 | 上层 View 是一个 RecyclerView,它收到了一个 ACTION_DOWN 事件,由于这个可能是点击事件,所以它先传递给对应 ItemView,询问 ItemView 是否需要这个事件,然而接下来又传递过来了一个 ACTION_MOVE 事件,且移动的方向和 RecyclerView 的可滑动方向一致,所以 RecyclerView 判断这个事件是滚动事件,于是要收回事件处理权,这时候对应的 ItemView 会收到一个 ACTION_CANCEL ,并且不会再收到后续事件。 51 | 52 | ### 多点触控 53 | #### 事件 54 | 55 | * ACTION_DOWN 第一个手指初次接触到屏幕 时触发。 56 | * ACTION_MOVE 手指在屏幕上滑动时触发,会多次触发。 57 | * ACTION_UP 最后一个 手指 离开屏幕 时触发。 58 | * ACTION_POINTER_DOWN 有非主要的手指按下(即按下之前已经有手指在屏幕上)。 59 | * ACTION_POINTER_UP 有非主要的手指抬起(即抬起之后仍然有手指在屏幕上)。 60 | 61 | #### 方法 62 | 63 | * getActionMasked() 多点触控必须使用这个方法获取事件类型 64 | * getActionIndex() 获取该事件是哪个手指产生的 65 | * getPointerCount() 获取屏幕上手指的个数 66 | * getPointerId(int pointerId)获取一个指针的位移标识符ID,手指按下和抬起来之间Id始终不变 67 | * findPointerIndex(int pointerId) d) 通过PointerId获取到当前状态下PointIndex,之后通过PointIndex获取其他内容 68 | * getX(int pointerIndex) 获取某一个指针(手指)的X坐标 69 | * getY(int pointerIndex) 获取某一个指针(手指)的Y坐标 70 | 71 | #### getAction() 与 getActionMasked() 72 | 73 | 当多个手指在屏幕上同时按下时候,会产生大量的事件,如何在获取事件类型的同时区分这些事件就是一个大问题了。 74 |
75 | int类型共32位(0x00000000),他们用最低8位(0x000000ff)表示事件类型,再往前的8位(0x0000ff00)表示事件编号,以手指按下为例讲解数值是如何合成的:
76 |
77 | ACTION_DOWN 的默认数值为 (0x00000000)
78 | ACTION_POINTER_DOWN 的默认数值为 (0x00000005)
79 | 80 | index属性: 81 | * 第1个手指按下 ACTION_DOWN (0x00000000) 82 | * 第2个手指按下 ACTION_POINTER_DOWN (0x00000105) 83 | * 第3个手指按下 ACTION_POINTER_DOWN (0x00000205) 84 | * 第4个手指按下 ACTION_POINTER_DOWN (0x00000305) 85 | 86 | #### 注意 87 | 88 | * 多点触控时必须使用 getActionMasked() 来获取事件类型。 89 | * 单点触控时由于事件数值不变,使用 getAction() 和 getActionMasked() 两个方法都可以。 90 | * 使用 getActionIndex() 可以获取到这个index数值。不过请注意,getActionIndex() 只在 down 和 up 时有效,move 时是无效的。 91 | 92 | #### 郑重声明:追踪事件流,请认准 PointId,这是唯一官方指定标准,不要相信 ActionIndex 那个小婊砸。 93 | 94 | PointId 在手指按下时产生,手指抬起或者事件被取消后消失,是一个事件流程中唯一不变的标识,可以在手指按下时 通过 getPointerId(int pointerIndex) 获得。 (参数中的 pointerIndex 就是 actionIndex) 95 | 96 | #### 历史数据 97 | 由于我们的设备非常灵敏,手指稍微移动一下就会产生一个移动事件,所以移动事件会产生的特别频繁,为了提高效率,系统会将近期的多个移动事件(move)按照事件发生的顺序进行排序打包放在同一个 MotionEvent 中,与之对应的产生了以下方法: 98 | 99 | * getHistorySize() 获取历史事件集合大小 100 | * getHistoricalX(int pos) 获取第pos个历史事件x坐标(pos < getHistorySize()) 101 | * getHistoricalY(int pos) 获取第pos个历史事件y坐标(pos < getHistorySize()) 102 | * getHistoricalX (int pin, int pos) 获取第pin个手指的第pos个历史事件x坐标(pin < getPointerCount(), pos < getHistorySize() ) 103 | * getHistoricalY (int pin, int pos) 获取第pin个手指的第pos个历史事件y坐标(pin < getPointerCount(), pos < getHistorySize() ) 104 | 105 | #### 注意 106 | * pin 全称是 pointerIndex,表示第几个手指,此处为了节省空间使用了缩写。 107 | * 历史数据只有 ACTION_MOVE 事件。 108 | * 历史数据单点触控和多点触控均可以用 109 | #### 伪代码 110 | 111 | ```java 112 | void printSamples(MotionEvent ev) { 113 | final int historySize = ev.getHistorySize(); 114 | final int pointerCount = ev.getPointerCount(); 115 | for (int h = 0; h < historySize; h++) { 116 | System.out.printf("At time %d:", ev.getHistoricalEventTime(h)); 117 | for (int p = 0; p < pointerCount; p++) { 118 | System.out.printf(" pointer %d: (%f,%f)", 119 | ev.getPointerId(p), ev.getHistoricalX(p, h), ev.getHistoricalY(p, h)); 120 | } 121 | } 122 | System.out.printf("At time %d:", ev.getEventTime()); 123 | for (int p = 0; p < pointerCount; p++) { 124 | System.out.printf(" pointer %d: (%f,%f)", 125 | ev.getPointerId(p), ev.getX(p), ev.getY(p)); 126 | } 127 | } 128 | 129 | ``` 130 | #### 获取事件发生的时间 131 | * getDownTime() 获取手指按下时的时间。 132 | * getEventTime() 获取当前事件发生的时间。 133 | * getHistoricalEventTime(int pos) 获取历史事件发生的时间。 134 | 135 | #### 事件分发机制 136 | 事件分发机制有dispatchTouchEvent,onInterceptTouchEvent和onTouchEvent三个方法协助完成,一般处理场景是拦截down事件,然后之后的move,up事件就在该拦截的地方停止 137 | ![](https://upload-images.jianshu.io/upload_images/944365-aea821bbb613c195.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/700) 138 | 139 | -------------------------------------------------------------------------------- /Android/View的工作原理.md: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /Android/动画.md: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /Android/四大组件的工作流程.md: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /Android/理解Windows和WindowManger.md: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /Android/综合技术.md: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /DesignPattern/chapter01 - 面向对象六大原则: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /DesignPattern/chapter02 - 单例模式: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /DesignPattern/chapter03 - Builder模式: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /DesignPattern/chapter04 - 原型模式: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /Http/test.md: -------------------------------------------------------------------------------- 1 | #### java内存区域 2 | * 方法区: 用户存储已经被虚拟机加载的类信息,常量,静态变量,即时编译器编译后的代码等。异常状态有异常状态有OutOfMemoryError 3 | * 常量池: 运行时常量池一般存放在方法区中,用户用于存放编译器生成的各种字面量和符号引用 4 | * 堆内存: 是jvm所管理的内存中最大的一块,唯一的目的就是存放实例对象,几乎所有的实例对象都存放在这里.java堆是垃圾收集器管理的主要区域,异常状态内存溢出 5 | * 虚拟机栈: 描述的是方法执行的内存模型,每个方法在执行的时候都会创建一个栈帧,用户存储局部变量表,操作数栈,动态链接,方法出口等信息 6 | * 本地方法栈:和虚拟机栈发挥的作用相同,但是本地方法执行的是native方法服务 7 | * 程序计数器:一块较小的内存,当前线程所执行的字节码的行号指示器。字节码执行工作的时候就是通过改变这个计数器的值来选取下一个需要执行的字节码指令 8 | 9 | #### java内存模型 10 | ##### java内存模型的目的 11 | 屏蔽掉各种硬件和操作系统的内存访问差异,用来实现让java程序在各种平台下都能达到一直的内存访问效果 12 | java内存模型规定了所有的变量都存储在主内存中,每条线程还有自己的工作线程。线程的工作线程阿訇保存了该线程所有用到的变量,这些变量都是从主内存中读取来的。线程对变量的所有操作都是在工作线程中进行的,不同线程之间也无法执行访问对方线程的变量。 13 | #### 八种操作 14 | * lock 作用于主内存的变量,把一个变量标识为一个线程的独霸状态 15 | * unlock 作用于主内存的变量,把一个处于锁定状态的变量释放出来 16 | * read把一个变量的值从主内存传递到工作内存中去, 17 | * load 把read的到的变量放到工作线程的工作副本中去 18 | * use 把工作线程中一个变量的值传递给执行引擎 19 | * assign 把一个从执行引擎得到的值传递给工作内存 20 | * store 把工作线程中的一个变量传递给主内存 21 | * write 把store工作中得到的值放到主内存的变量中 22 | 23 | 24 | #### http 请求和响应步骤 25 | * 1,建立TCP连接 26 | * 2,web浏览器向web服务器发送请求命令 27 | * 3,web浏览器发送请求头信息 28 | * 4,web浏览器应答 29 | * 5,web浏览器发送应答头信息 30 | * 6,web服务器向浏览器发送数据 31 | * 7,web服务器关闭tcp连接,一旦服务器向服务器发送了数据,就会关闭tcp。如果添加connection:keepAlive。tcp在连接发送后仍然保持打开状态 32 | 33 | #### http 请求报文 34 | * 1,请求行:请求方法,URL,协议版本;请求方法主要有GET,POST。URL=协议+主机+路径+参数 35 | * 2,请求头:请求头部为请求报文添加了一些附加信息,常见的请求头Host,接受请求的服务器地址,USER-Agent发送请求的应用程序名称 36 | * 3:请求数据:可选部分,get没有请求数据 37 | #### http 请求报文 38 | * 1,状态行:协议版本,状态码,状态码描述(状态码 200响应成功,302跳转,跳转的地址通过响应头的location制定,400客户端请求有语法错误,403服务器收到请求但是不想赢,404访问资源不存在,500服务器内部错) 39 | * 2,响应头部 40 | * 3,响应正文用于存放需要返回给客户端的数据 41 | #### https 简介 42 | https其实有两部分组成 http + ssl + tls也就是在http上面加了一层处理加密信息的模块。服务端和客户端的传输都会通过tls进行加密,所以传输的数据都是加密后的数据 43 | 44 | -------------------------------------------------------------------------------- /Http/test2.md: -------------------------------------------------------------------------------- 1 | #### 1.请简述TCP\UDP的区别 2 | tcp和udp都是osi模型中传输层的协议 3 | tcp是可靠的,传送数据无差错,不丢失,面向连接的如打电话之前需要先拨打,面向字节流,效率比较低,全双工,拥塞控制是慢开始,拥塞避免,快重传,快恢复,对准确性要求较高
4 | udp是不可靠的,不需要连接,面向报文,效率比较高,一对一,一对多,多对一,多对多,对效率要求较高,对准确性要求较低。UDP没有拥塞控制,因此网络出现拥塞不会使源主机的发送速率降低(对实时应用很有用,如IP电话,实时视频会议等) 5 | 我们在打ip电话的时候,如果是同tcp的话,数据在传输途中丢失会重发,我们无法流畅的传输通话人的声音,导致无法正常交流,在多播和广播通信中使用udp;TCP的逻辑通信信道是全双工的可靠信道,UDP则是不可靠信道 6 | #### 2.请简单说一下你了解的端口以及对应的服务 7 | ![](https://pic1.zhimg.com/80/v2-e584c505e895441d7b52c8f3c02c9770_hd.jpg) 8 | #### 3.简述TCP的三次握手和四次挥手 9 | ![](https://pic2.zhimg.com/v2-8720bd64871a5452df583fdab8207d64_r.jpg) 10 | ##### 三次握手 11 | ###### 第一次握手,客户端发起连接请求的包文段,将syn的位置设置为1,seq的位置设置为x,然后客户端进入syn_send状态,等待服务端的去额嗯 12 | ###### 第二次握手,服务器收到客户端的报文段之后,需要对这个syn报文段进行确认,设置ack = x+1;同时还要设置自己的syn信息,将syn设置为1,seq设置为y.把上述的所有信息存放到syn+ack报文中,一起发送给客户端,这个时候服务器进入syn_rec状态 13 | ###### 第三次握手,客户端收到syn_ack报文段之后。将ack设置为y+1,seq设置为x+1,向服务器发送ACK报文段,这个报文段设置完毕之后,客户端和服务器就进入了established,完成三次握手; 14 | ##### 四次挥手 15 | 当客户端没有东西要发送的时候,就会发送一个fin为1的没有数据的包文,进入fin——wait状态,服务器收到之后可以给服务端一个确认,这个时候客户端不在发送数据,但是仍然可以接受信息 16 | 客户端收到服务器的确认信息之后进入等待状态,等待服务器请求时放链接,服务端数据发送完成之后就会通知客户端请求释放,客户端收到之后就会回复一个确认信息。等待2msl,最大搬文生存时间,之后服务器关闭 17 | #### 4,描述一次完整的网络请求过程 18 | 域名解析(DNS)——> TCP三次握手,建立连接 ——> 发起HTTP请求 ——> 服务器响应请求,返回数据 ——> 客户端处理数据 ——> 合适时刻四次握手,断开连接 19 | #### GET、POST的区别 20 | 21 | GET请求可以被浏览器缓存,POST不可以 22 | POST安全一些,因为GET请求都在URL中,也会被浏览器保存记录;而POST请求可以放到Body中 23 | POST可以用RequestBody传输更多的数据,GET的数据量受到URL长度限制 24 | POST支持更多编码,且不对数据类型限制 25 | GET的目标功能是查询数据,POST的目标功能是修改数据,或者上传数据 26 | DNS解析过程 27 | 28 | #### DNS功能是将域名解析为IP地址。 29 | 30 | 查找浏览器缓存,是否有解析记录,没有则进入第二步 31 | 查找系统缓存,是否有解析记录,没有则进入第二步 32 | 给配置的DNS服务器(LDNS)发送请求,LDNS查找到则返回 33 | LDNS没有找到时会请求RootServer,返回一个顶级域名服务器 34 | LDNS请求顶级域名服务器,返回NameServer地址 35 | NameServer返回IP给LDNS,LDNS会进行缓存 36 | LDNS返回给用户 37 | 38 | #### 5,Https简介 39 | Https其实是由两部分组成 Http+ssl+tls,也就是在http上又加上一层处理加密信息的模块。服务端和客户端传输的信息都会通过TLS进行加密,所以传输后的数据都是通过加密的。 40 | * 客户端发起Https请求,其实就是https网址,然后连接到server的443端口 41 | * 服务端的配置:采用https的服务器必须要有一套自己的数字证书,可以自己制作,也可以向组织申请。区别就是自己制作的必须要通过客户端的验证,这套证书相当于公匙和私匙。 42 | * 传输证书,相当于传输公匙给服务器,包含了很多信息,如证书的颁发机构,过期时间等 43 | * 客户端解析证书:有客户端的tls完成,客户端解析到公匙之后利用公式对一个随机值进行加密,然后这个随机值就是相当于客户端的私匙了 44 | * 传送加密信息:把通过服务端公匙加密后的随机值传输到服务端,以后客户端和服务端就可以通过这个随机值进行加密和解密了 45 | * 服务端加密信息:服务端使用私匙进行解密,拿到随机值之后,然后把内容和该值进行对称加密,就是把信息和随机值通过某种算法集合在一起,所以这个随机值只有客户端和服务端知道,很安全 46 | * 传输加密后的信息给服务端,把信息传递 47 | * 服务端进行解密:使用随机值新型解密,ojbk 48 | 49 | -------------------------------------------------------------------------------- /Java/Java 反射.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Java反射 3 | date: 2017-4-23 18:58:27 4 | categories: [Java] 5 | tags: [Reflect,Java] 6 | --- 7 | ### 基本概念 8 | JAVA反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意方法和属性;这种动态获取信息以及动态调用对象方法的功能称为java语言的反射机制。 9 | 10 | ### 基本功能 11 | * 在运行时候判断任意对象所属的类 12 | * 在运行时候构造任意一个对象 13 | * 在运行时候判断任意 一个类具有的成员变量和方法 14 | * 在运行时调用任意一个对象的方法 15 | * 生成动态代理 16 | 17 | ### 基本运用 18 | #### 1.获得class(3种) 19 | 20 | * 使用Class类的forName(String clazzName)静态方法,改方法需要传入字符串参数,该字符串的参数的值是某个类的全名(eg:cn.edu.nuc.Test) 21 | * 调用每个类的class属性来获取该类对应的Class对象 22 | * 调用每个对象的getClass()方法,该类是Java.lang.Object的一个方法 23 | 24 | ```java 25 | //第一种方式 26 | Class mClass=Class.forName("cn.edu.nuc.People"); 27 | System.out.println(mClass.getName()); 28 | 29 | //第二种方式 30 | Class mClass2=People.class; 31 | System.out.println(mClass2.getName()); 32 | 33 | //第三种方式 34 | People mPeople=new People("dreamY",18); 35 | Class mClass1=mPeople.getClass(); 36 | System.out.println(mClass1.getName()); 37 | 38 | ``` 39 | ``` 40 | D:\java\jdk\bin\java 41 | cn.edu.nuc.People 42 | cn.edu.nuc.People 43 | cn.edu.nuc.People 44 | 45 | Process finished with exit code 0 46 | 47 | ``` 48 | #### 2.创建实例(主要两种) 49 | * 使用Class对象的newInstance方法来创建Class对象对应的实例(只可以用来创建无参数的,如果含有参数,不能采取这种方法) 50 | * 通过Class对象获取制定的Constuctor对象,再通过Constructor对象的newInstance()方法来创建实例,这种方法可以用制定的构造器构造类的实例 51 | 52 | ```java 53 | 54 | //第一种 55 | Class mClass=Class.forName("cn.edu.nuc.People"); 56 | People mPeople= (People) mClass.newInstance(); 57 | mPeople.setAge(18); 58 | System.out.println(mPeople.getAge()); 59 | 60 | //第二种 61 | Constructor mConstructor=mClass.getConstructor(String.class,int.class);//获取制定参数类型的构造器 62 | People mPeople1= (People) mConstructor.newInstance("dreamY",18); 63 | System.out.println(mPeople1.getAge()+mPeople1.getName()); 64 | 65 | 66 | ``` 67 | ``` 68 | D:\java\jdk\bin\java 69 | 18 70 | 18dreamY 71 | 72 | Process finished with exit code 0 73 | 74 | ``` 75 | 76 | #### 3.获取方法 77 | 以下所有结果以该程序为基础 78 | ```java 79 | public class Student { 80 | public Student() { 81 | 82 | } 83 | 84 | public void eat(int mI){ 85 | System.out.println(mI); 86 | 87 | } 88 | public void say(){ 89 | 90 | 91 | } 92 | private void shengao(){ 93 | 94 | } 95 | protected void tizhong(){ 96 | 97 | 98 | } 99 | } 100 | 101 | ``` 102 | * getDeclaredMethods()方法返回类或接口声明的所有方法,包括公共、保护、默认(包)访问和私有方法,但不包括继承的方法。 103 | 104 | ```java 105 | Class mClass=Student.class; 106 | Method[]mMethods= mClass.getDeclaredMethods(); 107 | for (Method mMethod:mMethods) { 108 | System.out.println(mMethod); 109 | } 110 | ``` 111 | ``` 112 | D:\java\jdk\bin\java 113 | public void cn.edu.nuc.Student.eat(int) 114 | public void cn.edu.nuc.Student.say() 115 | private void cn.edu.nuc.Student.shengao() 116 | protected void cn.edu.nuc.Student.tizhong() 117 | 118 | Process finished with exit code 0 119 | 120 | ``` 121 | 122 | * getMethods()方法返回某个类的所有公用(public)方法,包括其继承类的公用方法。 123 | 124 | ```java 125 | Class mClass=Student.class; 126 | Method[]mMethods= mClass.getMethods(); 127 | for (Method mMethod:mMethods) { 128 | System.out.println(mMethod.getName()); 129 | } 130 | ``` 131 | ``` 132 | D:\java\jdk\bin\java 133 | public void cn.edu.nuc.Student.eat(int) 134 | public void cn.edu.nuc.Student.say() 135 | public final void java.lang.Object.wait() throws java.lang.InterruptedException 136 | public final void java.lang.Object.wait(long,int) throws java.lang.InterruptedException 137 | public final native void java.lang.Object.wait(long) throws java.lang.InterruptedException 138 | public boolean java.lang.Object.equals(java.lang.Object) 139 | public java.lang.String java.lang.Object.toString() 140 | public native int java.lang.Object.hashCode() 141 | public final native java.lang.Class java.lang.Object.getClass() 142 | public final native void java.lang.Object.notify() 143 | public final native void java.lang.Object.notifyAll() 144 | 145 | Process finished with exit code 0 146 | 147 | ``` 148 | * getMethod方法返回一个特定的方法,其中第一个参数为方法名称,后面的参数为方法的参数对应Class的对象 149 | 150 | ```java 151 | Method mMethod=mClass.getMethod("eat",int.class); 152 | System.out.println(mMethod.getName()); 153 | 154 | ``` 155 | ``` 156 | D:\java\jdk\bin\java 157 | public void cn.edu.nuc.Student.eat(int) 158 | 159 | Process finished with exit code 0 160 | ``` 161 | #### 4.获取构造器信息 162 | 获取类构造器的用法与上述获取方法的用法类似。主要是通过Class类的getConstructor方法得到Constructor类的一个实例,而Constructor类有一个newInstance方法可以创建一个对象实例: 163 | 164 | ```java 165 | public T newInstance(Object ... initargs) 166 | ``` 167 | 可以根据传入的参数来调用对应的构造方法 168 | #### 5.获取类的成员变量信息 169 | * getFiled: 访问公有的成员变量 170 | * getDeclaredField:访问类的所有成员变量属性,包括继承的,实现的父类的所有属性 171 | * getFileds: 访问类的所有公有成员变量属性,包括继承的共有属性
172 |
173 | Field提供了两组方法来读取或设置成员变量的值: 174 | getXXX(Object obj):获取obj对象的该成员变量的值。此处的XXX对应8种基本类型。如果该成员变量的类型是引用类型,则取消get后面的XXX。 175 | setXXX(Object obj,XXX val):将obj对象的该成员变量设置成val值。 176 | 参考上面的getMethod和getDeclaredMethods定义 177 | 178 | ```java 179 | //生成新的对象:用newInstance()方法 180 | Object obj = mClass.newInstance(); 181 | //获取age成员变量 182 | Field field = mClass.getField("age"); 183 | //将obj对象的age的值设置为10 184 | field.setInt(obj, 10); 185 | //获取obj对象的age的值 186 | field.getInt(obj); 187 | ``` 188 | 189 | #### 6.调用方法 190 | 当我们从类中获取了一个方法后,我们就可以用invoke()方法来调用这个方法。invoke方法的原型为: 191 | 192 | ```java 193 | //第一个参数为实例化对象,第二个为参数 194 | public Object invoke(Object obj, Object... args) 195 | throws IllegalAccessException, IllegalArgumentException, 196 | InvocationTargetException 197 | ``` 198 | ```java 199 | Method mMethod=mClass.getMethod("eat",int.class); 200 | mMethod.invoke(mStudent,18); 201 | ``` 202 | ``` 203 | D:\java\jdk\bin\java 204 | 18 205 | 206 | Process finished with exit code 0 207 | ``` 208 | 当通过Method的invoke()方法来调用对应的方法时,Java会要求程序必须有调用该方法的权限。如果程序确实需要调用某个对象的private方法,则可以先调用Method对象的如下方法。 209 | setAccessible(boolean flag):将Method对象的acessible设置为指定的布尔值。值为true,指示该Method在使用时应该取消Java语言的访问权限检查;值为false,指示该Method在使用时要实施Java语言的访问权限检查。 210 | 211 | #### 实例化泛型 212 | 比如当我们遇到这样的情况 213 | ```java 214 | public abstract class Base

{ 215 | } 216 | ``` 217 | 我们想去用一个类继承这个Base,在Base中完成实例化P和M,我们可以借助反射去实现() 218 | ```java 219 | 220 | protect P p; 221 | protect M m; 222 | p=getT(this,0); 223 | m=getT(this,1); 224 | public static T getT(Object mO,int index){ 225 | 226 | try { 227 | return ((Class)((ParameterizedType)mO.getClass().getGenericSuperclass()) 228 | .getActualTypeArguments()[index]) 229 | .newInstance(); 230 | } catch (InstantiationException mE) { 231 | mE.printStackTrace(); 232 | } catch (IllegalAccessException mE) { 233 | mE.printStackTrace(); 234 | } 235 | 236 | return null; 237 | } 238 | 239 | ``` 240 | getGenericSuperclass() 通过反射获取当前类表示的实体(类,接口,基本类型或void)的直接父类的Type,getActualTypeArguments()返回参数数组 241 | ### 反射的优缺点 242 | 优点:
243 | (1)能够运行时动态获取类的实例,大大提高系统的灵活性和扩展性。
244 | (2)与Java动态编译相结合,可以实现无比强大的功能
245 | 缺点:
246 | (1)使用反射的性能较低
247 | (2)使用反射相对来说不安全
248 | (3)破坏了类的封装性,可以通过反射获取这个类的私有方法和属性
249 | 250 | 251 | 252 | 253 | 254 | -------------------------------------------------------------------------------- /Java/java String.md: -------------------------------------------------------------------------------- 1 | [string常用的API](http://www.apihome.cn/api/java/String.html) 2 | [原文链接string中常见的10个问题](http://www.programcreek.com/2013/09/top-10-faqs-of-java-strings/) 3 | 4 | #### 1. 字符串比较,使用 "==" 还是 equals() ? 5 | 简单来说, "==" 判断两个引用的是不是同一个内存地址(同一个物理对象). 6 | 而 equals 判断两个字符串的值是否相等. 7 | 除非你想判断两个string引用是否同一个对象,否则应该总是使用 equals()方法. 8 | 如果你了解 字符串的驻留 ( String Interning ) 则会更好地理解这个问题 9 | 10 | #### 2. 对于敏感信息,为何使用char[]要比String更好? 11 | String是不可变对象, 意思是一旦创建,那么整个对象就不可改变. 即使新手觉得String引用变了,实际上只是(指针)引用指向了另一个(新的)对象. 12 | 而程序员可以明确地对字符数组进行修改,因此敏感信息(如密码)不容易在其他地方暴露(只要你用完后对char[]置0). 13 | 14 | #### 3. 在switch语句中使用String作为case条件? 15 | 从 JDK7 开始,这是可以的,啰嗦一句,Java 6 及以前的版本都不支持这样做. 16 | ```java 17 | // 只在java 7及更高版本有效! 18 | switch (str.toLowerCase()) { 19 | case "a": 20 | value = 1; 21 | break; 22 | case "b": 23 | value = 2; 24 | break; 25 | } 26 | ``` 27 | #### 4. 转换String为数字 28 | 对于非常大的数字请使用Long,代码如下 29 | ```java 30 | int age = Integer.parseInt("10"); 31 | long id = Long.parseLong("190"); // 假如值可能很大. 32 | ``` 33 | #### 5. 如何通过空白字符拆分字符串 34 | String 的 split()方法接收的字符串会被当做正则表达式解析, 35 | "\s"代表空白字符,如空格" ",tab制表符"\t", 换行"\n",回车"\r". 36 | 而编译器在对源代码解析时,也会进行一次字面量转码,所以需要"\\s". 37 | ```java 38 | String[] strArray = aString.split("\\s+"); 39 | ``` 40 | 41 | #### 6. substring() 方法内部是如何处理的? 42 | 在JDK6中,substring()方法还是共用原来的char[]数组,通过偏移和长度构造了一个"新"的String。 43 | 想要substring()取得一个全新创建的对象,使用如下这种方式: 44 | ```java 45 | String sub = str.substring(start, end) + ""; 46 | 47 | ``` 48 | "hamburger".substring(4, 8) returns "urge"
49 | "smiles".substring(1, 5) returns "mile
50 | 51 | 当然 Java 7 中,substring()创建了一个新的char[] 数组,而不是共用. 52 | 想要了解更多,请参考: JDK6和JDK7中substring()方法及其差异 53 | 54 | #### 7. String vs StringBuilder vs StringBuffer 55 | StringBuilder 是可变的,因此可以在创建以后修改内部的值. 56 | StringBuffer 是同步的,因此是线程安全的,但效率相对更低. 57 | 58 | 59 | #### 8. 如何重复拼接同一字符串? 60 | 方案1: 使用Apache Commons Lang 库的 StringUtils 工具类. 61 | ```java 62 | String str = "abcd"; 63 | String repeated = StringUtils.repeat(str,3);//abcdabcdabcd 64 | ``` 65 | 66 | 方案2: 67 | 使用 StringBuilder 构造. 更灵活. 68 | ```java 69 | String src = "name"; 70 | int len = src.length(); 71 | int repeat = 5; 72 | StringBuilder builder = new StringBuilder(len * repeat); 73 | for(int i=0; i当Java运行时系统得到一个异常对象时,他将会沿着方法的`调用栈`逐层回溯,寻找处理这一异常的代码。找到能够处理这种类型的异常的方法后,运行时系统把当前的异常对象交给这个异常方法后,这一过程称为捕获(catch)异常。如果Java运行时系统找不到可以捕获异常的方法,则运行时系统中将终止,相应的Java程序也将退出。 6 | * 声明抛弃异常:将异常抛出方法之外,由调用该方法的环境去处理 `//消极的处理方式` 7 | >如果在一个方法中生成了一个异常,但是这一方法并不确切地知道该如何对这一异常事件进行处理,这时,一个方法就应该声明抛弃异常,使得异常对象可以从调用栈向后传播,直到有合适的方法捕获它为止。 8 | ## Java中预定义的异常类 9 | ![预定义的异常类](http://img.blog.csdn.net/20170323190427885?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvSm9raTIzMw==/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast) 10 | ### Error 11 | Error标识不可能或难以恢复的严重问题,例如内存不足,程序一般不处理这类情况。 12 | ### RuntimeException 13 | RuntimeException指示设计或实现上的问题,如果程序正确运行,这样的情况是不应该出现的。 14 | #### 常见异常 15 | * NullPointException--空指针异常 16 | * ArrayIndexOutOfBoundsException--数据越界异常 17 | * NegativeArraySizeException--数组负下标异常 18 | * ArithmeticException--算数异常类 19 | * ClassCastException--算数运算异常 20 | * IllegalArgumentException--传递非法参数异常 21 | * ArrayStoreException--向数组中存放与数组类型不符元素异常 22 | * NumberFormatException--数字格式异常 23 | * SecurityException--安全异常 24 | * UnsupportedOperationException--不支持的操作异常 25 | ### try-catch语句 26 | ```Java 27 | try{ 28 | //打开文件 29 | //判断大小 30 | //分配内存 31 | //读入内存 32 | //关掉文件 33 | }catch(/*文件打开失败*/){ 34 | //处理代码 35 | }catch(/*大小取值失败*/){ 36 | //处理代码 37 | }catch(/*内存分配失败*/){ 38 | //处理代码 39 | }catch(/*读取失败*/){ 40 | //处理代码 41 | }catch(/*关闭文件失败*/){ 42 | //处理代码 43 |    }finally{ 44 |    //总是执行的代码,即使碰到return也执行finally后才return,除非遇到System.exit(),程序会立刻退出 45 | } 46 | ``` 47 | ### throw/throws抛出异常 48 | ```Java 49 | //抛出的对象必须是Throwable的子类 50 | public int read () throws IOException{ 51 | ...... 52 | } 53 | 54 | public static void main(String args[]) throws IOException, IndexOutOfBoundsException { 55 |                ······ 56 | } 57 | ``` 58 | ### 堆栈调用机制 59 | * 如果一个try-catch块中没有处理,那么将会抛向此方法的调用者 60 | * 如果一个异常回到main方法,而且也没有处理,那么程序终将终止 61 | ![堆栈处理机制](http://img.blog.csdn.net/20170323211705302?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvSm9raTIzMw==/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast) 62 | ## 自定义异常类 63 | ```Java 64 | public class MydateException extends Exception{ 65 | private String reason; 66 | public MydateException(String r){ 67 | reason = r; 68 | } 69 | public String getReason(){ 70 | return reason; 71 | } 72 | } 73 | 74 | public class Mydate { 75 | int year,month,day; 76 | void setDate(int year,int month,int day) throws MydateException{ 77 | if(day>31) 78 | throw new MydateException("day too big"); 79 | this.year = year; 80 | this.month = month; 81 | this.day = day; 82 | } 83 | public static void main(String[] args){ 84 | Mydate t = new Mydate(); 85 | try { 86 | t.setDate(2001,1,100); 87 | }catch (MydateException e){ 88 | System.out.println(e.getReason()); 89 | } 90 | } 91 | } 92 | ``` 93 | -------------------------------------------------------------------------------- /Java/java基础知识.md: -------------------------------------------------------------------------------- 1 | ### 1、作用域public,private,protected,以及不写时的区别 2 | 3 | | 作用域 | 当前类 | 同一package |子孙类 |其他package| 4 | | :------------ |:---------------:|:---------------:|:---------------:|:---------------:| 5 | | public | √ | √ |√|√| 6 | | protected | √ |√| √| ×| 7 | | friendly | √ | √ |×|×| 8 | | private | √|× |×|×| 9 | 10 | 11 | 12 | ### 2、Anonymous Inner Class (匿名内部类) 是否可以extends(继承)其它类,是否可以implements(实现)interface(接口) 13 | 答:匿名的内部类是没有名字的内部类。不能extends(继承) 其它类,但一个内部类可以作为一个接口,由另一个内部类实现 14 | ### 3、Static Nested Class 和 Inner Class的不同 15 | 答:Nested Class (一般是C++的说法),Inner Class (一般是JAVA的说法)。Java内部类与C++嵌套类最大的不同就在于是否有指向外部的引用上。注: 静态内部类(Inner Class)意味着1创建一个static内部类的对象,不需要一个外部类对象,2不能从一个static内部类的一个对象访问一个外部类对象 16 | ### 4、&和&&的区别 17 | 答:&是位运算符,表示按位与运算,&&是逻辑运算符,表示逻辑与(and 18 | ### 5、Collection 和 Collections的区别 19 | 答:Collection是集合类的上级接口,继承与他的接口主要有Set 和List. Collections是针对集合类的一个帮助类,他提供一系列静态方法实现对各种集合的搜索、排序、线程安全化等操作 20 | ### 6、序列化与反序列化的作用: 21 | 22 | 对象的序列化主要有两种用途:
23 | 1) 把对象的字节序列永久地保存到硬盘上,通常存放在一个文件中;
24 | 2) 在网络上传送对象的字节序列。
25 | 26 | 27 | 28 | 因为不对对象序列化的化容易出现很多问题,所以引入了序列化解决了这些问题。
29 | 30 | 31 | 32 | 对象序列化包括如下步骤:
33 | 1) 创建一个对象输出流,它可以包装一个其他类型的目标输出流,如文件输出流;
34 | 2) 通过对象输出流的writeObject()方法写对象。
35 | 对象反序列化的步骤如下:
36 | 1) 创建一个对象输入流,它可以包装一个其他类型的源输入流,如文件输入流;
37 | 2) 通过对象输入流的readObject()方法读取对象。
38 | 下面让我们来看一个对应的例子,类的内容如下:
39 | 40 | 41 | 42 | serialVersionUID作用:
43 | 序列化时为了保持版本的兼容性,即在版本升级时反序列化仍保持对象的唯一性。
44 | 有两种生成方式:
45 | 一个是默认的1L,比如:private static final long serialVersionUID = 1L;
46 | 一个是根据类名、接口名、成员方法及属性等来生成一个64位的哈希字段,比如:
47 | private static final long serialVersionUID = xxxxL;
48 | 49 | 当你一个类实现了Serializable接口,如果没有定义serialVersionUID,Eclipse会提供这个提示功能告诉你去定义 。
50 | ### 7、final, finally, finalize的区别。 51 |   final 用于声明属性,方法和类,分别表示属性不可变,方法不可覆盖,类不可继承。 52 | finally是异常处理语句结构的一部分,表示总是执行。 53 | ### 8、final 54 | * 根据程序上下文环境,Java关键字final有“这是无法改变的”或者“终态的”含义,它可以修饰非抽象类、非抽象类成员方法和变量。你可能出于两种理解而需要阻止改变:设计或效率。 55 | * final类不能被继承,没有子类,final类中的方法默认是final的。 56 | * final方法不能被子类的方法覆盖,但可以被继承。 57 | * final成员变量表示常量,只能被赋值一次,赋值后值不再改变。 58 | * final不能用于修饰构造方法。 59 | * 注意:父类的private成员方法是不能被子类方法覆盖的,因此private类型的方法默认是final类型的。 60 | 61 | ####final类 62 | final类不能被继承,因此final类的成员方法没有机会被覆盖,默认都是final的。在设计类时候,如果这个类不需要有子类,类的实现细节不允许改变,并且确信这个类不会载被扩展,那么就设计为final类。 63 | ####final方法 64 | 如果一个类不允许其子类覆盖某个方法,则可以把这个方法声明为final方法。 65 | 使用final方法的原因有二: 66 | 第一、把方法锁定,防止任何继承类修改它的意义和实现。 67 | 第二、高效。编译器在遇到调用final方法时候会转入内嵌机制,大大提高执行效率。 68 | ####final变量(常量) 69 | 用final修饰的成员变量表示常量,值一旦给定就无法改变! 70 | final修饰的变量有三种:静态变量、实例变量和局部变量,分别表示三种类型的常量。 71 | 从下面的例子中可以看出,一旦给final变量初值后,值就不能再改变了。 72 | 另外,final变量定义的时候,可以先声明,而不给初值,这中变量也称为final空白,无论什么情况,编译器都确保空白final在使用之前必须被初始化。但是,final空白在final关键字final的使用上提供了更大的灵活性,为此,一个类中的final数据成员就可以实现依对象而有所不同,却有保持其恒定不变的特征。 73 | ####final参数 74 | 当函数参数为final类型时,你可以读取使用该参数,但是无法改变该参数的值 75 | 二、static 76 | 77 | * static表示“全局”或者“静态”的意思,用来修饰成员变量和成员方法,也可以形成静态static代码块,但是Java语言中没有全局变量的概念。 78 | 79 | * 被static修饰的成员变量和成员方法独立于该类的任何对象。也就是说,它不依赖类特定的实例,被类的所有实例共享。只要这个类被加载,Java虚拟机就能根据类名在运行时数据区的方法区内定找到他们。因此,static对象可以在它的任何对象创建之前访问,无需引用任何对象。 80 | 81 | * 用public修饰的static成员变量和成员方法本质是全局变量和全局方法,当声明它类的对象市,不生成static变量的副本,而是类的所有实例共享同一个static变量。 82 | 83 | * static变量前可以有private修饰,表示这个变量可以在类的静态代码块中,或者类的其他静态成员方法中使用(当然也可以在非静态成员方法中使用--废话),但是不能在其他类中通过类名来直接引用,这一点很重要。实际上你需要搞明白,private是访问权限限定,static表示不要实例化就可以使用,这样就容易理解多了。static前面加上其它访问权限关键字的效果也以此类推。 84 | 85 | * static修饰的成员变量和成员方法习惯上称为静态变量和静态方法,可以直接通过类名来访问,访问语法为: 86 | 类名.静态方法名(参数列表...) 87 | 类名.静态变量名 88 | 用static修饰的代码块表示静态代码块,当Java虚拟机(JVM)加载类时,就会执行该代码块(用处非常大,呵呵)。 89 | 90 | #### 1、static变量 91 | 按照是否静态的对类成员变量进行分类可分两种:一种是被static修饰的变量,叫静态变量或类变量;另一种是没有被static修饰的变量,叫实例变量。两者的区别是: 92 | 对于静态变量在内存中只有一个拷贝(节省内存),JVM只为静态分配一次内存,在加载类的过程中完成静态变量的内存分配,可用类名直接访问(方便),当然也可以通过对象来访问(但是这是不推荐的)。 93 | 对于实例变量,没创建一个实例,就会为实例变量分配一次内存,实例变量可以在内存中有多个拷贝,互不影响(灵活)。 94 | 95 | #### 2、静态方法 96 | 静态方法可以直接通过类名调用,任何的实例也都可以调用,因此静态方法中不能用this和super关键字,不能直接访问所属类的实例变量和实例方法(就是不带static的成员变量和成员成员方法),只能访问所属类的静态成员变量和成员方法。因为实例成员与特定的对象关联!这个需要去理解,想明白其中的道理,不是记忆!!! 97 | 因为static方法独立于任何实例,因此static方法必须被实现,而不能是抽象的abstract。 98 | ### static和final一块用表示什么 99 | static final用来修饰成员变量和成员方法,可简单理解为“全局常量”! 100 | 对于变量,表示一旦给值就不可修改,并且通过类名可以访问。 101 | 对于方法,表示不可覆盖,并且可以通过类名直接访问。 102 | 103 | 特别要注意一个问题: 104 | 对于被static和final修饰过的实例常量,实例本身不能再改变了,但对于一些容器类型(比如,ArrayList、HashMap)的实例变量,不可以改变容器变量本身,但可以修改容器中存放的对象,这一点在编程中用到很多。 105 | 106 | ### 如果要对一个特别大的(如100位)数进行相加,在java中如何计算: 107 | [相关链接](http://ly5633.iteye.com/blog/1218724) 108 | 在Java中针对比较大的数字,有大数类型来进行表示。即BigInteger和BigDecimal两个类。 109 | 以BigDecimal为例: 110 | ```java 111 | BigDecimal bigDecimalA = new BigDecimal("1234567890123456789012345678901"); 112 | BigDecimal bigDecimalB = new BigDecimal("1234567890123456789012345678902"); 113 | // 加 + 114 | bigDecimalA = bigDecimalA.add(bigDecimalB); 115 | // 减 - 116 | bigDecimalA = bigDecimalA.subtract(bigDecimalB); 117 | // 乘 * 118 | bigDecimalA = bigDecimalA.multiply(bigDecimalB); 119 | // 除 / 120 | bigDecimalA = bigDecimalA.divide(bigDecimalB); 121 | ``` 122 | // ......其他的类似,API里很详细,不再赘述了。 123 | -------------------------------------------------------------------------------- /Java/java多线程.md: -------------------------------------------------------------------------------- 1 | 2 | ## 多线程的安全问题 3 | ```java 4 | class Ticket implements Runnable{ 5 | private int ticket =100; 6 | public void run(){ 7 | while(true){ 8 | if(ticket>0){ 9 | System.out.System.out.println(ticket--); 10 | } 11 | } 12 | } 13 | 14 | } 15 | ``` 16 | #### 问题的原因 17 | 当多个线程同时获取获取cpu执行权的时候,都会执行ticket--;多条语句在操作同一个线程的时候,一个线程堆多条语句只执行了一部分,还没有执行完,另一个线程参与进来,导致共享数据 18 | #### 解决办法 19 | 对于多条操作共享的数据的时候,只能让一个线程执行完,其他线程不可以参加执行 20 | #### java对于多线程的安全问题提供了解决方案 21 | 就是同步代码块 22 | synchronized(对象){ 23 | 需要被同步的代码 24 | } 25 | 可以重入,一个线程获取了锁之后,在当前类的其他方法中也能获取锁,若果出现异常,锁和会自动释放。同步不具有继承性 26 | #### 对象(监视器,锁) 27 | 判断的条件,当线程获得执行权之后执行同步代码,进入之后讲对象关闭。直到上一个线程执行完同步代码。对象打开,这个时候各个线程又开始争取执行权。eg:厕所的门把手;改之后的代码如下: 28 | 29 | ```java 30 | class Ticket implements Runnable{ 31 | private int ticket =100; 32 | Object obj=new Object(); 33 | public void run(){ 34 | while(true){ 35 | synchronized (obj) { 36 | if(ticket>0){ 37 | System.out.System.out.println(ticket--); 38 | } 39 | } 40 | } 41 | } 42 | 43 | } 44 | ``` 45 | #### 同步的前提: 46 | * 必须要有两个或者两个以上的线程 47 | * 必须多个线程使用同一个锁 48 | * 必须保证同步中有一个线程在运行 49 | 50 | #### 好处 :解决多线程同步问题 51 | #### 弊端 :每次都在判定锁,消耗了资源 52 | ## 生产者消费者问题 53 | ```java 54 | /** 55 | * 生产者 56 | */ 57 | public class Product{ 58 | private Condition condition; 59 | private ReentrantLock reentrantLock; 60 | 61 | public Product(ReentrantLock reentrantLock,Condition condition) { 62 | super(); 63 | this.condition = condition; 64 | this.reentrantLock = reentrantLock; 65 | } 66 | public void setValue(){ 67 | try { 68 | reentrantLock.lock(); 69 | while (!StringObject.value.equals("")){ 70 | condition.await(); 71 | } 72 | String value = System.currentTimeMillis()+""+System.nanoTime(); 73 | System.out.println(Thread.currentThread().getName()+"set value = "+value); 74 | StringObject.value = value; 75 | condition.signalAll(); 76 | 77 | } catch (InterruptedException e) { 78 | e.printStackTrace(); 79 | }finally { 80 | reentrantLock.unlock(); 81 | } 82 | } 83 | } 84 | /** 85 | * 消费者 86 | */ 87 | public class Consumer { 88 | private ReentrantLock reentrantLock; 89 | private Condition condition; 90 | 91 | public Consumer(ReentrantLock reentrantLock, Condition condition) { 92 | this.reentrantLock = reentrantLock; 93 | this.condition = condition; 94 | } 95 | public void getValue(){ 96 | try { 97 | reentrantLock.lock(); 98 | while (StringObject.value.equals("")){ 99 | condition.await(); 100 | } 101 | System.out.println(Thread.currentThread().getName()+"get value = "+StringObject.value); 102 | StringObject.value = ""; 103 | condition.signalAll(); 104 | } catch (InterruptedException e) { 105 | e.printStackTrace(); 106 | } finally { 107 | reentrantLock.unlock(); 108 | } 109 | 110 | } 111 | } 112 | public class ConThread extends Thread { 113 | private Consumer consumer; 114 | 115 | public ConThread(Consumer consumer) { 116 | this.consumer = consumer; 117 | } 118 | 119 | @Override 120 | public void run() { 121 | while (true){ 122 | consumer.getValue(); 123 | } 124 | } 125 | } 126 | public class ProThread extends Thread { 127 | private Product p; 128 | public ProThread(Product p){ 129 | super(); 130 | this.p = p; 131 | } 132 | @Override 133 | public void run() { 134 | while (true){ 135 | p.setValue(); 136 | } 137 | } 138 | } 139 | 140 | public class Client { 141 | public static void main(String[] args) { 142 | ReentrantLock reentrantLock = new ReentrantLock(); 143 | Condition condition = reentrantLock.newCondition(); 144 | 145 | for (int i = 0; i < 3 ; i++) { 146 | ConThread conThread = new ConThread(new Consumer(reentrantLock,condition)); 147 | ProThread proThread = new ProThread(new Product(reentrantLock,condition)); 148 | 149 | conThread.start(); 150 | proThread.start(); 151 | } 152 | } 153 | } 154 | 155 | ``` 156 | ###### 这里是多生产多消费的代码,注意的地方使用signalAll而不是signa,如果是单生产单消费的话不用注意这个问题,但是多生产的话如果不适用All则会造成假死,由于当前生产线程有好多,在生产完一个之后唤醒了下一个生产者线程接着等待,导致所有的生产者线程都处于等待状态,消费者线程也会有同样的问题,所以造成了假死。使用while的原因是因为如果两个线程在wait之后被唤醒会继续往下执行,会发生越界异常 157 | 158 | -------------------------------------------------------------------------------- /Java/java注解.md: -------------------------------------------------------------------------------- 1 | 2 | ### 概念 3 | java提供了一种原程序中的元素关联任何信息和任何元数据的途径和方法 4 | 5 | 6 | 7 | ### Java中常见的注解 8 | #### jdk注解 9 | * @Override覆盖父类的方法 10 | * @Deprecated过时的方法 11 | * @SuppressWarnings("deprecation")对过时的方法进行描述 12 | 13 | ### 注解的分类 14 | #### 按照运行机制来分 15 | * 源码注解 注解只存在在源码中,编译成.class文件就不存在了 16 | * 编译时注解 注解在源码和.class都存在的注解(jdk的注解) 17 | * 运行时注解 在运行阶段还起作用,甚至会影响运行逻辑 18 | 19 | #### 按照来源来分 20 | * 来自jdk的注解 21 | * 来自第三方的注解 22 | * 自己定义的注解 23 | 24 | ### 自定义注解 25 | #### 语法要求 26 | ```java 27 | //@interface 进行注解的定义 28 | public @interface Description { 29 | 30 | //成员以无参无异常形式声明,这里并不是方法 31 | String desc(); 32 | 33 | String author(); 34 | //给成员定义默认的值 35 | int age()default 18; 36 | 37 | } 38 | ``` 39 | * 成员类型是受限制的,合法的类型包括原始类型和String,Class,Annotation,Enumeration 40 | * 如果注解只有一个成员,则成员必须取名为value(),在使用时候可以忽略成员名和复制号(=) 41 | * 注解类可以没有成员,没有成员的注解称为标识注解 42 | 43 | #### 元注解 44 | ##### @Target()注解的定义域 45 | * ElementType.CONSTRUCTOR 构造方法声明 46 | * ElementType.FIELD 字段声明 47 | * ElementType.LOCAL_VARABLE 局部变量声明 48 | * ElementType.METHOD 方法声明 49 | * ElementType.PACKAGE 包声明 50 | * ElementType.PARAMETER 参数声明 51 | * ElementType.TYPE 类,接口 52 | 53 | ##### @Retention() 54 | * RetentionPolicy.SOURCE 只在源码显示,编译时会丢弃 55 | * Retention.CLASS 编译时会记录到class中,运行时候忽略 56 | * RetentionPolicy.RUNTIME 运行时候存在,可以通过反射读取 57 | 58 | ##### @Inherited() 59 | 允许子类继承 实现接口继承没有用,只能是class,而且只能继承类名上面的注解 60 | 61 | ##### @Documented 62 | 生成Javadoc时包含注解 63 | 64 | #### 使用自定义注解的语法 65 | @<注解名>(<成员名1>=<成员值1>,<成员名2>=<成员值2>,........)
66 | @Description(desc = "hello",author = "world",age = 18) 67 | 68 | ### java8和注解 69 | 70 | * @Repeatable 71 | 说明该注解标识的注解可以多次使用到同一个元素的声明上。 看一个使用的例子。首先我们创造一个能容纳重复的注解的容器: 72 | 73 | ```java 74 | \ 75 | /** 76 | * Container for the {@link CanBeRepeated} Annotation containing a list of values 77 | */ 78 | @Retention( RetentionPolicy.RUNTIME ) 79 | @Target( ElementType.TYPE_USE ) 80 | public @interface RepeatedValues 81 | { 82 | CanBeRepeated[] value(); 83 | } 84 | ``` 85 | 接着,创建注解本身,然后标记@Repeatable 86 | 87 | ```java 88 | @Retention( RetentionPolicy.RUNTIME ) 89 | @Target( ElementType.TYPE_USE ) 90 | @Repeatable( RepeatedValues.class ) 91 | public @interface CanBeRepeated 92 | { 93 | String value(); 94 | } 95 | ``` 96 | 最后,我们可以这样重复地使用: 97 | 98 | ```java 99 | @CanBeRepeated( "the color is green" ) 100 | @CanBeRepeated( "the color is red" ) 101 | @CanBeRepeated( "the color is blue" ) 102 | public class RepeatableAnnotated 103 | { 104 | 105 | } 106 | ``` 107 | * 自Java8开始,我们可以在类型上使用注解。由于我们在任何地方都可以使用类型,包括 new操作符,casting,implements,throw等等。注解可以改善对Java代码的分析并且保证更加健壮的类型检查。这个例子说明了这一点: 108 | 109 | ```java 110 | @SuppressWarnings( "unused" ) 111 | public static void main( String[] args ) 112 | { 113 | // type def 114 | @TypeAnnotated 115 | String cannotBeEmpty = null; 116 | 117 | // type 118 | List<@TypeAnnotated String> myList = new ArrayList(); 119 | 120 | // values 121 | String myString = new @TypeAnnotated String( "this is annotated in java 8" ); 122 | 123 | } 124 | // in method params 125 | public void methodAnnotated( @TypeAnnotated int parameter ) 126 | { 127 | System.out.println( "do nothing" ); 128 | ``` 129 | 130 | * @FunctionalInterface: 131 | 132 | 这个注解表示一个函数式接口元素。函数式接口是一种只有一个抽象方法(非默认)的接口。编译器会检查被注解元素,如果不符,就会产生错误。例子如下: 133 | 134 | 135 | ```java 136 | 137 | // implementing its methods 138 | @SuppressWarnings( "unused" ) 139 | MyCustomInterface myFuncInterface = new MyCustomInterface() 140 | { 141 | 142 | @Override 143 | public int doSomething( int param ) 144 | { 145 | return param * 10; 146 | } 147 | }; 148 | 149 | // using lambdas 150 | @SuppressWarnings( "unused" ) 151 | MyCustomInterface myFuncInterfaceLambdas = ( x ) -> ( x * 10 ); 152 | } 153 | 154 | @FunctionalInterface 155 | 156 | interface MyCustomInterface 157 | { 158 | /* 159 | * more abstract methods will cause the interface not to be a valid functional interface and 160 | * the compiler will thrown an error:Invalid '@FunctionalInterface' annotation; 161 | * FunctionalInterfaceAnnotation.MyCustomInterface is not a functional interface 162 | */ 163 | // boolean isFunctionalInterface(); 164 | 165 | int doSomething( int param ); 166 | } 167 | 168 | 169 | ``` 170 | 这个注解可以被使用到类,接口,枚举和注解本身。它的被JVM保留并在runtime可见,这个是它的声明: 171 | 172 | ```java 173 | 174 | @Documented 175 | @Retention(value=RUNTIME) 176 | @Target(value=TYPE) 177 | public @interface FunctionalInterface 178 | ``` 179 | 180 | 181 | 182 | 183 | 184 | ### 解析注解 185 | ```java 186 | 187 | @Target({ElementType.TYPE,ElementType.METHOD}) 188 | @Retention(RetentionPolicy.RUNTIME) 189 | @Inherited 190 | public @interface Description { 191 | 192 | String value(); 193 | } 194 | 195 | public interface Person { 196 | 197 | String name(); 198 | } 199 | 200 | 201 | @Description("this name class") 202 | public class Child implements Person { 203 | @Override 204 | @Description("this name is method") 205 | public String name() { 206 | return null; 207 | } 208 | } 209 | 210 | 211 | import java.lang.reflect.Method; 212 | 213 | /** 214 | * Created by Administrator on 2017/4/22. 215 | */ 216 | public class ParseAnn { 217 | public static void main(String[] args) { 218 | //使用类加载器加载类 219 | try { 220 | Class mClass=Class.forName("cn.edu.nuc.Child"); 221 | //找到类上面的注解 222 | boolean is=mClass.isAnnotationPresent(Description.class);//检查传入的注解是否存在于当前元素。 223 | if (is) { 224 | //拿到注解的实例 225 | Description mDescription= (Description) mClass.getAnnotation(Description.class);//按照传入的参数获取指定类型的注解。返回null说明当前元素不带有此注解 226 | System.out.println(mDescription.value()); 227 | } 228 | 229 | //找到方法的注解 230 | Method[]ms=mClass.getMethods(); 231 | for (Method mMethod:ms) { 232 | boolean isM=mMethod.isAnnotationPresent(Description.class); 233 | if (isM){ 234 | Description mDescription=mMethod.getAnnotation(Description.class); 235 | System.out.println(mDescription.value()); 236 | } 237 | 238 | } 239 | 240 | //另一种找到注解的方法 241 | for (Method mMethod:ms) { 242 | Annotation []mAnnotations=mMethod.getAnnotations();//返回该元素的所有注解,包括没有显式定义该元素上的注解 243 | for (Annotation mAnnotation:mAnnotations){ 244 | if (mAnnotation instanceof Description){ 245 | System.out.println(((Description) mAnnotation).value()); 246 | } 247 | } 248 | } 249 | 250 | } catch (ClassNotFoundException mE) { 251 | mE.printStackTrace(); 252 | } 253 | 254 | } 255 | } 256 | 257 | ``` 258 | 结果 259 | 260 | ```java 261 | D:\java\jdk\bin\java 262 | this name class 263 | this name is method 264 | this name is method 265 | 266 | 267 | Process finished with exit code 0 268 | 269 | ``` 270 | //注意接口是不能继承的,所以换成class,我们看下方法上的注解能不能继承 271 | ```java 272 | public class Child extends Person { 273 | @Override 274 | 275 | public String name() { 276 | return null; 277 | } 278 | } 279 | @Description("this name class") 280 | public class Person { 281 | 282 | @Description("this name is method") 283 | public String name(){ 284 | return null; 285 | } 286 | } 287 | 288 | ``` 289 | 结果 290 | 291 | ```java 292 | D:\java\jdk\bin\java 293 | this name class 294 | 295 | Process finished with exit code 0 296 | ``` 297 | 很明显不能 298 | -------------------------------------------------------------------------------- /Java/java集合.md: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /Java/java面向对象.md: -------------------------------------------------------------------------------- 1 | ### 子类的实例化主要分为两个步骤: 2 | 类相关静态内容 初始化; 3 | 先父类再子类:
4 |   1.父类的static属性;
5 |   2.父类的static块;
6 |   3.子类的static属性;
7 |   4.子类的static块;
8 | 5.父类的普通属性;
9 |   6.父类的构造块;
10 |   7.父类的构造函数;
11 |   8.子类的普通属性;
12 |   9.子类的构造块;
13 |   10.子类的构造函数;
14 | 15 | 16 | 17 | 18 | ### 抽象类可以有构造函数,但是不能实例化。 19 | 子类实例化必须要调用父类构造函数(默认调用父类的无参构造函数)。如果父类定义了有参构造函数,则子类必须显示调用父类的该构造函数 20 | ### 面向对象编程有三个特征,即封装、继承和多态。 21 | 22 | #### 封装隐藏了类的内部实现机制,从而可以在不影响使用者的前提下改变类的内部结构,同时保护了数据。 23 | 24 | #### 继承是为了重用父类代码,同时为实现多态性作准备。那么什么是多态呢? 25 | 26 |   方法的重写、重载与动态连接构成多态性。Java之所以引入多态的概念,原因之一是它在类的继承问题上和C++不同,后者允许多继承,这确实给其带来的非常强大的功能,但是复杂的继承关系也给C++开发者带来了更大的麻烦,为了规避风险,Java只允许单继承,派生类与基类间有IS-A的关系(即“猫”is a “动物”)。这样做虽然保证了继承关系的简单明了,但是势必在功能上有很大的限制,所以,Java引入了多态性的概念以弥补这点的不足,此外,抽象类和接口也是解决单继承规定限制的重要手段。同时,多态也是面向对象编程的精髓所在。 27 | #### 要理解多态性,首先要知道什么是“向上转型”。 28 |  我定义了一个子类Cat,它继承了Animal类,那么后者就是前者是父类。我可以通过
29 |   Cat c = new Cat()
30 |   实例化一个Cat的对象,这个不难理解。但当我这样定义时
31 |   Animal a = new Cat()
32 | #### 这代表什么意思呢? 33 |   很简单,它表示我定义了一个Animal类型的引用,指向新建的Cat类型的对象。由于Cat是继承自它的父类Animal,所以Animal类型的引用是可以指向Cat类型的对象的。那么这样做有什么意义呢?因为子类是对父类的一个改进和扩充,所以一般子类在功能上较父类更强大,属性较父类更独特,定义一个父类类型的引用指向一个子类的对象既可以使用子类强大的功能,又可以抽取父类的共性。所以,父类类型的引用可以调用父类中定义的所有属性和方法,而对于子类中定义而父类中没有的方法,它是无可奈何的;同时,父类中的一个方法只有在在父类中定义而在子类中没有重写的情况下,才可以被父类类型的引用调用;对于父类中定义的方法,如果子类中重写了该方法,那么父类类型的引用将会调用子类中的这个方法,这就是动态连接。看下面这段程序: 34 | 35 | ```java 36 |   class Father{ 37 |   public void func1(){ 38 |   func2(); 39 |   } 40 |   //这是父类中的func2()方法,因为下面的子类中重写了该方法 41 |   //所以在父类类型的引用中调用时,这个方法将不再有效 42 |   //取而代之的是将调用子类中重写的func2()方法 43 |   public void func2(){ 44 |   System.out.println("AAA"); 45 |   } 46 |   } 47 |   class Child extends Father{ 48 |   //func1(int i)是对func1()方法的一个重载 49 |   //由于在父类中没有定义这个方法,所以它不能被父类类型的引用调用 50 |   //所以在下面的main方法中child.func1(68)是不对的 51 |   public void func1(int i){ 52 |   System.out.println("BBB"); 53 |   } 54 |   //func2()重写了父类Father中的func2()方法 55 |   //如果父类类型的引用中调用了func2()方法,那么必然是子类中重写的这个方法 56 |   public void func2(){ 57 |   System.out.println("CCC"); 58 |   } 59 |   } 60 |   public class PolymorphismTest { 61 |   public static void main(String[] args) { 62 |   Father child = new Child(); 63 |   child.func1();//打印结果将会是什么? 64 |   } 65 |   } 66 | ``` 67 | 68 |   上面的程序是个很典型的多态的例子。子类Child继承了父类Father,并重载了父类的func1()方法,重写了父类的func2()方法。重载后的func1(int i)和func1()不再是同一个方法,由于父类中没有func1(int i),那么,父类类型的引用child就不能调用func1(int i)方法。而子类重写了func2()方法,那么父类类型的引用child在调用该方法时将会调用子类中重写的func2()。那么该程序将会打印出什么样的结果呢?很显然,应该是“CCC”。 69 | 70 | #### 对于多态,可以总结它为: 71 | 72 | * 使用父类类型的引用指向子类的对象;
73 | * 该引用只能调用父类中定义的方法和变量; 74 | * 如果子类中重写了父类中的一个方法,那么在调用这个方法的时候,将会调用子类中的这个方法;(动态连接、动态调用)
75 | * 变量不能被重写(覆盖),”重写“的概念只针对方法,如果在子类中”重写“了父类中的变量,那么在编译时会报错。
76 | *********************************************************************
77 | 78 | ### 多态详解(整理)多态是通过: 79 | 80 | * 接口 和 实现接口并覆盖接口中同一方法的几不同的类体现的
81 | * 父类 和 继承父类并覆盖父类中同一方法的几个不同子类实现的.
82 | 83 | ### 一、基本概念 84 |   多态性:发送消息给某个对象,让该对象自行决定响应何种行为。
85 |   通过将子类对象引用赋值给超类对象引用变量来实现动态方法调用。
86 |   java 的这种机制遵循一个原则:当超类对象引用变量引用子类对象时,被引用对象的类型而不是引用变量的类型决定了调用谁的成员方法,但是这个被调用的方法必须是在超类中定义过的,也就是说被子类覆盖的方法。
87 | * 如果a是类A的一个引用,那么,a可以指向类A的一个实例,或者说指向类A的一个子类。
88 | * 如果a是接口A的一个引用,那么,a必须指向实现了接口A的一个类的实例。
89 | ### 二、Java多态性实现机制 90 |   SUN目前的JVM实现机制,类实例的引用就是指向一个句柄(handle)的指针,这个句柄是一对指针: 91 |   一个指针指向一张表格,实际上这个表格也有两个指针(一个指针指向一个包含了对象的方法表,另外一个指向类对象,表明该对象所属的类型); 92 |   另一个指针指向一块从java堆中为分配出来内存空间。 93 | ### 、总结 94 | 95 | #### 1、通过将子类对象引用赋值给超类对象引用变量来实现动态方法调用。 96 | 97 |   DerivedC c2=new DerivedC();
98 |   BaseClass a1= c2; //BaseClass 基类,DerivedC是继承自BaseClass的子类
99 |   a1.play(); //play()在BaseClass,DerivedC中均有定义,即子类覆写了该方法
100 |   分析
101 | 102 | * 为什么子类的类型的对象实例可以覆给超类引用? 103 |   自动实现向上转型。通过该语句,编译器自动将子类实例向上移动,成为通用类型BaseClass; 104 | * a.play()将执行子类还是父类定义的方法? 105 |   子类的。在运行时期,将根据a这个对象引用实际的类型来获取对应的方法。所以才有多态性。一个基类的对象引用,被赋予不同的子类对象引用,执行该方法时,将表现出不同的行为。 106 |   在a1=c2的时候,仍然是存在两个句柄,a1和c2,但是a1和c2拥有同一块数据内存块和不同的函数表。
107 | 108 | 109 | #### 2、不能把父类对象引用赋给子类对象引用变量 110 |   BaseClass a2=new BaseClass();
111 |   DerivedC c1=a2;//出错
112 |   在java里面,向上转型是自动进行的,但是向下转型却不是,需要我们自己定义强制进行。
113 |   c1=(DerivedC)a2; 进行强制转化,也就是向下转型.
114 | 115 | #### 3、记住一个很简单又很复杂的规则,一个类型引用只能引用引用类型自身含有的方法和变量。 116 |   你可能说这个规则不对的,因为父类引用指向子类对象的时候,最后执行的是子类的方法的。 117 |   其实这并不矛盾,那是因为采用了后期绑定,动态运行的时候又根据型别去调用了子类的方法。而假若子类的这个方法在父类中并没有定义,则会出错。 118 |   例如,DerivedC类在继承BaseClass中定义的函数外,还增加了几个函数(例如 myFun()) 119 |   分析: 120 |   当你使用父类引用指向子类的时候,其实jvm已经使用了编译器产生的类型信息调整转换了。 121 |   这里你可以这样理解,相当于把不是父类中含有的函数从虚拟函数表中设置为不可见的。注意有可能虚拟函数表中有些函数地址由于在子类中已经被改写了,所以对象虚拟函数表中虚拟函数项目地址已经被设置为子类中完成的方法体的地址了。 122 | #### 4、Java与C++多态性的比较 123 |   jvm关于多态性支持解决方法是和c++中几乎一样的, 124 |   只是c++中编译器很多是把类型信息和虚拟函数信息都放在一个虚拟函数表中,但是利用某种技术来区别。 125 |   Java把类型信息和函数信息分开放。Java中在继承以后,子类会重新设置自己的虚拟函数表,这个虚拟函数表中的项目有由两部分组成。从父类继承的虚拟函数和子类自己的虚拟函数。 126 |   虚拟函数调用是经过虚拟函数表间接调用的,所以才得以实现多态的。 127 |   Java的所有函数,除了被声明为final的,都是用后期绑定。 128 | ### 四. 1个行为,不同的对象,他们具体体现出来的方式不一样, 129 |   比如: 方法重载 overloading 以及 方法重写(覆盖)override 130 | ```java 131 |   class Human{ 132 |   void run(){输出 人在跑} 133 |   } 134 |   class Man extends Human{ 135 |   void run(){输出 男人在跑} 136 |   } 137 |   这个时候,同是跑,不同的对象,不一样(这个是方法覆盖的例子) 138 |   class Test{ 139 |   void out(String str){输出 str} 140 |   void out(int i){输出 i} 141 |   } 142 | ``` 143 |   这个例子是方法重载,方法名相同,参数表不同
144 |   ok,明白了这些还不够,还用人在跑举例
145 |   Human ahuman=new Man();
146 |   这样我等于实例化了一个Man的对象,并声明了一个Human的引用,让它去指向Man这个对象
147 |   意思是说,把 Man这个对象当 Human看了.
148 |   比如去动物园,你看见了一个动物,不知道它是什么, "这是什么动物? " "这是大熊猫! "
149 |   这2句话,就是最好的证明,因为不知道它是大熊猫,但知道它的父类是动物,所以,
150 |   这个大熊猫对象,你把它当成其父类 动物看,这样子合情合理.
151 |   这种方式下要注意 new Man();的确实例化了Man对象,所以 ahuman.run()这个方法 输出的 是 "男人在跑 "
152 |   如果在子类 Man下你 写了一些它独有的方法 比如 eat(),而Human没有这个方法,
153 |   在调用eat方法时,一定要注意 强制类型转换 ((Man)ahuman).eat(),这样才可以...
154 |   对接口来说,情况是类似的...
155 |   实例: 156 | ```java 157 |   package domatic; 158 |   //定义超类superA 159 |   class superA { 160 |   int i = 100; 161 |   void fun(int j) { 162 |   j = i; 163 |   System.out.println("This is superA"); 164 |   } 165 |   } 166 |   // 定义superA的子类subB 167 |   class subB extends superA { 168 |   int m = 1; 169 |   void fun(int aa) { 170 |   System.out.println("This is subB"); 171 |   } 172 |   } 173 |   // 定义superA的子类subC 174 |   class subC extends superA { 175 |   int n = 1; 176 |   void fun(int cc) { 177 |   System.out.println("This is subC"); 178 |   } 179 |   } 180 | class Test { 181 |   public static void main(String[] args) { 182 |   superA a = new superA(); 183 |   subB b = new subB(); 184 |   subC c = new subC(); 185 |   a = b; 186 |   a.fun(100); 187 |   a = c; 188 |   a.fun(200); 189 |   } 190 |   } 191 |   /* 192 |   * 上述代码中subB和subC是超类superA的子类,我们在类Test中声明了3个引用变量a, b, 193 |   * c,通过将子类对象引用赋值给超类对象引用变量来实现动态方法调用。也许有人会问: 194 |   * "为什么(1)和(2)不输出:This is superA"。 195 |   * java的这种机制遵循一个原则:当超类对象引用变量引用子类对象时, 196 |   * 被引用对象的类型而不是引用变量的类型决定了调用谁的成员方法, 197 |   * 但是这个被调用的方法必须是在超类中定义过的, 198 |   * 也就是说被子类覆盖的方法。 199 |   * 所以,不要被上例中(1)和(2)所迷惑,虽然写成a.fun(),但是由于(1)中的a被b赋值, 200 |   * 指向了子类subB的一个实例,因而(1)所调用的fun()实际上是子类subB的成员方法fun(), 201 |   * 它覆盖了超类superA的成员方法fun();同样(2)调用的是子类subC的成员方法fun()。 202 |   * 另外,如果子类继承的超类是一个抽象类,虽然抽象类不能通过new操作符实例化, 203 |   * 但是可以创建抽象类的对象引用指向子类对象,以实现运行时多态性。具体的实现方法同上例。 204 |   * 不过,抽象类的子类必须覆盖实现超类中的所有的抽象方法, 205 |   * 否则子类必须被abstract修饰符修饰,当然也就不能被实例化了 206 |   */ 207 |   以上大多数是以子类覆盖父类的方法实现多态.下面是另一种实现多态的方法-----------重写父类方法 208 |   1.JAVA里没有多继承,一个类之能有一个父类。而继承的表现就是多态。一个父类可以有多个子类,而在子类里可以重写父类的方法(例如方法print()),这样每个子类里重写的代码不一样,自然表现形式就不一样。这样用父类的变量去引用不同的子类,在调用这个相同的方法print()的时候得到的结果和表现形式就不一样了,这就是多态,相同的消息(也就是调用相同的方法)会有不同的结果。举例说明: 209 |   //父类 210 |   public class Father{ 211 |   //父类有一个打孩子方法 212 |   public void hitChild(){ 213 |   } 214 |   } 215 |   //子类1 216 |   public class Son1 extends Father{ 217 |   //重写父类打孩子方法 218 |   public void hitChild(){ 219 |   System.out.println("为什么打我?我做错什么了!"); 220 |   } 221 |   } 222 |   //子类2 223 |   public class Son2 extends Father{ 224 |   //重写父类打孩子方法 225 |   public void hitChild(){ 226 |   System.out.println("我知道错了,别打了!"); 227 |   } 228 |   } 229 |   //子类3 230 |   public class Son3 extends Father{ 231 |   //重写父类打孩子方法 232 |   public void hitChild(){ 233 |   System.out.println("我跑,你打不着!"); 234 |   } 235 |   } 236 |   //测试类 237 |   public class Test{ 238 |   public static void main(String args[]){ 239 |   Father father; 240 |   father = new Son1(); 241 |   father.hitChild(); 242 |   father = new Son2(); 243 |   father.hitChild(); 244 |   father = new Son3(); 245 |   father.hitChild(); 246 |   } 247 |   } 248 |   都调用了相同的方法,出现了不同的结果!这就是多态的表现! 249 | ``` 250 | 251 | -------------------------------------------------------------------------------- /Java/jvm.md: -------------------------------------------------------------------------------- 1 | ### 四中引用类型 2 | ![](https://pic1.zhimg.com/80/65b7abe9bf2fcd249c789024d95bb67a_hd.jpg) 3 | #### 强引用:只要引用存在,对象就永远不会被回收,我们平时用到嘴对的就是强应用,就算内存溢出也不会被回收、Object o = new Object() 4 | #### 软引用:用来描述一些有用但是非必须的对象,在内存溢出之前,会被这些对象列进回收范围内,之后进行回收 5 | ```java 6 | SoftReference softReference = new SoftReference(s); 7 | if (softReference.get() != null) { 8 | sN = (String) softReference.get(); 9 | }else { 10 | s = new String("hello"); 11 | softReference = new SoftReference(s); 12 | } 13 | ``` 14 | #### 弱引用:用来描述一些非必须对象,只能存活在下一次垃圾回收之前,当下一次垃圾回收之前无论内存是不是够,都会回收 15 | #### 虚引用:也成为幻影引用,一个对象是否有幻影应用都不会影响他的生存时间,也无法通过一个虚引用来获取一个对象,唯一的作用,就是在垃圾回收的时候获取一个通知虚引用主要用来跟踪对象被垃圾回收器回收的活动。虚引用与软引用和弱引用的一个区别在于:虚引用必须和引用队列 (ReferenceQueue)联合使用。当垃圾回收器准备回收一个对象时,如果发现它还有虚引用,就会在回收对象的内存之前,把这个虚引用加入到与之 关联的引用队列中。 16 | ```java 17 | ReferenceQueue queue = new ReferenceQueue (); 18 | PhantomReference pr = new PhantomReference (object, queue); 19 | ``` 20 | 程序可以通过判断引用队列中是否已经加入了虚引用,来了解被引用的对象是否将要被垃圾回收。如果程序发现某个虚引用已经被加入到引用队列,那么就可以在所引用的对象的内存被回收之前采取必要的行动。 21 | https://blog.csdn.net/coding_or_coded/article/details/6603549 22 | -------------------------------------------------------------------------------- /Java/线程池.md: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # StudyNotes 2 | > **一起学习,一起交流** 3 | Q Q:[Einsame](http://sighttp.qq.com/msgrd?v=3&uin=478214853&site=&menu=yes)
4 | 邮箱:[478214853@qq.com](mailto:478214853@qq.com)
5 | 主页:[http://lovehaodong.cn](http://lovehaodong.cn) 6 | 7 | ## Java 8 | 9 | * [Java 基础知识](https://github.com/yanghaodong/StudyNotes/blob/master/Java/java%E5%9F%BA%E7%A1%80%E7%9F%A5%E8%AF%86.md) 10 | * [Java 面向对象](https://github.com/DreamYHD/StudyNotes/blob/master/Java/java%E9%9D%A2%E5%90%91%E5%AF%B9%E8%B1%A1.md) 11 | * [Java 集合](https://github.com/yanghaodong/StudyNotes/edit/master/Java/java集合.md) 12 | * [Java String](https://github.com/yanghaodong/StudyNotes/blob/master/Java/java%20String.md) 13 | * [Java 异常](https://github.com/DreamYHD/StudyNotes/blob/master/Java/java%20%E5%BC%82%E5%B8%B8.md) 14 | * [Java 多线程](https://github.com/yanghaodong/StudyNotes/edit/master/Java/java多线程.md) 15 | * [Java 线程池](https://github.com/yanghaodong/StudyNotes/edit/master/Java/线程池.md) 16 | * [Java io流](https://github.com/DreamYHD/StudyNotes/blob/master/Java/java%20io.md) 17 | * [Java 注解](https://github.com/DreamYHD/StudyNotes/blob/master/Java/java%E6%B3%A8%E8%A7%A3.md) 18 | * [Java 反射](https://github.com/DreamYHD/StudyNotes/blob/master/Java/Java%20%E5%8F%8D%E5%B0%84.md) 19 | 20 | 21 | ## DesignPattern 22 | * [代码区](https://github.com/DreamYHD/DesignPatterns) 23 | * [chapter01 - 面向对象六大原则](https://github.com/yanghaodong/StudyNotes/master/DesignPattern/chapter01-面向对象六大原则.md) 24 | * [chapter02 - 单例模式](https://github.com/onlylemi/notes/blob/master/DesignPattern/chapter02-单例模式.md) 25 | * [chapter03 - Builder模式](https://github.com/onlylemi/notes/blob/master/DesignPattern/chapter03-Builder模式.md) 26 | * [chapter04 - 原型模式](https://github.com/onlylemi/notes/blob/master/DesignPattern/chapter04-原型模式.md) 27 | * [chapter05 - 工厂方法模式](https://github.com/onlylemi/notes/blob/master/DesignPattern/chapter05-工厂方法模式.md) 28 | * [chapter06 - 抽象工厂模式](https://github.com/onlylemi/notes/blob/master/DesignPattern/chapter06-抽象工厂模式.md) 29 | * [chapter07 - 策略模式](https://github.com/onlylemi/notes/blob/master/DesignPattern/chapter07-策略模式.md) 30 | * [chapter08 - 状态模式](https://github.com/onlylemi/notes/blob/master/DesignPattern/chapter08-状态模式.md) 31 | * [chapter09 - 责任链模式](https://github.com/onlylemi/notes/blob/master/DesignPattern/chapter09-责任链模式.md)* [chapter10 - 解释器模式](https://github.com/onlylemi/notes/blob/master/DesignPattern/chapter10-解释器模式.md) 32 | * [chapter11 - 命令模式](https://github.com/onlylemi/notes/blob/master/DesignPattern/chapter11-命令模式.md) 33 | * [chapter12 - 观察者模式](https://github.com/onlylemi/notes/blob/master/DesignPattern/chapter12-观察者模式.md) 34 | * [chapter13 - 备忘录模式](https://github.com/onlylemi/notes/blob/master/DesignPattern/chapter13-备忘录模式.md) 35 | * [chapter14 - 迭代器模式](https://github.com/onlylemi/notes/blob/master/DesignPattern/chapter14-迭代器模式.md) 36 | * [chapter15 - 模板方法模式](https://github.com/onlylemi/notes/blob/master/DesignPattern/chapter15-模板方法模式.md) 37 | * [chapter16 - 访问者模式](https://github.com/onlylemi/notes/blob/master/DesignPattern/chapter16-访问者模式.md) 38 | * [chapter17 - 中介者模式](https://github.com/onlylemi/notes/blob/master/DesignPattern/chapter17-中介者模式.md) 39 | * [chapter18 - 代理模式](https://github.com/onlylemi/notes/blob/master/DesignPattern/chapter18-代理模式.md) 40 | * [chapter19 - 组合模式](https://github.com/onlylemi/notes/blob/master/DesignPattern/chapter19-组合模式.md) 41 | * [chapter20 - 适配器模式](https://github.com/onlylemi/notes/blob/master/DesignPattern/chapter20-适配器模式.md) 42 | * [chapter21 - 装饰模式](https://github.com/onlylemi/notes/blob/master/DesignPattern/chapter21-装饰模式.md) 43 | * [chapter22 - 享元模式](https://github.com/onlylemi/notes/blob/master/DesignPattern/chapter22-享元模式.md) 44 | * [chapter23 - 外观模式](https://github.com/onlylemi/notes/blob/master/DesignPattern/chapter23-外观模式.md) 45 | * [chapter24 - 桥接模式](https://github.com/onlylemi/notes/blob/master/DesignPattern/chapter24-桥接模式.md) 46 | 47 | 48 | 49 | 50 | ## Android 51 | #### 以下内容为学习《Android开发艺术探索》笔记 52 | * [Part01 - Activity生命周期和启动模式](https://github.com/yanghaodong/StudyNotes/master/DesignPattern/chapter01-面向对象六大原则.md) 53 | * [Part02 - IPC机制](https://github.com/onlylemi/notes/blob/master/DesignPattern/chapter02-单例模式.md) 54 | * [Part03 - Drawable](https://github.com/onlylemi/notes/blob/master/DesignPattern/chapter03-Builder模式.md) 55 | * [Part04 - Android的线程和线程池](https://github.com/onlylemi/notes/blob/master/DesignPattern/chapter04-原型模式.md) 56 | * [Part05 - Bitmap的加载和Caches](https://github.com/onlylemi/notes/blob/master/DesignPattern/chapter05-工厂方法模式.md) 57 | * [Part06 - View的事件体系](https://github.com/onlylemi/notes/blob/master/DesignPattern/chapter07-策略模式.md) 58 | * [Part07 - View的工作原理](https://github.com/onlylemi/notes/blob/master/DesignPattern/chapter08-状态模式.md) 59 | * [Part08 - 理解Windows和WindowManger](https://github.com/onlylemi/notes/blob/master/DesignPattern/chapter09-责任链模式.md) 60 | * [Part09 - RemoteViews](https://github.com/onlylemi/notes/blob/master/DesignPattern/chapter11-命令模式.md) 61 | * [Part10 - 动画](https://github.com/onlylemi/notes/blob/master/DesignPattern/chapter12-观察者模式.md) 62 | * [Part11 - 四大组件的工作原理](https://github.com/onlylemi/notes/blob/master/DesignPattern/chapter06-抽象工厂模式.md) 63 | * [Part12 - Android的消息机制](https://github.com/onlylemi/notes/blob/master/DesignPattern/chapter13-备忘录模式.md) 64 | * [Part13 - JNI和NDK编程](https://github.com/onlylemi/notes/blob/master/DesignPattern/chapter14-迭代器模式.md) 65 | * [Part14 - Android性能优化](https://github.com/onlylemi/notes/blob/master/DesignPattern/chapter15-模板方法模式.md) 66 | 67 | 68 | 69 | 70 | ## RxJava 71 | 72 | * [RxJava概述](http://lovehaodong.cn/2017/03/11/RxJava%20%E5%AE%B6%E6%97%8F/) 73 | * [RxJava基础](http://lovehaodong.cn/2017/03/19/RxJava%20RxJava/) 74 | * [RxJava Permissions](http://lovehaodong.cn/2017/03/16/RxJava%20RxPermissions/) 75 | * [RxJava RxLifecyle](http://lovehaodong.cn/2017/03/14/RxJava%20RxLifecycle/) 76 | * [RxJava RxBus基础](http://lovehaodong.cn/2017/03/13/RxJava%20RxBus/) 77 | * [RxJava RxBus进阶](http://lovehaodong.cn/2017/04/09/RxJava%20RxBusTwo/) 78 | * [RxJava RxBinding](http://lovehaodong.cn/2017/03/11/RxJava%20RxBinding/) 79 | 80 | ## Linux 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | --------------------------------------------------------------------------------