美文网首页
2018-09-10

2018-09-10

作者: throwsmyself | 来源:发表于2018-09-10 21:17 被阅读0次

    有关长度的方法

    数组 字符串 集合 文件
    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
      • 修改本地仓库的位置 非必须 但是建议修改
      <localRepository>E:\Service\maven\repository</localRepository>
      
      • 添加国内镜像 (阿里云)
      <mirror>
          <id>alimaven</id>
          <name>aliyun maven</name>
          <url>http://maven.aliyun.com/nexus/content/groups/public/</url>
          <mirrorOf>central</mirrorOf>
        </mirror>
      

    配置环境变量

    • 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
    <properties>
      <maven.compiler.source>1.8</maven.compiler.source>
      <maven.compiler.target>1.8</maven.compiler.target>
    </properties>
    
    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<Integer> 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<K,V> 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<String,Integer> map = new HashMap<>();
    map.put("小翔",210); map.put("小俐",160); map.put("小黑",720);
    Set<String> ks = map.keySet();//得到所有主键对象组成的Set集合
    Collection<Integer> vs = map.values();//得到所有值对象组成的Collection集合
    Set<Map.Entry<String,Integer>> es = map.entrySet();//得到所有键值对对象(Map.Entry)组成的Set集合
    for(Map.Entry<String,Integer> 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<XXX>
        @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

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