2018-09-10

有关长度的方法

数组 字符串 集合 文件
length length() size() length()
int int int long

了解JAVA及工具使用

java的特征

  • 跨平台(JVM)
    Classloader(类加载器)
    ByteCode Verifier(字节码校验器)
    Interfreter(解释执行器)
  • 安全 健壮
    GC(garbage collection) 防止内存泄漏
    exception:当代码出现不合适的地方会报告异常 等待程序员解决
    没有指针 可以避免非法访问
  • 免费 开源
  • 简单
    语法简单:指针 运算符重载 手动的垃圾回收
    思想简单:面向对象的思想 = OO思想
    面向过程的思想:需要人以计算机的角度去思考问题
    面向对象的思想:需要拿着代码去模拟现实生活
  • 动态更新
    核心方法值保留一个指向关系

java开发环境

安装jdk

SDK = Software Development Kits = 软件开发工具包
JDK = Java Development Kit = java开发工具包
JRE = Java Runtime Environment = java运行环境
JVM = 类加载器 + 字节码校验器 + 解释执行器
JRE = JVM + API(核心类库)
JDK = JRE + BIN(常用的工具命令)

设置环境变量

PATH:让操作系统更加快捷的找到一个文件/一个文件夹
PATH=C:\Program Files\Java\jdk-10.0.1\bin
CLASSPATH:类加载器 让类加载器明确去哪里加载.class文件
一般不需要设置 默认值:.[当前目录]
JAVA_HOME:其它的程序使用(WEB)
set PATH=C:\Program Files\Java\jdk1.8.0_74\bin
环境变量的名字进行大写 %%: 表示取出中间环境变量的值
用 ; 分隔多个环境变量
我的电脑 -> 属性 -> 高级 -> 环境变量 -> 新建

java编译运行CMD命令

  • javac (-d 目录) HelloWord.java (-d -> 自动创建包结构)
  • java (目录) HelloWord (有包结构时)
  • javadoc (-d 目录) HelloWord.java
  • jar cvf (Hello.jar) HelloWord.class
    Main-Class: HelloWord

端口被占用

netstat -ano | findstr 8080  ## 得到占用程序的pid
tasklist | findstr 14592  ## 得到占用程序的名称
taskkill /f /t /im javaw.exe  ## 结束程序

Eclipse

编码设置

  • General-> ContentTypes-> Text,Default encoding: utf-8-> update
  • Text,jsp: utf-8
  • 工作空间默认编码: General-> Workspace, Text file encoding-> other: utf-8
  • 新建jsp默认编码: General->Files and Editors-> Jsp-> encoding: utf-8

优化

  • 拼写检查: Editors Spelling-> 去掉Enable spell checking上面的对勾
  • 显示行号: General-> Editors-> Text Editors, Show line numbers
  • 字体: window-> Preferences-> General-> Appearance-> colors and Fonts, Basic-Text Font
  • 代码提示: window-> Preferences-> java-> Editor-> Content Assist, Auto-Activation, Auto Activation triggers for java 改..abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ([{,

单元测试

  1. 工程右键build path -> add libraies -> jUnit
  2. 单元测试的方法命名规则 -> public void 方法名(){}

@Test 表示这是一个用来测试待测试方法的方法。(重点掌握)
@Ignore 表示这个方法不执行,被忽略。
@Before 表示在每个方法之前都会执行该测试方法一次。
@After 表示在每个方法之后都会执行该测试方法一次。

SVN

Subversion简称,是一款 C/S结构的版本管理工具。主要用在多人开发的协同开发场景。
需要配置环境变量

cmd方式

创建代码仓库
svnadmin create D:\Repositories\book
监管代码仓库
svnserve -d -r E:\Repositories\demo

从SVN检出
svn checkout svn://localhost/test
添加到svn
svn add "demo.java"
svn commit "demo.java" -m "演示上传文件到svn"

关于SVNServer中的配置
修改Repositories/项目名/cconf/svnserve.conf下

  • anon-access = read 匿名访问方式
  • auth-access = write 用户访问方式
  • password-db = passwd 修改用户和密码 格式 username = password
  • authz-db = authz 给用户添加权限 格式 [/](可访问空间) username = rwx

在MyEclipse中添加SVN支持
site 目录下 features 和 plugins 文件夹覆盖到 MyEclipse 根目录

maven

依赖管理 -> 我们在项目中需要用到的jar包都交给maven统一管理,不用手动把jar包导入到工程中来。

目录结构

  • Bin:可执行文件
  • Boot:一个类加载器的框架
  • Lib:存放各种maven需要的jar包
  • Conf:maven的配置文件 settings.xml
    • 修改本地仓库的位置 非必须 但是建议修改
    E:\Service\maven\repository
    
    • 添加国内镜像 (阿里云)
    
        alimaven
        aliyun maven
        http://maven.aliyun.com/nexus/content/groups/public/
        central
      
    

配置环境变量

  • JAVA_HOME: JDK的安装目录
  • MAVEN_HOME: maven家,bin目录的上一层
  • Path: MAVEN的bin目录

Maven-helloworld

  1. mvn compile: 编译源代码,会在target目录生成.class文件
  2. mvn test: 执行单元测试 会在target中生成测试类的class文件和测试报告
  3. Mvn package: 打包 在target中生成一个jar包
  4. Mvn install: 安装 将jar包安装到本地仓库 执行install时会自动执行 compile->test->package
  5. 在执行compile \ test\ package\install 命令时,执行后边的命令会自动的执行前边命令。
  6. Mvn clean: 清空 清空target目录 不会执行其他命令
  7. 以上命令可以混合执行如: mvn clean test 或者mvn clean package

eclipse-maven
window -> preferences -> maven -> installations 添加bin目录的上一层
window -> preferences -> maven -> usersettings 添加conf\settings.xml

创建一个maven工程

  1. 加入jdk版本并强制更新 工程名 -> maven -> update project -> 勾选force update -> OK

  1.8
  1.8

  1. 添加web.xml
    工程名 -> properties -> project facets -> Dynamic... -> runtimes -> 勾选部署的服务器 -> 下方配置xml -> src/main/webapp -> OK
  • 如果maven没有部署 -> 找不到maven的jar
    工程名 -> properties -> Deployment Assembly -> add -> java Build Path Entries -> maven

maven范围
compile(编译范围): 编译范围依赖在所有的classpath 中可用,同时它们也会被打包。
provided(已提供范围): provided 依赖只有在当JDK 或者一个容器已提供该依赖之后才使用。例如, 如果你开发了一个web 应用,你可能在编译 classpath 中需要可用的Servlet API 来编译一个servlet,但是你不会想要在打包好的WAR 中包含这个Servlet API;这个Servlet API JAR 由你的应用服务器或者servlet 容器提供。已提供范围的依赖在编译classpath (不是运行时)可用。它们不是传递性的,也不会被打包。
runtime(运行时范围): 依赖在运行和测试系统的时候需要,但在编译的时候不需要。
test(测试范围): 只有在测试编译和测试运行阶段可用。
system(系统范围): 与provided 类似,但是你必须显式的提供一个对于本地系统中JAR 文件的路径。这么做是为了允许基于本地对象编译,而这些对象是系统类库的一部分。这样的构件应该是一直可用的,Maven 也不会在仓库中去寻找它。如果你将一个依赖范围设置成系统范围,
你必须同时提供一个 systemPath 元素。注意该范围是不推荐使用的(你应该一直尽量去从公共或定制的 Maven 仓库中引用依赖)。

基础运算

进制转换

整数二进制转换

0 127 -128 -1 0
00000000 01111111 10000000 11111111 00000000
0+num -1-num

浮点类型二进制转换

float x = 21.25F;
将两个部分全部转换成二进制
整数:21 = 16 + 4 + 1 = 10101
小数:0.25 * 2 * 2 = 01
21.25 = 10101.01

将上面的结果转换成二进制的科学计数法

10101.01 -> 1.010101 * 2(4)

对号入座

符号位1 幂指位8 数值位23
0 10000011 01010100000000000000000

127+4 = 128+2+1= 10000011 01000001101010100000000000000000

强制类型转换
包含关系(范围)可以直接转换 类型范围大转类型范围小要强转

运算符

类型 包含
分隔符 {} [] () , ;
单目运算符 ++ -- ~ !
强制类型转换 (int)(char)
算术运算符 */ %
+-
移位运算 << >> >>>
关系运算 > >= < <=
等价运算 == !=
按位运算 & ^ |
逻辑运算 &&
||
三目运算 a?b:c
赋值运算 = += -= *= /=

提高运行效率

  • &(2^n -1) <===> %(2^n)
    & 100......00
    % 011......11
  • 交换数值(不能交换浮点类型)
    a = a ^ b;====>a=^
    b = a ^ b;====>b=^+b=a
    a = a ^ b;====>a=^+a=b

数据类型

基本数据类型

boolean char byte short int long float double
16 8 16 32 64 32 64

char

char a = 'a';
char a = '中';
char a = 88; //ASCII编码
char a = '\u4e2d'; //Unicode编码
char a = '\t';

int

int num = 25; //十进制
int num = 0b1011; //二进制
int num = 025; //八进制
int num = 0x4e; //十六进制

float/double

float:符号位1 + 幂指位8 + 数值位23
double:符号位1 + 幂指位11 + 数值位52
3.2E4F
E:表示科学计数法 3.2*10(4)
F:表示float类型

封装类

Boolean Character Byte Short Integer Long Float Double

String中常用方法

String  StringBuffer  StringBuilder
方法 备注
length() 字符长度
getBytes() 得到字节数组
toCharArray() 转化成字符数组
split(String) 按照指定的内容劈开
equals(String) 是否相同
equalsIgnoreCase(String) 是否相同-忽略大小写
contains(String) 是否含有指定的内容
startsWith(String) 是否以指定的内容开头
endsWith(String) 是否以指定的内容结尾
toUpperCase() 全部大写
toLowerCase() 全部小写
replace(String,String) 全部替换
replaceAll(String,String) 全部替换[支持正则表达式]
replaceFirst(String,String) 替换第一个
trim() 去除前后空格
substring(int x,int y) 截取数组下标x到下标y-1
substring(int x) 截取数组下标x到最后
charAt(int x) 找到指定下标对应的元素
indexOf(String) 字符串所在下标
lastIndexOf(String) 最后一次出现的下标

Integer中常用的方法

Integer num = new Integer(num);
Integer num = Integer.valueOf(num);
int x = Integer.parseInt(str);
//valueOf() : -128 到 127 常量缓冲池

数组

  • 得到数组元素
    数组对象[下标]
    Arrays.toString(数组对象);(import java.util.Arrays;)
  • 数组大小
    数组对象.length
  • 遍历复制
    新数组 = 老数组.clone();
    System.arraycopy(原数组, 原数组起始下标, 目标数组, 目标数组起始下标, 复制长度);
  • 冒泡排序
  for(int i=0; i< data.length-1; i++){ //循环次数
      for(int j=0; j< data.length-1-i; j++){   //两两比较 一个循环
          if(错误的位置){
              //交换 -> j
          }
      }
  }
  • 自动排序
Arrays.sort(数组对象);  //从小到大
import java.util.*;

分支循环控制

  • if else: 使用return ;简化代码 不要做if(boolean == true)这种低智商的判断
  • switch case: for当循环体需要一个值,循环结束不需要这个值时,最好用for
  • while
  • do while
  • continue: 跳过本次循环,开始下一次循环
  • break: 表示跳出所在的循环
  • a: 循环外设置,循环里面continue/break a:

修饰符

访问权限修饰符 作用范围 属性,方法
public=>公共的 公开 T T
protected=>受保护的 本包/子类 O T
(default)=>默认的 本包 T T
private=>私有的 本类 O T
  • static: 加载时执行一次
  • final: 基本数据类型:数值不能改变 引用数据类型:地址不能改变
  • abstract: 抽象类不能创建对象 但能构造方法 抽象方法不能具体实现

面向对象

类-Class

  1. Class类的实例代表正在运行的JAVA应用程序中的类和接口
  2. JVM创建一个类==>加载Class对象==>创建对象[类的信息都存放在Class对象中]
  3. 一个类的对象可以有很多个,但是Class对象只能有一个
  4. Class类没有公共的构造方法,Class类的对象是由JVM在加载类时自动构造的
  5. 所有具有相同元素类型和维数的数组都共享同一个Class对象

获得Class对象

  • 类 类名字.class Classc= Student.class,Class cls = Emp.class
  • 对象 Class cls = 对象.getClass()
  • 类名字 Class cls = Class.forName(“类名字”)

创建对象的两个方式

  • new();强类型。相对高效。能调用任何public构造。
  • newInstance();弱类型。低效率。只能调用无参构造。
    使用场景:运行时传入一个类的名字,创建实例===>newInstance()===>Class ===>Class.forName("");
newInstance()是实现IOC、反射、依赖倒置 等技术方法的必然选择,new 只能实现具体类的实例化,不适合于接口编程。类里面就是通过这个类的默认构造函数构建了一个对象,如果没有默认构造函数就抛出InstantiationException, 如果没有访问默认构造函数的权限就抛出IllegalAccessException

构造方法

super():首行默认执行父类无参构造方法
注意:父类没有无参却使用无参super就会编译报错
this():执行本类参数匹配的构造方法
super()/this()只能出现一个

成员变量/局部变量

  • 定义的位置不同
  • 作用域不同
    成员变量:依赖于对象存在 只要对象没有被回收 都可以访问
    局部变量:所在方法体内存在 一旦所在的方法体执行结束 局部变量立即消亡
  • 默认值不同
    成员变量:有默认值
    局部变量:没有默认值 必须先赋值
  • 重名时访问方式不同
    直接访问该变量默认是局部变量
    如果我们想要访问成员变量 需要加上this.

接口

类与类之间需要特定的接口协调,将一组类视为单一的类,调用者通过接口与这组类联系
属性默认存在三个修饰符:public static final
方法默认存在两个修饰符:public abstract

接口和抽象类之间的区别

  • 分别表示java中两大类型
    interface:接口,需要实现,用implement
    abstract class:类,需要继承,用extends
  • 对属性的要求不同
    接口里面的属性默认是静态的最终变量(public static final)
    抽象类里面的属性就是普通属性
  • 对方法的要求不同
    interface是完全抽象的 只能声明方法 且不能定义方法体 子类必须实现
    抽象类里面即可以定义抽象方法 又可以定义普通方法 子类可以有选择的实现
  • 一个类可以实现多个interface
    一个类只能继承一个abstract class
  • interface强调的是特定功能的实现,
    abstract class强调的是从属关系

枚举

  • enum java5.0之后
  • 枚举不是类,但是可以将枚举看做一个类来使用
  • 成员(,,,) + 属性(private) + 方法
public enum Color {
    RED("红色",1),Yellow("黄色",2),Blue("蓝色",3);
    private Color(String name, int num){
        this.name = name;
        this.num = num;
    }
    private String name;
    private int num;
    public String getName() {return name;}
    public int getNum() {return num;}
    @Override
    public String toString(){
        return name;
    }
}

注解

annotation

@Target({ElementType.METHOD,ElementType.TYPE})
@Retention(value=RetentionPolicy.SOURCE)
public @interface Demo{
  //只有属性是value时,赋值可以省略
  String value() default "demo";
    Color[] cs();
}

@Target:表示注解适用的程序元素。

  • value=ElementType.METHOD:方法
  • value=ElementType.TYPE:类
  • value=ElementType.FIELD:属性

@Retention:标识注解可以保留多长时间

  • Value=RetentionPolicy.SOURCE:注解信息保存在源码中
  • Value=RetentionPolicy.CLASS:注解信息保存在class文件中 默认的
  • Value=RetentionPolicy.RUNTIME:注解信息保留到运行期

封装继承多态

封装 private 属性,方法

隐藏实现细节 对外提供公共的访问方式
将属性都私有化,对外提供set、get方法来访问
  • 提高了安全性。不允许直接访问细节 可以实现数据可控
  • 提高了易用性。
  • 提高了复用性。
  • 隔离了变化。

继承extends 子类 extends 父类

java中的类只允许单根继承
私有属性在子类的内存空间里面存在
但是不能继续使用 所以不能算是继承得到
super访问父类同名变量

多态用父类型代指所有子类型(继承或者实现)

  • 创建对象 (非重点)
  • 放在参数中 解除代码之间的耦合度
    优势:提高代码的扩展性
    弊端:不能使用子类的特有方法

@overload
同类体内相同名称的方法 参数数量或者类型不同
方法重载对返回类型和修饰符没有要求

@override
访问权限修饰符 >= 父类的权限
返回类型 + 方法签名 相同
异常处理部分 <= 父类的异常(范围,和个数无关)

@Override:注解

数据共享

静态变量
返回类型:方法执行结束之后 返回给我们的数据
方法参数:方法执行的过程中 需要我们提供的数据
方法的定义三个部分:
修饰符 + 返回类型 + 方法签名(方法名 + 参数)

参数传递

内部类

定义在一个类类体当中的另一个类 被称作内部类
内部类的分类: 能够共享到外部类所有[静态+非静态]成员[属性+方法]
Outer.Inner in = new Outer().new Inner();
  • 静态内部类: 能够共享到外部类所有静态成员[属性+方法]
Outer.Inner in = new Outer.Inner();
  • 局部内部类: 外部类所有成员 [被定义在非静态方法中]
    外部类静态成员 [被定义在静态方法中]
    另外还有final修饰的局部变量 [8.0开始可以不加]
Inner in = new Inner();
  • 匿名内部类:
//没有名字
new 父类/接口() { 完成方法覆盖; }

单例模式

  1. 私有化构造方法 ――>无法随意创建对象
  2. 创建一个私有的 静态的 对象 ――>private 外界无法创建 所以要在本类中创建一个对象
    恶汉式:无论是否存在直接new 懒汉式:为null时new
  3. 提供一个公共的 静态的 返回本类类型对象的方法

Object的一些方法

clone():"克隆"一个对象的方法
对clone方法进行方法覆盖
public 类名 clone()throws CloneNotSupportesdException{
Object x = super.clone();
return (类名)x;
当前的类需要实现接口
class 类名 implements Cloneable{}
main方法调用

finalize():对象的"遗言"方法
当一个对象要被回收的时候 gc会主动调用这个对象的finalize方法

toString():制定一个对象打印显示的内容
@Override
public String toString(){return ;}

equals():定义一个类型的比较规则
== 比较 变量(栈) 存放的 对象(堆) 的内存地址
equals 程序员自定义的比较规则

hashCode():定义一个对象的散列特征依据
Hashtable => 哈希表 => 散列表
所谓散列 指的是:将一大组数据分散排列成若干小组

集合

                        Java Collections Framework
                                Java集合框架
            Collection                            Map
            [单值类型集合]                        [键值对集合]
                                                主键唯一
    List                Set
    有序 不唯一            无序 唯一                SortedMap
                        SortedSet                 主键有序 唯一
                        主键有序 唯一
  • 集合中所有的"唯一"都是逻辑相等 是人们希望它相等而把它们算作相同 实际上它们并不是同一个
    这也是 equals 和 == 的区别
  • 散列表或者二叉树 不能 get(下标) 或者 remove(下标)

迭代器Iterator

for(Iterator<> iter = list.iterator(); iter.hasNext(); ){//存在下一个
    iter.next();//下一个
    iter.remove();//删除
}
迭代器使用过程中不允许使用集合增删操作,否则会触发并发修改异常ConcurrentModificationException
如果一定要删除,请使用迭代器自带的iter.remove;
若果一定要添加,请新建一个集合暂存

List

基本方法

//创建List集合
List<泛型类型> list = new ArrayList<>();
//添加元素
list.add(元素);
Collections.addAll(list,元素1,元素2);
//集合长度 有几个元素
list.size()
//根据下标获取元素
list.get(i)

遍历集合

  • for + get(i)
  • foreach
  • Iterator
  • lambda表达式(JDK8.0新特性)

删除元素

//根据下标删除元素
remove(int)
//删除指定Object元素
remove(Object)
//清空集合
clear()
  • 如果要删除的是Integer对象
    请务必保证remove()的参数是Integer而不是int
  • 尊重equals()比较的结果
  • "谁主张 谁举证" 要被删除的那个对象主动调用equals()

数组扩容
如果知道数组长度 最好传参指定
因为数组扩容需要创建新数组 移动元素 删除旧数组

//确保底层数组能装指定的元素个数 - 扩容
list.ensureCapacity()
//将底层数组大小调整到跟真正元素个数一致 - 锁容
list.trimToSize()

四种List

Arraylist LinkedList Vector Stack
底层 数组 链表 数组 数组模拟栈结构
区别 连续存储 内存指向
ArrayList JDK6.0及之前x*3/2+1 JDK7.0及之后x+(x>>1)
Vector new Vector(10)
*2
new Vector(10,8)
+8

stack

//向栈顶添加一个新元素<==>add()
push()
//从栈顶取走一个元素<==>get()+remove()
pop()

Set(HashSet)

完整比较流程 增删改都尊重这个流程

hashCode && (== || equals)
删除重复元素 后来的舍弃

修改参与排序的属性

  1. 删除 --> 可能比较器无法返回0 使用迭代器删除
  2. 修改属性
  3. 重新添加回集合 --> 也是重新排序的过程 需要注意迭代器遍历时不能对集合操作 建一个新的集合来暂存

HashSet构造方法的两个参数:int 分组组数,float 加载因子

//example
new HashSet<>(16,0.75F);
分组组数可以随意指定 但是最终一定是2的n次方数
阈值 = (int)(分组组数*加载因子);  //12
阈值 = Threshold => hold住多少个元素

SortedSet(TreeSet)

TreeSet特有的方法,不能使用多态创建:first() last() pollFirst() pollLast()

TreeSet set = new TreeSet<>();
Collections.addAll(set,55,33,44,11,22,22,22,22,22);
System.out.println(set.size());//唯一
System.out.println(set);//有序 从小到大排序
System.out.println(set.first());//得到第一个 也就是最小值
System.out.println(set.last());//得到最后一个 也就是最大值
System.out.println(set.pollFirst());//删除第一个并返回它本身 即返回11
System.out.println(set.pollFirst());//22

TreeSet必须要实现comparable接口或者参数传入实现comparator接口的比较器

Comparable  compareTo(1)
Comparator  compare(1,2)

多个属性综合形成排序规则

优先尊重什么属性 就先描述假如什么属性不同

修改参与排序的属性

  1. 删除 --> 可能比较器无法返回0 使用迭代器删除
  2. 修改属性
  3. 重新添加回集合 --> 也是重新排序的过程 需要注意迭代器遍历时不能对集合操作 建一个新的集合来暂存

Map/SortedMap

Map map = new HashMap<>();
map.put(k,v);
map.putAll(另一个Map集合);
map.size();
map.get(k);
map.containsKey(k);//是否存在此主键 返回bool类型
map.containsValue(v);//是否存在此值 返回bool类型
map.remove(k);

重复元素处理添加元素时,主键相同(hashCode=1,equals return true)值不同,那么保留主键替换值

遍历Map

keySet() -> 得到所有主键对象组成的Set集合
values() -> 得到所有值对象组成的Collection集合
entrySet() -> 得到所有键值对对象(Map.Entry)组成的Set集合
getKey() getValue() setValue()
================================================
Map map = new HashMap<>();
map.put("小翔",210); map.put("小俐",160); map.put("小黑",720);
Set ks = map.keySet();//得到所有主键对象组成的Set集合
Collection vs = map.values();//得到所有值对象组成的Collection集合
Set> es = map.entrySet();//得到所有键值对对象(Map.Entry)组成的Set集合
for(Map.Entry e: es){
    if(e.getKey()=="小翔") e.setValue(750);
    System.out.println(e.getKey()+": "+e.getValue());
    }
}
对上面得到的集合进行操作就是对Map进行操作

HashMap 和 HashTable的区别

  • 同步特性
    HashMap 同一时间允许多个线程进行操作 效率高 但是可能出现并发错误
    Hashtable 同一时间只允许一个线程进行操作 效率低 但是不会出现并发错误
    JDK5.0开始集合工具类Collections.synchronizedMap();
    JDK5.0开始java.util.concurrent.ConcurrentHashMap支持并发的HashMap
  • 对于null的"态度"不同
    HashMap 无论主键还是值 都允许存放null 只是主键要求唯一 所以只能有一个null
    Hashtable 无论主键还是值 都不允许null出现 一旦出现null 则直接出现异常
  • 底层实现有区别
    HashMap 底层默认分为16个小组 分组组数可以随意指定 但是最终一定是2的n次方数 &(分组组数-1)
    Hashtable 底层默认分为11个小组 它分组组数可以随意指定 %(分组组数)
  • 出现的版本不同
    HashMap - since JDK1.2
    Hashtable since JDK1.0 [集合两大鼻祖之一]

异常Exception

                            Throwable
            Error                       Exception
    底层硬件环境或者系统问题            运行过程出现的例外情况
                                    RuntimeException
                                    运行过程出现的例外情况
=================================================================
非运行时异常 编译时需要给出处理方案 否则无法编译
运行时异常 编译时无需给出处理方案 编译可以通过 但是后面的代码无法执行
两者都是在运行时出现!!!

处理异常

throws Exception
try(){ }catch(Exception1 | Exception2 | Exception3 ex){ex.printStackTrace()}finally{ }
throw //主动制造异常
  • try()括号里的内容支持包括流以及任何可关闭的资源,数据流会在 try 执行完毕后自动被关闭
  • 当try和catch中有return时,先把要返回的值保存起来,不管finally中的代码怎么样,返回的值都不会改变,仍然是之前保存的值,所以函数返回值是在finally执行前确定的;
  • finally中最好不要包含return,否则程序会提前退出,返回值不是try或catch中保存的返回值
  • 如果finally前有System.exit(0)结束java虚拟机,finally不会执行

实用技巧

全局变量赋值需要处理异常时可以在初始化块中try catch
运行时异常默认抛出 不抛出任何异常 也是抛出所有运行时异常
学会try catch finally嵌套使用
无论前面的资源关闭是否出现异常 都要尝试去关闭后面的资源
try的大括号当中定义的变量是特殊的局部变量 会在try的大括号结束的时候消亡
在某些场景下学会使用异常处理代替传统的分支流程 会有意想不到的好效果

线程Thread

新生        就绪        运行        消亡
Born      Runnable  Running  Dead
    等待池        锁池        阻塞                ====>都属于阻塞状态
    wait pool    lock pool  Blocking

程序 -> 保存在物理介质中的代码片段
进程 -> 一旦程序运行起来 就变成了操作系统当中一个进程
线程 -> 一个程序当中一条独立的执行线索

线程章节所有主动进入阻塞状态的方法 都需要进行异常处理
线程章节所有静态方法 不要关注谁调用方法 而要关注调用出现在哪
调用出现在谁的线程体当中 就是操作那个线程

创建线程

extends Thread -> 线程对象.start()
    @Override
    public void run(){  ...;    }
implements Runnable ->Thread xx = new Thread(线程对象) ->xx.start();
    @Override
    public void run(){  ...;    }
implements Callable
    @Override
    public XXX call(){  ...;    }
    它强化了Runnable接口中run()的两大不足
    1st.run被定义为void方法 执行结束之后无法返回数据
    2nd.run没有任何throws声明 但是call有

控制线程

setPriority(int) -> 优先级 默认5 可选范围10-1
static sleep(long) -> 让当前线程休眠指定的毫秒数
static yield() -> 让当前线程放弃时间片 返回到就绪
join() -> 让其他线程加入 并执行完成后再执行后面的语句

线程章节其它常用方法

setName() + getName() -> extends Thread 设置和得到线程的名字 不是类名
static activeCount() -> 程序当中所有活跃线程的总数 = 就绪 + 运行 + 阻塞
    这个方法永远不可能返回0(主线程)
setDaemon(true) -> 设置线程成为守护线程
    守护线程通常都是无限循环 防止过早消亡
    设置成为守护线程要早于自己的start()
    守护线程应当具有极低的优先级别
interrupt() -> 中断 打断线程的阻塞状态
    让线程从阻塞状态 直接返回就绪
    注意 会触发异常
static currentThread() -> 得到当前处于运行状态的线程对象
    在主方法当中得到主线程的线程对象
    在run()调用的其它方法中用来得到线程对象
    它永远不会直接出现在run() 因为得到的对象等价于this

并发错误

多个线程共享同一个数据(对象)
时间片突然耗尽 线程中的代码未能连续执行
多个线程共享的那个对象 -> 临界资源

解决并发错误

  • 互斥锁 = 互斥锁标记 = 锁旗标 = 锁标记 = 监视器 = Monitor
    synchronized 同步的 修饰符 形容词 Modifier
    synchronized特性 只对本类有效 隔代丢失
synchronized(临界资源){...}修饰代码块
public synchronized void add(Object obj){...}修饰方法
  • Java包的工具包的并发包的锁包的可重入锁
    lock() unlock();
    java.util.concurrent.locks.ReentrantLock

死锁

互斥锁标记使用不当 两个线程各占有部分资源又去申请另一个线程已经持有的资源
从而双双进入对方资源的锁池当中====>引入等待池
锁池 要使用锁标记 在锁池内争夺锁的使用权
等待池 主动调用wait方法,休眠
===========================================================
wait(): 放弃锁标记 进入等待池
notify(): 从调用方法的对象等待池中随机唤醒等待池中一个线程
notifyAll(): 唤醒所有阻塞的线程

锁池/等待池

都是每个对象都有一份的空间 而且是存放线程的~
它们都属于阻塞状态
进入锁池不需要释放锁标记
进入等待池需要释放锁标记
锁池不需要 一旦锁标记再度可用 线程自动返回就绪
等待池必须要程序员调用notify() 或者 notifyAll()
离开锁池直接返回就绪
离开等待池直接前往锁池

线程池
一个线程的完整执行时间 = 创建 + 核心逻辑的执行 + 销毁

import java.util.concurrent.*;
ExecutorService es= Executors.newFixedThreadPool(2);//可重用的线程池
ExecutorService es= Executors.newCachedThreadPool();//缓存机制的线程池
ExecutorService es= Executors.newSingleThreadExecutor();//单一实例的线程执行器
es.submit(t1);
es.shutdown();        将之前加入的线程全部完成后退出
es.shutdownNow();        将已经在执行的全部完成后退出
  • 提高资源利用率
  • 提高响应速度
  • 使线程具有可管理性

IO流

方向 -> 输入流 输出流 ==> 参照物是本身
单位 -> 字节流 字符流
功能 -> 节点流 过滤流(包装流、处理流)

new File(String 路径)
new File(String 父目录,String 文件名)
new File(File 父目录对象,String 文件名)
===========================================================
static listRoots() -> 列出当前计算机的所有根目录
String[] list() -> 得到一个目录当中所有的文件名字
File[] listFiles() -> 得到一个目录当中所有的文件对象
exists() -> 判断File对象指代的文件或者目录是否存在
isFile() -> 判断File对象代表的是不是一个文件
isDirectory() -> 判断File对象代表的是不是一个目录
length() -> 得到一个文件的字节个数
===========================================================
mkdirs() -> 创建多层不存在的目录结构
renameTo() -> 重命名文件或者目录
x.renameTo(y); x必须存在 y必须不存在
    x和y可以在不同的目录结构 从而实现剪切移动
delete() -> 删除文件或者目录
    它真的不懂什么叫做"回收站"
    如果要删除的是一个目录 则必须保证目录为空
getName() -> 得到文件或者目录的名字
getParent() -> 得到文件或者目录的父目录
getAbsolutePath() -> 得到文件或者目录的绝对路径
setLastModified() -> 设置文件最后一次修改时间
lastModified() -> 得到文件最后一次修改时间

解析时间

java.util.Date
getYear() getMonth()+1 getDate()
getHours() getMinutes() getSeconds()
java.util.Calendar
get(1) get(2)+1 get(5) get(11) get(12) get(13)
java.text.SimpleDateFormat
"yyyy-MM-dd HH:mm:ss"
format()
parse()

包含子目录的递归遍历的攻略

  1. 我们需要一个专门用来过滤Dir的过滤器 最好使用单例模式[醉汉式]
  2. 我们需要一个专门用来过滤File的过滤器 最好使用单例模式[懒汉式]
  3. 这才是递归遍历的核心所在 一个递归调用的方法
    这个方法需要一个File对象做参数 代表正要对付的那个目录
    3.1. 利用1st开发完的过滤器 得到当前目录中所有子目录
    3.2. 利用2nd开发完的过滤器 得到当前目录中所有File
    3.3. 判断3-1和3-2得到的不是null 防止没有权限而导致的空指针异常
    3.4. 遍历3-1得到的所有子目录 并且再次调用3rd
    3.5. 遍历3-2得到的所有图片文件 进行对应的操作规则. 先进子目录,子目录全部遍历完成才会再进同级目录,然后再往上一层走
  4. 主方法当中创建一个File对象代表要对付的主目录 并且再次调用3rd方法

字节流

InputStream 所有字节输入流统一的父类 抽象类

int read()
int read(byte[] data)
int read(byte[] data,int off,int len)

OutputStream 所有字节输出流统一的父类 抽象类

write(int data)
write(byte[] data)
write(byte[] data,int off,int len)
Buffered = 缓冲 Data = 数据 Object = 对象 | File = 文件

FileInputStream 字节流 输入流 节点流
FileOutputStream 字节流 输出流 节点流

构造方法可以传入字符串或者文件对象只能连接文件 不能连接目录
FileOutputStream 自动创建对象 <==> createNewFile()
但是如果连接的目录结构都不存在 则直接抛出异常
FileOutputStream 是有杀伤力的 直接替换原文件
追加模式 new FileOutputStream("a.txt",true);
FileInputStream 以-1作为读取结束的标识
用完流请第一时间关闭流

BufferedInputStream 字节流 输入流 节点流
BufferedOutputStream 字节流 输出流 节点流

过滤流 给节点流添加缓冲空间 提高效率
不能直接连文件 第二个参数设置缓存空间大小 默认只有8192 也就是8K
BufferedInputStream read()  -> 以-1为读取结束的标识
BufferedOutputStream write(int data)

DataInputStream
DataOutputStream

过滤流 给节点流添加读写基本数据类型的功能
DataInputStream 提供了一组readXxxx() -> 有返回值 -> 不再以-1作为读取结束的标识了
DataOutputStream 提供了一组writeXxxx() -> 要参数
到达文件结尾还尝试继续读取 出现EOFException => End of File

ObjectInputStream
ObjectOutputStream

过滤流 给节点流添加读写对象的功能
ObjectInputStream readObject(); ->不以-1作为读取结束的标识
ObjectOutputStream writeObject();
到达文件结尾还尝试继续读取 出现EOFException => End of File
只能将支持 java.io.Serializable 接口的对象写入流中 必须 implements Serializable
而且其中所有的属性的类型 也有序列化
如果某些属性无关紧要 可以transient => 不参与持久化
如果要持久化的是一个集合对象
则要求集合当中的元素的类型 也要实现序列化接口
如果要持久化的是一个使用了比较器的TreeSet或TreeMap
就连比较器的类型也要实现序列化接口

字符流

Reader 所有字符输入流统一的父类 抽象类

int read()
int read(char[] data)
int read(char[] data,int off,int len)

Writer 所有字符输出流统一的父类 抽象类

write(int data)
write(char[] data)
write(char[] data,int off,int len)

FileReader 字符流 输入流 节点流
FileWriter 字符流 输出流 节点流

构造方法可以传入字符串或者文件对象
只能连接文件 不能连接目录
FileWriter 自动创建对象 <==> createNewFile()
但是如果连接的目录结构都不存在 则直接抛出异常
FileWriter 是有杀伤力的 直接替换原文件
追加模式 new FileWriter("a.txt",true);
FileInputStream 以-1作为读取结束的标识
用完流请第一时间关闭流

BufferedReader 字符流 输入流 过滤流
BufferedWriter 字符流 输出流 过滤流

过滤流 给节点流添加缓冲空间
实现以行为单位读写
不能直接连文件
BufferedReader - String readLine()  -> 以null代表读取结束  -> 不再以-1作为读取结束的标识了
BufferedWriter - write(String)

PrintStream
PrintWriter
和BufferedWriter相比较的优势:

  • 既可以当做节点流 又可以当做过滤流
  • 既可以连接字节流 又可以连接字符流
  • 当做节点流使用 可以指定字符集
  • 当做过滤流使用 可以指定自动清空缓冲
  • println() = write() + newLine()
    综上所述 今后如果需要写出文本文件 PrintWriter绝对是不二选择

InputStreamReader 桥转换器 能够将字节流转换成字符流

FileInputStream fis = new FileInputStream("abc.txt");
InputStreamReader r = new InputStreamReader(fis);
BufferedReader br = new BufferedReader(r);

OutputStreamWriter 桥转换器 能够将字节流转换成字符流

FileOutputStream fos = new FileOutputStream("cba.txt");
OutputStreamWriter w = new OutputStreamWriter(fos);
BufferdWriter bw = new BufferedWriter(w);

因为PrintWriter的强大 让OutputStreamWriter几乎无用武之地
但是 其实幕后的英雄还是它
RandomAccessFile 构造方法第二个参数 请指定rw模式
setLength(long) -> 能够将连接的文件设定到指定的大小

反射

JAVA反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意一个方法和属性;这种动态获取的信息以及动态调用对象的方法的功能称为java语言的反射机制。
反射就是把java类中的各种成分映射成一个个的Java对象。
Class对象的由来是将class文件读入内存,并为之创建一个Class对象。
在运行期间,一个类,只有一个Class对象产生。
反射是框架设计的灵魂

获得类

类名.class
对象.getClass();
Class.forName("对象名");
通过class获取实例 无参
cls.newInstance();

获取构造方法

Constructor c = cls.getDeclaredConstructor();
Constructor[] cs = cls.getDeclaredConstructors();
............
通过构造方法获取实例 可以指定参
c.newInstance(obj...);

获得属性

Field f = cls.getField(String);本类和直接父类public的属性
Field[] fs = cls.getFields();
Field f = cls.getDeclaredField(String);本类的所有属性
Field[] fs = cls.getDeclaredFields();
属性名
f.getName();
修饰符 getModifies()->整数
Modifier.toString(f.getModifiers());
类型 getType->Class
f.getType().getName();
破封装 -> private
f.setAccessible();
对带有指定参数的指定对象设置field的值
field.set(instance,value);

获得方法

Method m = cls.getMethod(String);
ethod[] ms = cls.getMethods()
Method m = cls.getDeclaredMethod(String);
ethod[] ms = cls.getDeclaredMethods();
方法名
m.getName();
修饰符
Modifier.toString(m.getModifiers());
返回类型
m.getReturnType().getName();
method 由 instance 调用 参数 value 是框架的核心
method.invoke(instance,value);

你可能感兴趣的:(2018-09-10)