Java 自己可能会忘的东西

Java Learning


基础理解

  • 大小写敏感

  • 关键词检测

    所有的标识符都应该以字母(A-Z 或者 a-z),美元符($)、或者下划线(_)开始
    首字符之后可以是字母(A-Z 或者 a-z),美元符($)、下划线(_)或数字的任何字符组合

Java变量

  • 局部变量

  • 类/静态变量

  • 成员变量/非静态变量

    注释

 /* 多行注释 */
 // 单行注释```

Java运行

Java 对象和类

  • 多态
  • 继承
  • 封装
  • 抽象
  • 对象
  • 实例
  • 方法
  • 重载

object

https://www.runoob.com/java/java-object-classes.html


面向对象

类的定义和使用:类名 成员变量 方法

​ 类名 对象名 = new 类名()

使用对象: 对象名.变量名 // 对象名.方法名()

成员变量:定义在类中 方法外

成员方法:去除static(静态)修饰符


继承

继承概念: 泛指把前人的作风 文化 知识 财产等接受过来

Java中:

被继承的类叫做 父类

继承的类叫做 子类

格式:

(extends)
    class 父类{
        // .....
    }
    class 子类 extends 父类{
        // .....
    }

效果:

子类拥有了父类的非私有成员 (成员变量 成员方法)

场景: 多个类中存在相同的属性和行为时 可以将这些内容提取出来放到一个新类中 让这些类和新类产生父子关系 实现代码复用

优点:

功能复用 便于扩展 结构清晰 易维护

缺点:

打破了封装性 高耦合性

程序设计追求

低耦合 高内聚

耦合

两个 or 更多的模块相互依赖对方

内聚

模块内部结构紧密 独立性强


this和super的区别

this的本质 对象

super的本质 父类内存空间的标识

子类的第一行 都有一个默认的sueper
用来访问父类的无参构造

如果父类没有无参构造
可以通过super(参数)的方法访问父类的带参构造


类和方法

方法重写(Override)

  • 定义

  • 子类中出现和父类方法定义相同的方法的现象

  • 解释

    • 方法重写 也叫 复写 覆盖
    • 方法名 参数列表 返回值类型都相同
  • 注意

    • 父类私有方法无法重写

    • 子类方法访问权限不能小于父类方法

      • 四大权限修饰符的修饰范围 从小到大

        *private 默认 protected public *

    • 子类不能比父类方法抛出更大的异常

  • 使用场景

    • 扩展父类功能
    • 父类功能过时 重新实现父类功能

访问权限修饰符(public/private/default/protected)

本类 本包 子类 其他类
private Y
默认 Y Y
protected Y Y Y
public Y Y Y Y

private : 强调给自己使用 ==属性==

默认 : 强调给同包下的来使用

protected : 强调给子类使用 ==会被子类继承的方法==

public : 强调给大家使用 ==方法==


方法重写

方法名 参数列表 返回值类型 修饰符 定义位置
重载 Overload 相同 不同(个数或对应类型) 无关 无关 同一个类
重写 Override 相同 相同 相同 访问权限不小于被重写方法 子父类中

继承

特点

  • 单继承

    • Java只支持类的单继承 但是支持多层(重)继承

    • Java支持接口的多继承

    • 构造方法不能继承

      • 构造方法用于初始化本类对象

      • 创建子类对象时 需要调用父类构造初始化对象

      • 该对象的父类内容 若父类构造可以被继承 该操作回造成调用的混乱

      • 接口A extends 接口B,接口c,接口D...
      • public class Fruit{}
        public class Apple extends Fruit{}
        public class Orange extends Fruit{}
        public class Fuji extends Apple{}
        public class GreenApple extends Apple{}


多态

多种状态 同一对象在不同情况下表现出不同的状态或行为

抽象类

概念

包涵抽象方法的类 用abstract实现

抽象方法

只有方法声明 没有方法体的方法 用abstract修饰

抽象方法的由来

当需要定义一个方法 却不明确方法的具体实现时 可以将方法定义为abstract 具体实现延迟到子类

特点

要求子类必须重写

修饰符

abstract关键字修饰

修饰符 abstract class 类名 {}

修饰符 abstract 返回值类型 方法名 {}

抽象类不能被实例化 即不能new 只能创建子类

抽象类子类的两个选择

重写父类所有的抽象方法

定义成抽象类

抽象类成员的特点

  • 成员变量
    • 可以有普通的成员变量 也可以有成员变量 final
  • 成员方法
    • 可以有普通方法 也可以有抽象方法
    • 抽象类不一定有抽象方法 有抽象方法的类一定是抽象类/接口
  • 构造方法
    • 像普通类一样有构造方法 且可以重载

总结: 抽象类中的成员 比 普通类多一种 抽象方法

​ 其他一样

抽象类的案例

Request : 程序员 经理

​ 均有 姓名 工资 工号 // 经理有奖金​

​ 请使用继承思想设计出上述需求中的类 并分别创建对象使用

分析:

  • 共同的属性和行为定义在父类 Employee 并不明确 abstract 且内容为 name salary id work()
  • 定义经理类 Manager 继承Employee 属性和行为 : bonus work()
  • 定义程序员类 Coder 继承Employee 属性和行为 : work();
  • 在测试类中分别创建对象并使用

小细节

子类开发中一般都有两个构造方法

子类的空参构造访问父类的空参构造

子类的全参构造访问父类的全参构造


static 关键字

作用:

用于修饰类的成员:

成员变量:类变量

成员方法:类方法

调用方式:

类名.成员变量名  
类名.成员方法名(参数)

static修饰成员变量

  • 特点 : 被本类所有对象共享

Waring

随意修改静态变量的值是有风险的 为了降低风险 可以使用final关键字修饰 即公有静态变量 (注意命名的变化)


修饰成员方法

  • 静态方法

静态方法中没有对象this 所以不能访问非静态成员

  • 静态方法的使用场景

只需要访问静态成员

不需要访问对象状态 所需参数都由参数列表显示提供

通俗一点: 没有调用任何对象属性 就可以考虑 void

public void die() {
    hp = 0;
    battleWin();//非静态方法可以调用静态方法
}
public static void battleWin() {
    System.out.println("battleWin");
    //die(); 不能调用,静态方法不能调用非静态方法
}

类方法 静态方法

public class Hero {
    public String name = "some hero"; 

    public Hero(){
        name = "one hero";
    }
    {
        name = "the hero";
    }

}

Answer : one hero

顺序:

声明的时候初始化

块初始化

构造方法内的初始化


单例模式

饿汉式

GiantDragon.java

public class GiantDragon {
   //私有化构造方法使得该类无法在外部通过new 进行实例化
   private GiantDragon(){}

   //准备一个类属性,指向一个实例化对象。 因为是类属性,所以只有一个
   private static GiantDragon instance = new GiantDragon();

   //public static 方法,提供给调用者获取上面定义的对象
   public static GiantDragon getInstance(){
       return instance;
   }

}

[^HungryMan]: private 令其外部不能使用new 但是内部进行了new然后新建了一个方法给外界 用于产生new的方法

TestGiantDragon.java

public class TestGiantDragon {

   public static void main(String[] args) {
       //通过new实例化会报错
//      GiantDragon g = new GiantDragon();

       //只能通过getInstance得到对象
       GiantDragon g1 = GiantDragon.getInstance();
       GiantDragon g2 = GiantDragon.getInstance();
       GiantDragon g3 = GiantDragon.getInstance();

       //都是同一个对象
       System.out.println(g1==g2);
       System.out.println(g1==g3);
   }
}

立即加载的方式,无论是否会用到这个对象,都会加载
如果在构造方法里写了性能消耗较大,占时较久的代码,比如建立与数据库的连接,那么就会在启动的时候感觉稍微有些卡顿

时间充裕

懒汉式

GiantDragon.java

public class GiantDragon {

   //私有化构造方法使得该类无法在外部通过new 进行实例化
   private GiantDragon(){       
   }

   //准备一个类属性,用于指向一个实例化对象,但是暂时指向null
   private static GiantDragon instance;

   //public static 方法,返回实例对象
   public static GiantDragon getInstance(){
       //第一次访问的时候,发现instance没有指向任何对象,这时实例化一个对象
       if(null==instance){
           instance = new GiantDragon();
       }
       //返回 instance指向的对象
       return instance;
   } 
}

TestGiantDragon.java

public class TestGiantDragon {

   public static void main(String[] args) {
       //通过new实例化会报错
//      GiantDragon g = new GiantDragon();

       //只能通过getInstance得到对象

       GiantDragon g1 = GiantDragon.getInstance();
       GiantDragon g2 = GiantDragon.getInstance();
       GiantDragon g3 = GiantDragon.getInstance();

       //都是同一个对象
       System.out.println(g1==g2);
       System.out.println(g1==g3);
   }
}

延迟加载的方式,只有使用的时候才会加载。
使用懒汉式,在启动的时候,会感觉到比饿汉式略快,因为并没有做对象的实例化。 但是在第一次调用的时候,会进行实例化操作,感觉上就略慢。

线程安全**

小结:

  1. 构造方法私有化
  2. 静态属性指向实例
  3. public static的 getInstance方法,返回第二步的静态属性

枚举类型



接口

接口技术用于描述具有什么功能 但并不给出具体实现 类要遵从接口描述的统一规则进行定义 所以 接口是对外提供的一组规则 标准

接口定义

  • interface
  • intereface 接口名{}
  • 类和接口是实现关系 用Implements表示
    • calss 类名 implements 接口名

接口概述

接口创建对象的特点

  • 接口不能实例化
    • 通过多态的方式实例化子类
  • 接口的子类(实现类)
    • 可以是抽象类 可以是普通类

接口继承关系的特点

  • 接口与接口之间的关系

    • 继承关系 可以多继承
    • 接口 extends 接口1 接口2 接口3..
  • 继承和实现的区别

    • 继承体现的是 is a的关系 父类中定义共性内容
    • 实现体现的是like a关系 接口中定义扩展内容

接口成员的特点

接口成员变量的特点

  • 接口没有成员变量 只有公有的 静态的常量
public static final 常量名 = 常量值 ;

接口成员方法的特点

  • 成员方法
    • JDK 9以后 可以有私有变量
      • private 返回值类型 方法名 {}
  • 接口构造
    • 接口不能实例化 无法构造

对象转型

类型转换

当需要使用子类特有功能时 需进行

  • 向上转型(自动)
    • 子类型转换为 父类型
Animal animal = new Dog();
  • 向下转型 (强制)
    • 父类型转换到子类型
Dog dog = (Dog)animal;

注意

  • 只能在继承层次内进行转换 否则

    • ClassCastException
  • 将父类对象转换成子类对象之前 使用 instanceof检查

    • 对象名 instanceof 数据类型
    • 判断前边的对象是否是后边的数据类型

多态

Java中实现多态

  • 要有继承(或实现)关系
  • 要有方法重写
  • 父类引用指向子类对象( is a 关系 )
public class Test{
    public static void main(String[] args){
        Animal a = new Dog();
    }
}

父类引用指向子类

编译看左 运行看右

Animal an = new Dog();

多态的使用场景

父类型可以作为形参的数据类型 这样可以接受其任意的子类对象 // 比如一个方法 要父类你可以把子类对象丢进去

多态关系中成员变量的使用

多态关系中 成员变量是不涉及到重写的

编译看左 运行看左

编译看左 : 在编译期间会看左边的类型有没有这个成员 没有就报错 有就不报错

运行看左 : 在运行期间使用的是 左边类型中的成员

多态的好处和弊端

好处

  • 可维护性
  • 可扩展性

弊端

不能使用子类特有成员

操作符的多态

+

两侧都是整型 代表数字相加

任意一个是字符串 代表字符串连接

类的多态现象

同一个类型 调用同一个方法 呈现不同的状态

不使用多态

假设英雄要使用血瓶和魔瓶,就需要为Hero设计两个方法
useLifePotion
useMagicPotion

除了血瓶和魔瓶还有很多种物品,那么就需要设计很多很多个方法,比如
usePurityPotion 净化药水
useGuard 守卫
useInvisiblePotion 使用隐形药水
等等等等

package charactor;

import property.LifePotion;
import property.MagicPotion;

public class Hero {
    public String name;
    protected float hp;

    public void useLifePotion(LifePotion lp){
        lp.effect();
    }
    public void useMagicPotion(MagicPotion mp){
        mp.effect();
    }

    public static void main(String[] args) {

        Hero garen =  new Hero();
        garen.name = "盖伦";

        LifePotion lp =new LifePotion();
        MagicPotion mp =new MagicPotion();

        garen.useLifePotion(lp);
        garen.useMagicPotion(mp);

    }

}
使用多态

如果物品的种类特别多,那么就需要设计很多的方法
比如useArmor,useWeapon等等

这个时候采用多态来解决这个问题
设计一个方法叫做useItem,其参数类型是Item
如果是使用血瓶,调用该方法
如果是使用魔瓶,还是调用该方法
无论英雄要使用什么样的物品,只需要一个方法即可**

package charactor;

import property.Item;
import property.LifePotion;
import property.MagicPotion;

public class Hero {
    public String name;
    protected float hp;

    public void useItem(Item i){
        i.effect();
    }

    public static void main(String[] args) {

        Hero garen =  new Hero();
        garen.name = "盖伦";

        LifePotion lp =new LifePotion();
        MagicPotion mp =new MagicPotion();

        garen.useItem(lp);
        garen.useItem(mp);     

    }

}

PS:

LifePotion.java

package property;

public class LifePotion extends Item {
    public void effect(){
        System.out.println("血瓶使用后,可以回血");
    }
}

MagicPotion.java

package property;

public class MagicPotion extends Item{

    public void effect(){
        System.out.println("蓝瓶使用后,可以回魔法");
    }
}

隐藏

Hero h = new ADHero();

Q:

h.battleWin(); //battleWin 是一个类方法
h是父类类型的引用
但是指向一个子类对象
h.battleWin();会调用父类的方法?还是子类的方法?

A:

调用对象方法是从对象所指向的类型向父类进行搜索,匹配相应的方法。
类方法只能是在申明的类中寻找方法。
所以Hero h =new ADHero();
h.battleWin();
只能在Hero类型中匹配类方法battleWin()

Object 类

Object 类是所有类的父类

声明一个类 默认是继承了Object

public class Hero extends Object

toString

System.out.println(h.toString());
 //直接打印对象就是打印该对象的toString()返回值
System.out.println(h);

两者是等价的

finalize

当一个对象没有任何引用指向的时候 他就满足了垃圾回收的条件

就会调用此方法

由虚拟机JVM 调用的

equals

用于判断两个对象的内容是否相同

hshCode

线程同步

getClass

返回对象的类对象


final

该类不能被继承 ** 即无子类 但是可以有父类**

方法

该方法*不能被重写 * 即 只让子类用 不让子类改

基本型变量

最终变量 常量 只能赋值一次

常量

指 可以公开 直接访问 不会变化的z值

public static final int itemTotalNumber = 6;
//物品栏的数量

抽象类

父类提供一个抽象方法 子类继承后 就必须重写该方法

抽象类无法被实例化

public abstract class Hero{
    public static void main(String[] args){
        Hero h = new Hero();

    }
}

无法实现

与接口的区别

抽象类 接口
个数 子类只能继承一个抽象类 子类可以实现多个接口
声明 public , protected,package,private静态/非静态 final / 非final public,final , 静态

内部类

非静态内部类

public class Hero {
    private String name; // 姓名

    float hp; // 血量

    float armor; // 护甲

    int moveSpeed; // 移动速度

    // 非静态内部类,只有一个外部类对象存在的时候,才有意义
    // 战斗成绩只有在一个英雄对象存在的时候才有意义
    class BattleScore {
        int kill;
        int die;
        int assit;

        public void legendary() {
            if (kill >= 8)
                System.out.println(name + "超神!");
            else
                System.out.println(name + "尚未超神!");
        }
    }


    public static void main(String[] args) {
        Hero garen = new Hero();
        garen.name = "盖伦";
        // 实例化内部类
        // BattleScore对象只有在一个英雄对象存在的时候才有意义
        // 所以其实例化必须建立在一个外部类对象的基础之上
        BattleScore score = garen.new BattleScore();
        score.kill = 9;
        score.legendary();
    }

}

静态内部类

package charactor;

public class Hero {
    public String name;
    protected float hp;

    private static void battleWin(){
        System.out.println("battle win");
    }

    //敌方的水晶
    static class EnemyCrystal{
        int hp=5000;

        //如果水晶的血量为0,则宣布胜利
        public void checkIfVictory(){
            if(hp==0){
                Hero.battleWin();

                //静态内部类不能直接访问外部类的对象属性
                System.out.println(name + " win this game");
            }
        }
    }

    public static void main(String[] args) {
        //实例化静态内部类
        Hero.EnemyCrystal crystal = new Hero.EnemyCrystal();
        crystal.checkIfVictory();
    }

}

匿名类

package charactor;

public abstract class Hero {
    String name; //姓名

    float hp; //血量

    float armor; //护甲

    int moveSpeed; //移动速度

    public abstract void attack();

    public static void main(String[] args) {

        ADHero adh=new ADHero();
        //通过打印adh,可以看到adh这个对象属于ADHero类
        adh.attack();
        System.out.println(adh);

        Hero h = new Hero(){
            //当场实现attack方法
            public void attack() {
                System.out.println("新的进攻手段");
            }
        };
        h.attack();
        //通过打印h,可以看到h这个对象属于Hero$1这么一个系统自动分配的类名

        System.out.println(h);
    }

}

本地类

package charactor;

public abstract class Hero {
    String name; //姓名

    float hp; //血量

    float armor; //护甲

    int moveSpeed; //移动速度

    public abstract void attack();

    public static void main(String[] args) {

        //与匿名类的区别在于,本地类有了自定义的类名
        class SomeHero extends Hero{
            public void attack() {
                System.out.println( name+ " 新的进攻手段");
            }
        }

        SomeHero h  =new SomeHero();
        h.name ="地卜师";
        h.attack();
    }

}

在匿名类种使用外部的局部变量

package charactor;

public abstract class Hero {

    public abstract void attack();

    public static void main(String[] args) {

        //在匿名类中使用外部的局部变量,外部的局部变量必须修饰为final
        final int damage = 5;

        Hero h = new Hero(){
            public void attack() {
                System.out.printf("新的进攻手段,造成%d点伤害",damage );
            }
        };

    }

}

默认方法

JDK 8 New

接口也可以提供具体方法 不仅仅是抽象方法

package charactor;

public interface Mortal {
    public void die();

    default public void revive() {
        System.out.println("本英雄复活了");
    }
}

综合练习

UML – Unified Module Language

统一建模语言 用来方便的表示类的属性,方法,以及类和类之间的关系

解释UML

实线箭头指向的是需要继承的父类


数字与字符串

所有的基本类型 都有对应的 类类型

intInteger

转换

Integer it = new Integer(i);

int i2 =  it.intValue();

Number

包括Byte Integer Double Short Float Long

自动装箱

 //基本类型转换成封装类型
        Integer it = new Integer(i);

//自动转换就叫装箱
        Integer it2 = i;

自动拆箱

       Integer it = new Integer(i);

  //封装类型转换成基本类型
        int i2 = it.intValue();

    //自动转换就叫拆箱
        int i3 = it;

int的最大最小值

      //int的最大值
        System.out.println(Integer.MAX_VALUE);
        //int的最小值      
        System.out.println(Integer.MIN_VALUE);

字符串转换

数字转字符串

String str = String.valueOf(i);

Integer it = i;
String str2 = it.toString();

字符串转数字

String str = "999";

int i = Integer.parseInt(str);

数学方法

四舍五入

Math.rounds();

字符

char 只能存储一个字符

character 常用方法

isLetter判断是否为字母

isDigit 判断是否为数字

isWhitespace 是否是空白

isUpperCase 是否是大写

isLowerCase 是否是小写

toUpperCase 转换为大写

toLowerCase 转换为小写

toString 转换为字符串

字符串

String 是一个类 所以我们见到得字符串都是对象

String hero = new String(cs);//  通过字符数组创建一个字符串对象

String hero3 = garen + teemo;//  通过+加号进行字符串拼接

String 无法被继承

String 表现相当于常量 里面得内容永远无法被改变

.length 返回字符串的长度

操纵字符串

.split() 分割字符串

toCharArray 获取对应的字符串数组

subString() 截取部分

charAt() 指定位置的字符

trim 去除首尾空格

indexOf() 第一次出现的位置 如果加入,num在num之后的第一次出现的位置

lastIndexOf() 最后一次出现

contains() 是否包括

replaceAl(,) 全部替换

replaceFirst() 只替换第一个

比较字符串

String str1 = "the light";

String str2 = new String(str1);

内容一致 但是是不同的对象

== 判断的是两个字符串是不是同一个字符串

String str1 = "the light";

 String str3 = "the light";

这两个却是同一个对象

equals 比较字符串的内容是否相同 区分大小写

equalsIgnoreCase 忽略大小写判断是否一致

startsWith()

endsWith()

StringBuffer

StringBuffer sb = new StringBuffer(str);

sb.append("Life");

sb.delete(4,10);

sb.insert(4,"there");

sb.reverse;
sb.length; // 长度 指的是字符串实际字符的长度

sb.capacity;    // 容量 分配的空间 比字符串有冗余

IStringBuffer

自己写一个StringBuffer

TODO: TBD


Date 日期

时间远点

1970年1月1日 8点0分0秒 (为什么是8点,因为中国的太平洋时区是UTC-8,刚好和格林威治时间差8个小时)

为什么对应1970年呢? 因为1969年发布了第一个 UNIX 版本:AT&T,综合考虑,当时就把1970年当做了时间原点。

所有的日期,都是以为这个0点为基准,每过一毫秒,就+1

Date d1 = new Date(5000); // 毫秒
// 从1970年1月1日 早上8点0分0秒 开始经历了5秒的时间

now.getTime

System.currentTimeMillis()

都能获得时间 long 类型

SimpleDateFormat

日期格式化

format 日期转字符串

parse 字符串转日期

  • y 代表年 yyyy

  • M 代表月 yy

  • d 代表日 dd

  • H 代表24进制的小时 HH

  • h 代表12进制的小时 hh

  • m 代表分钟 mm

  • s 代表秒 ss

  • S 代表毫秒 sss

Calendar

使用单例模式获取Calendar 对象

Calendar c = Calendar.getInstance();
Date now = c.getTime();
        // 当前日期
        System.out.println("当前日期:\t" + format(c.getTime()));

        // 下个月的今天
        c.setTime(now);
        c.add(Calendar.MONTH, 1);
        System.out.println("下个月的今天:\t" +format(c.getTime()));

        // 去年的今天
        c.setTime(now);
        c.add(Calendar.YEAR, -1);
        System.out.println("去年的今天:\t" +format(c.getTime()));

        // 上个月的第三天
        c.setTime(now);
        c.add(Calendar.MONTH, -1);
        c.set(Calendar.DATE, 3);
        System.out.println("上个月的第三天:\t" +format(c.getTime()));
private static String format(Date time) {
        return sdf.format(time);
    }

改变日期

c.add(Calendar.MONTH, 2);
c.set(Calendar.DATE, -3);

甚至可以搞负数


异常处理

常见异常的处理方法:

try cathch finally throws

try catch

     File f= new File("d:/LOL.exe");

        try{
            System.out.println("试图打开 d:/LOL.exe");
            new FileInputStream(f);
            System.out.println("成功打开");
        }
        catch(FileNotFoundException e){
            System.out.println("d:/LOL.exe不存在");
            e.printStackTrace();
        }

先执行try内容 如果有问题 立刻到catch中 printStackTrace() 会打印调用的痕迹

也可 catch 异常的父类

catch (Exception e){}

多异常处理办法

可以写多个catch 抓住多个错误

catch (FileNotFoundException e) {
    System.out.println("d:/LOL.exe不存在");
    e.printStackTrace();
} 
catch (ParseException e) {
    System.out.println("日期格式解析错误");
    e.printStackTrace();
}

放一个里面catch也可

catch (FileNotFoundException | ParseException e) {}

缺点是无法判断到底是哪个错误 需要使用instanceof 进行种类的判断

if (e instanceof FileNotFoundException)
    System.out.println("d:/LOL.exe不存在");
if (e instanceof ParseException)
    System.out.println("日期格式解析错误");

finally

无论是否出错 finally中的代码都会被执行

finally{System.out.println("无论文件是否存在, 都会执行的代码");}

throws

eg. main方法调用method1 method1调用method2 method执行可能有错误的操作

method2不打算处理 他想扔出去

method1 接住这个问题 他要么try catch 消化了 或者throws 抛出去

public class TestException {

    public static void main(String[] args) {
        method1();

    }

    private static void method1() {
        try {
            method2();
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        }

    }

    private static void method2() throws FileNotFoundException {

        File f = new File("d:/LOL.exe");

        System.out.println("试图打开 d:/LOL.exe");
        new FileInputStream(f);
        System.out.println("成功打开");

    }
}

throwthrows 的区别

thorw throws
出现的位置 通常方法体内 方法声明
意义 一定出现了异常 才扔出去的 表示可能出现异常 如果出现再扔出去

Q:

假设有一个方法 public int method(), 会返回一个整数
在这个方法中有try catch 和 finally.
try 里返回 1
catch 里 返回 2
finally 里 返回3

最后返回几?

A:

由于不管是否出现错误都会执行finally 先执行try 没有错误 但是finally会覆盖掉他的返回值

异常的分类

CheckedException 可查异常

即//必须进行处理//的异常

RuntimeException 运行时异常

不是必须进行 try catch 的异常

常见的有

除数不能为0异常:ArithmeticException
下标越界异常:ArrayIndexOutOfBoundsException
空指针异常:NullPointerException

Java之所以会设计运行时异常的原因之一,是因为下标越界,空指针这些运行时异常太过于普遍,如果都需要进行捕捉,代码的可读性就会变得很糟糕。

Error 错误

系统级别的异常 一般是内存用光了

运行时异常 RuntimeException 和错误 Error 都能被捕捉

运行时异常与非运行时异常的区别?

运行时异常是不可查异常,不需要对其进行显式的捕捉

非运行时异常是可查异常,必须要对其进行显式的捕捉,抛出,不然编译器会报错不允许程序运行.

Throwable

Throable 是类 ExceptionError 都继承了该类

捕捉得时候也可以使用Throwable 进行捕捉


I/O 异常处理

File f = new File("D:/LoLFolder");

File f1 = new File(f,"LoL.exe");

f.exists()

判断是否存在

f.isDirectory()

是否是文件夹

f.isFile()

是否是文件

f.length() long

返回long类型 byte字节

f.renameTo()

改名 当且仅当改变成功了返回true

        File f = new File("d:/LOLFolder/skin/garen.ski");

        // 以字符串数组的形式,返回当前文件夹下的所有文件(不包含子文件及子文件夹)
        f.list();

        // 以文件数组的形式,返回当前文件夹下的所有文件(不包含子文件及子文件夹)
        File[]fs= f.listFiles();

        // 以字符串形式返回获取所在文件夹
        f.getParent();

        // 以文件形式返回获取所在文件夹
        f.getParentFile();
        // 创建文件夹,如果父文件夹skin不存在,创建就无效
        f.mkdir();

        // 创建文件夹,如果父文件夹skin不存在,就会创建父文件夹
        f.mkdirs();

        // 创建一个空文件,如果父文件夹skin不存在,就会抛出异常
        f.createNewFile();
        // 所以创建一个空文件之前,通常都会创建父目录
        f.getParentFile().mkdirs();

        // 列出所有的盘符c: d: e: 等等
        f.listRoots();

        // 刪除文件
        f.delete();

        // JVM结束的时候,刪除文件,常用于临时文件的删除
        f.deleteOnExit();

集合与框架

Iterator 遍历

ArrayList implements List

容量逐渐增加 capacity

LinkedList

双向链表结构 Deque

Queue FIFO

offer 最后加

poll 取出第一个

peek 查看第一个

HashMap

键值对

key 唯一 不可重复 相同的key加入会覆盖上一次的

HashSet

元素不可重复

无具体顺序

Collection

接口

Collections

类 是容器的工具类

swap 交换
reverse 反转
shuffle 混淆
sort 排序
rotate 滚动 类似平移
synchronizedList 线程安全

比较

ArrayList HashSet
顺序 有顺序 无顺序
重复 可以重复 不能重复(Hashcode - equals)
ArrayList LinkedList
速度 插入 删除 插入 删除
解释 顺序结构 进行定位即可 链表结构 需要逐渐的找 速度慢
HashMap HashTable
存放null 可以 不可以
线程 不是线程安全 线程安全
HashSet LinkedSet TreeSet
顺序 无序 插入顺序 从小到大

—–hashcode概念—–
所有的对象,都有一个对应的hashcode(散列值)
比如字符串“gareen”对应的是1001 (实际上不是,这里是方便理解,假设的值)
比如字符串“temoo”对应的是1004
比如字符串“db”对应的是1008
比如字符串“annie”对应的也**是1008**

—–保存数据—–
准备一个数组,其长度是2000,并且设定特殊的hashcode算法,使得所有字符串对应的hashcode,都会落在0-1999之间
要存放名字是”gareen”的英雄,就把该英雄和名称组成一个键值对,存放在数组的1001这个位置上
要存放名字是”temoo”的英雄,就把该英雄存放在数组的1004这个位置上
要存放名字是”db”的英雄,就把该英雄存放在数组的1008这个位置上
要存放名字是”annie”的英雄,然而 “annie”的hashcode 1008对应的位置已经有db英雄了,那么就在这里创建一个链表,接在db英雄后面存放annie

—–查找数据—–
比如要查找gareen,首先计算”gareen”的hashcode是1001,根据1001这个下标,到数组中进行定位,(根据数组下标进行定位,是非常快速的) 发现1001这个位置就只有一个英雄,那么该英雄就是gareen.
比如要查找annie,首先计算”annie”的hashcode是1008,根据1008这个下标,到数组中进行定位,发现1008这个位置有两个英雄,那么就对两个英雄的名字进行逐一比较(equals),因为此时需要比较的量就已经少很多了,很快也就可以找出目标英雄
这就是使用hashmap进行查询,非常快原理。

空间换时间



Codes   Learning Java
本文作者:Ge15emium
版权声明:本博客所有文章除特别声明外,均采用 CC BY-SA 3.0协议 。转载请注明出处!