• JAVA 必须掌握技能(三)-Java 基础知识


    版权声明:本文为CSDN博主「iswitched」的原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接及本声明。
    原文链接:https://blog.csdn.net/weixin_44873106/article/details/89787021

    1 环境变量配置

    JAVA_HOME:jdk路径
    Path:要把jdk的bin目录路径,添加到path变量

    2.八种数据基本类型

    比较简单此处不单独罗列
    引用数据类型:数组,类,接口
    2.1 char :Unicode编码的字符,或字符的整数编码,必须用单引号
      float默认值是0.0f;
      double默认值是0.0d;
    2.2基本类型字面值规则
      1.整数字面值是int类型,如果右侧赋值超出int范围,需要做转型处理
      2.byte,short,char 三种比int小的整数,在自身范围内可以直接赋值。 byte d=1+3 正确,1+3编译器会自动转成4
      3.浮点数字面值是double;浮点数转成整数会直接舍弃小数点后位数。
      4.字面值后缀,L D F
      5.字面值前缀,0b 二进制;0x 16进制;0 8进制; u char 类型16进制
    2.3基本类型的运算规则
      1.计算结果的数据类型与运算中的最大类型一致。
      2.byte,short,char三种比int小的整数,计算时会自动转成int 做加法运算时,数据类型会自动转成int,除了自增加自减不进行转化外,其它情况都是无long型时,所有非int类型转成int类型;有long类型时,都转成long类型。 char类型相加,提升为int类型。   

      3.整数运算溢出。Integer.MAX_VALUE+1 得负数最小值
      4.浮点数运算不精确
      5.浮点数特殊值 infinity 整数除0 ;Nan 负数开方
    2.4 基本类型的类型转换
      数字类型之间可以互相转换,从小到大自动转换,从大到小需要强制转型。
      double d = 245; float d=100;自动转型

    2.5运算符
      && :逻辑与(短路与),两边同为真结果才为真,短路与:左边是假,右边忽略不执行
      & :不管左边结果是什么都要执行右边(&的左右两边都要参与运算)
      || :逻辑或(短路或),两边只要有一个真结果就是真,短路或:左边是真,右边忽略不执行

    3.流程控制

    3.1 switch:只能判断byte short char int enum jdk1.7之后的string。
      从成立的case 无条件穿透所有的case包括default直到结束或者遇到break中断跳出循环;
      如果所有条件都不成立,则执行default

    3.2 for循环

    3.3 break 和 continue
      Break 中断、跳出循环和switch
      Continue 跳过后面的代码 继续进入循环的下一轮执行
    3.4 for-each循环

      数组遍历、集合迭代遍历的语法简化

    4.面向对象 —— 封装、继承、多态 ★ ★ ★ ★ ★

    封装
      1 类:模板、图纸 。类中定义对象的属性数据(成员变量),方法(成员方法)类第一次使用时会加载到方法区
      2 对象:从模板中创建的具体实例,实例是数据的打包
        新建实例时,在堆内存中新分配内存空间给这个实例

      3引用变量:理解成“遥控器”,保存一个实例的内存地址(引用变量保存在栈),引用变量的特殊值:null 不保存任何实例的内存地址

      4构造方法:新建实例对象时,立即执行的一个特殊方法;构造方法必须和类同名,并且没有返回值类型。
        一个类中必须有构造方法,自己没定义,系统会添加默认构造方法,构造方法一般用来给属性赋值

      5 构造方法重载

      一个类中可以定义多个不同参数的构造方法,是方法重载的一种体现

      6 方法重载Overload:

      同名不同参,与返回值类型无关,所有方法都可以重载7 this关键字:this.xxx 特殊引用,引用当前对象的地址
      this(…):构造方法之间的调用,必须是首行代码,如果有多个构造方法,会通过this(…)调取下面的所有构造方法,完成赋值。
      注意this不能在静态方法中使用
    继承
    Java的继承是单继承多实现,只能继承一个父类(如果不继承其他类,默认继承object类),但可以实现多个接口
      1.不能继承的有:构造方法,私有成员
        过程:先新建父类对象,再新建子类对象,两者作为一个整体对象,调用成员时,先找子类,再找父类
      2.方法重写:override
        继承的方法,在子类中重新定义父类中的方法(只能在子类重写),方法名相同,参数的个数和类型也必须相同,返回值类型也必须相同。
        方法重写返回值类型如果是基本类型应与父类的一致;重写要求方法名完全相同,返回值类型如果是基本类型或无返回值时必须一致。
      3.父类的构造方法
        新建子类对象时会先新建父类对象,也会先执行父类的构造方法
        默认执行父类的无参构造,默认隐含调用super();
        new Student() 默认执行父类无参构造
        new Student(……)默认执行父类无参构造
        手动调用父类的有参构造,super(参数):父类没有无参构造时必须手动调用
      4.super
        Super.xxxx() 方法重写时,调用父类中同一个方法的代码
        Super(参数) 调用父类的构造方法,默认调用父类无参构造super(),手动调用有参构造super(),必须是首行代码
        注意super不能在静态方法中使用
    多态
    一个对象具有多种形态的表现,多态的前提是必须有继承。
    void f(父类型 o1) { }
    把一个子类型的实例当做父类型来处理,所有的子类型都可以传递到该方法,被当做父类型处理;作用:一致的类型
    1. 类型的转换
      A. 向上转型
        子类的实例转成父类型,用父类型的引用变量,来引用子类实例,向上转型后,只能调用父类定义的通用成员,子类特有成员被隐藏
      B. 向下转型
        已经转成父类型的子类实例,转回子类型为了对子类型进行特殊处理
    2. Instanceof 运行期类型识别
      当多种子类型都被当做父类型来处理,要对某种子类型进行特殊处理,可以先判断其真实类型再向下转型——对真实类型,及其父类型判断,都返回true。格式:

    s instanceof Line 

    5.数组
      属于object类,用来存放一组数据的数据结构,数组是最基本的一种数据结构但不是基本数据类型,数组是相同数据类型组成的集合,数组中的元素按线性顺序排序
    1 数组的创建
      数组创建后若未指定初始值,则会依据数组类型的不同来设置默认值

    int[] a = new int[6];
    // 新建int[]数组,长度6,默认值都是0,数组的起始地址值保存在变量a。
    
    int[] a = {6,2,6,8};
    Int[] a= new int[]{1,2,3,4,5};
    a = new int[]{7,3,8,1,7,9,3,1};
    // 为存在的数组变量赋值直接初始化数据,要添加数据类型

    2 数组的长度属性 a.length
      数组一旦创立,长度不可变
      最大下标 a.length-1
      允许0长度的数组
    3 二维数组
      存放数组的数组

    int[][] a = new int[3][2];

    外围长度为3,内部3个数组长度为2,一共有4个数组,内部数组默认值0,外围数组保存的是内部数组的地址。

    int[][] a = new int[3][];

    只建一个外围数组长度3,3个位置都是null,之后可以建新数组放入内部。

    4 Arrays 数组工具类

    Arrays.toString //(数组) 把数组数据连接成字符串。
    Arrays.sort //(数组) 数组排序 基本类型:优化的快速排序;引用类型:优化的合并排序。
    Arrays.binarySearch //(数组,目标值) 二分法查找,在有序数组中查找目标值下标,找不到返回 -(插入点+1)。
    Arrays.copyof // (数组,长度) 复制数组成一个指定长度的新数组。

    5 数组 复制

    Arrays.copyof // (数组,长度) 复制数组成一个指定长度的新数组
    System.arraycopy // (原数组,原数组起始位置,目标数组,目标数组起始位置,复制的数量) ——不会创建新的数组,目标数组要事先存在。

    6. 变量

    // 1 局部变量:定义在方法中或局部代码块中,必须初始化(第一次赋值时分配内存空间)
    // 局部变量的作用域在定义它的大括号内有效,在作用范围内不能重复定义。
    // 2 成员变量:定义在类中,自动初始化默认值,访问受访问控制符限制;局部变量可以和成员变量同名。

    7.Object类

    如果一个类不继承其他类,则默认继承Object类
    1.方法

    toString() // 获得一个对象的字符串表示。
    // Object中的默认实现是:“类名@地址”可在子类中重写toString方法。
    equals() // 当前对象与参与对象比较是否相等。
    a.equals(b) // Object中的默认实现是比较内存地址。
    // this == obj:==
    // Object中比较内存地址,基本类型默认比较内容值。

    8.String 类

    String是封装char[] 数组的对象

    S =”abcd”
    S={-value:[‘a’,’b’,’d’,’g’]}

    1.字符串创建

    Char[] a ={‘a’,’b’,’c’};
    String s = new String(a); >>>简易语法>>> String s = “abcd”

    2.字符串的常量池

    String s1 = “abcd”  // 字符串的字面值写法。第一次使用一个字符串字面值时,会在字符串常量池中新分配内存,再次使用相同字面值时,直接访问常量池中存在的对象,而不会重复创建

    3.字符串 中的Equals 和 “==”

    // “==”比较内存地址
    // Equals 看父类中的方法,object中的默认方法是比较内存地址,String类中重写了父类方法比较的是字符内容。如下说明:
    
    char[] a = {'a','b','c','d'};
    String s1 = new String(a);//堆中新分配内存
    String s2 = "abcd"; //在常量池新分配内存
    String s3 = "abcd"; //访问常量池中存在的对象
    System.out.println(s1==s2); //false 比较内存地址
    System.out.println(s2==s3); //true 比较内存地址
    String类中重写了equals方法,方法中比较的是字符内容
    System.out.println(s1.equals(s2));//true 比较字符串内容
    System.out.println(s2.equals(s3));//true 比较字符串内容

    4.字符串不可变且字符串连接效率低,每次连接都会新建字符串对象
    5.字符串的常用方法

    charAt(i)  // 获取指定位置的字符
    length()  //  字符串长度,字符的数量
    indexof()  // 找第一个子串出现的初始位置,找不到返回-1
    indexof  // (子串,start)从执行位置向后找
    lastIndexof(子串)   // 从后向前找
    subString(start)  // 截取start到末尾
    subString(start,end )  // 截取(start,end )范围
    trim()  // 去除两端的空白字符
    matches()  // 用来判断是否匹配正则表达式

    6.StringBuilder: 可变的字符序列,封装char[]数组,提供了一组方法,可以对内部封装的字符进行修改,常用来代替字符串做高效的字符串连接

    append()//  追加字符内容,内部数组默认初始容量16,放满后翻倍+2;
    delete(start,end) //  删除区间(start,end);
    deleteCharAt(i)//  删除指定位置 i;
    insert(i,内容) //  在指定位置插入内容;
    insertCharAt(i,字符)//  在指定位置插入单个字符;
    replace(start,end,内容)//  替换指定范围的内容;
    
    //  StringBuilder和StringBuffer
    //  StringBuilder:线程不安全,效率高;JDK1.5版本后的新类。
    //  StringBuffer:线程安全,旧版本的类。

    9.正则表达式
    一般用来判断用户的输入内容是否符合格式要求

    matches()// 字符串的方法,用来判断是否匹配
    if(s.matches(regex)) {}
    split(正则):// 用匹配的子串来拆分字符串
    String s = "aaa,bbb,ccc";
    String[] a = s.split(",");

    replace(正则,子串)替换所有匹配的子串

    10.基本类型的包装类

    // 把基本类型当做对象来使用
    byte –    Byte
    short –    Short
    int –    Integer
    long    –    Long
    float    –    Float
    double –    Double
    char    –    Character
    boolean –    Boolean

    1. 数字父类Number

    // 子类:Byte,Short,Integer,Long,Float,Double,BigDecimal,BigInteger
    // 取出基本类型值的方法
    byteValue(),shortValue(),intValue(),longValue(),floatValue(),doubleValu()

    2. Intger类

    // 创建Integer对象: a= { value:6}
    Integer a = new Integer(6);
    Integer a = Integer.valueOf(6);
    // Integer 类中存在256个Integer缓存对象,封装-127到128;如果访问指定范围内的值,会访问缓存对象,如果超出范围,会新建对象。

    3. Integer类的方法

    // 字符串解析成int
    Integer.parseInt();
    Byte.parseByte();
    Integer.toBinaryString() // 转成二进制字符串
    Integer.toOctalString()  // 转成八进制字符串
    Integer.toHexString(255) // 转成十六进制字符串

    4. BigDcimal和BigInteger 类
    BigDcimal精确的浮点数运算
    BigInteger 超大的整数运算

    创建对象:

    BigDecimal bd = BigDecimal.valueOf(2);
    // 方法:
    add(BigDecimal bd)
    subtract(BigDecimal bd)
    multiply(BigDecimal bd)
    divide(BigDecimal bd)
    divide(BigDecimal bd,保留位数,舍入方式)
    setScale(保留位数,舍入方式)

    5. 自动装箱,自动拆箱

    // 基本类型值,自动装箱成包装对象
    // Integer a = 6; 编译器编译成: Integer a = Integer.valueOf(6);
    
    // 自动拆箱(自动拆箱要注意null值)
    // int i = a; 编译器编译成:    int i = a.intValue();

    11.抽象类
    半成品类,没有完成的类;抽象方法:没有代码,只有方法的定义,抽象类不能创建实例,主要用来被继承。

    public abstract void f();
    //包含抽象方法的类一定是抽象类
    
    public abstract class A { };

    抽象方法的作用:
    作为通用方法,在父类中定义;要求子类,必须实现这个方法。
    1)抽象类可以有自己的构造方法
    2)抽象类可以有具体的方法
    3)包含抽象方法的类一定是抽象类,必须使用abstract关键字修饰,这个方法必须由子类来实现。
    4)抽象类不能使用new关键字来创建实例
    5)当一个类中只要有一个抽象方法,这个类就必须是抽象类
    6)抽象类可以定义实例变量和静态变量以及常量
    7)抽象类可以再继承抽象类,也可以继承普通的类

    12.关键字 final
    内存地址不可变,可以修饰常量、类、方法
    1. final 常量:值不可变,但引用类型因为保存的是地址,所以内容可以变。

    final Point a = new Point(3,4);
    a.x = 30;//
    a.y = 40;//

    2. final 方法不能在子类重写,但可以被继承。;final不能用于修饰构造方法,父类的private成员方法是不能被子类方法覆盖的,因此private类型的方法默认是final类型的。
    3. final 类 不能被继承,没有子类
    Static — 静态 共享的数据
    静态成员属于类,而不属于实例

    静态成员
    用类来调用静态成员 Soldier.count
    实例成员
    用实例来调用实例成员 s1.id
    工具方法
    Math.Random() Arrays.toString() String.valueOf()
    静态方法中不能直接调用实例的成员(非静态),只能用实例调用

    class A {
        public static void main(String[] args) {
            f();//静态调静态
        }
      static void f() {
        g();//错,静态不能直接调用非静态
        A a = new A();
        a.g();//只能用实例调用
      }
      void g(){
      }
    }        

    静态初始化块

    class A {
      static {
        // 静态初始化块
        // 类被加载时,只执行一次
      }
    }

    静态变量保存在方法区类的空间中,只保存一份可以在所有实例中共享的数据

    对象的加载过程
    加载类

    • 1.加载父类,为父类静态变量分配内存 – 后台执行不可见
    • 2. 加载子类,为子类静态变量分配内存
    • 3. 执行父类静态变量的赋值运算,和静态初始化块
    • 4. 执行子类静态变量的赋值运算,和静态初始化块

    新建实例

    • 5. 新建父类实例,为父类实例变量分配内存
    • 6. 新建子类实例,为子类实例变量分配内存
    • 7. 执行父类的实例变量赋值运算
    • 8. 执行父类的构造方法
    • 9. 执行子类的实例变量赋值运算
    • 10. 执行子类的构造方法

    13.集合

    用来存放一组数据的数据结构
    数组的缺点: 长度固定 ; 访问方式单一只能下标访问; 前面增删数据操作繁琐
    集合的继承结构:

    • Collection 是对象集合, Collection 有两个子接口 List 和 Set,
    • List 可以通过下标 (1,2…) 来取得值,值可以重复,而 Set 只能通过游标来取值,并且值是不能重复的
    • ArrayList , Vector , LinkedList 是 List 的实现类
    • ArrayList 是线程不安全的, Vector 是线程安全的,这两个类底层都是由数组实现的
    • LinkedList 是线程不安全的,底层是由链表实现的
    • Map 是键值对集合
    • HashTable 和 HashMap 是 Map 的实现类
    • HashTable 是线程安全的,不能存储 null 值
    • HashMap 不是线程安全的,可以存储 null 值

    ArrayList
    数组列表,封装了一个数组,及其操作代码和更便捷的方法,内部数组默认初始容量10 放满后,1.5倍增长
    方法
    add(数据)— 添加数据;get(int i)—访问指定下标数据; remove(int i)移除指定位置数据,返回被移除的数据; remove(数据)— 找到第一个相等的数据,找到移除并返回true,找不到返回false; size() 元素的数量;iterator() 辅助新建迭代器
    效率
    访问任意位置效率高,增删数据效率可能降低

    LinkedList — 双向链表
    方法
    和ArrayList有相同的方法

    1. LinkedList 两端数据操作方法
    2. addFirst(数据);addLast(数据);getFirst();getLast();removeFisrt()
    3. removeLast()
    4. 效率

    两端效率高
    HashMap — 哈希表、散列表 (面试必问) ★ ★ ★ ★ ★
    存放键值对数据,用键来快速定位数据,来提取键对应的值
    键:不重复,无序

    1. Hashmap中的key-value都是储存中entry数组中的
    2. Hashmap的实现不是同步的,意味着它不是线程安全的
    3. Hashmap的实例有两个参数影响其性能:初始容量,和加载因子
    4. 方法
    5. put(key,value)放入键值对数据,重复的键会覆盖旧值
    6. get(key)获得键对应的值,键不存在,得到null
    7. remove(key)移除键值对数据,返回被移除的值
    8. size()键值对的数量

    哈希运算过程

    HashMap内部,使用entry[]数组存放数据

    • 数组默认初始容量16
    • 放满后容量翻倍+2
    • key.hashCode()获得键的哈希值
    • 用哈希值和数组长度,运算产生下标值 i
    • 新建entry对象来封装键值对数据
    • Entry对象,放入i 位置
    •  如果是空位置,直接放入
    •  如果有数据,一次equals()比较是否相等
    •  找到相等的,覆盖旧值
    •  没有相等的,链表连接在一起
    •  负载率、加载因子超过0.75
    •  新建翻倍容量的新数组
    •  所有数据,重新执行哈希值,存入新数组
    •  Jdk 1.8
    •  链表长度到8,转成红黑树
    •  树上的数据减少到6,转回成链表

    hashCode()
    hashCode()是object的方法,默认实现是用内存地址作为哈希值
    可以重写方法来获得相同的哈希值
    哈希运算中要有相同的哈希值,才能保证计算出相同下标值,并且要equals()也要相等(equals方法也要重写),才可以覆盖旧值,否则会链表连接。
    重写hashCode的惯用算法:(x.y是变量的值)


    14.异常
    封装错误信息的对象
    错误信息:类型、提示消息、行号
    异常的继承结构

    捕获异常

    try {
      } catch(AException e) {
      } catch(BException e) {
      } catch(父类型Exception e) {
      } finally {
        // 不管出不出错,都会执行
    }

    如果抛出异常,并且中catch中有return语句,这个return语句会先执行,执行之后将结果保
    存在缓存中,再去查看是否有finally,如果有finally就先执行finally语句,之后再返回缓存中
    return的值,如果finally中也有return,那么finally中的return会覆盖掉之前缓存中的return,
    即最终会返回finally中的return值

    throw 手动抛出异常,执行异常的抛出动作 类似 return;当程序出现逻辑错误,不自动创建并抛出异常,可以手动判断逻辑错误,手动创建异常对象并抛出。
    底层的异常往上层抛,在上层处理

    if(...) {
      AException e = new AException();
      throw e;
    }

    异常包装

    • 捕获的异常对象,包装成其他类型再做抛出,多种类型简化成一种类型,不能抛出的异常包装成能抛出的异常再抛。
    • RuntimeException 和 其他Exception
    • RuntimeException— 非检查异常,编译器不检查是否有异常处理代码,存在默认的抛出管道
    • 其他异常 — 编译器检查是否有处理代码,不处理,不能编译。

    15.接口
    极端的抽象类,结构设计工具,用来解耦合,隔离现实
    Implements代替extends
    Interface 代替class
    接口的定义:
     公开的抽象方法  公开的常量  公开的内部类、内部接口

    • 1)接口只能定义常量
    • 2)接口只能定义抽象方法
    • 3)接口只能继承接口,不能继承普通的类和抽象类
    • 4)接口是没有构造方法

    注意:

    • 1)在接口中定义常量时,可以不用final static修饰,因为编译器在编译时会自动加上。
    • 2)在接口中定义抽象方法时可以省略abstract关键字,编译器在编译时同样会加上。

    类可以同时继承多个接口

    class A implements X,Y,Z {}
    class A extends B implements X,Y,Z {}

    接口和接口的继承

    interface A extends X,Y,Z {}

    16.文件、字符操作流
    File
    封装一个磁盘路径字符串,提供了一组对文件、文件夹的操作方法,可以封装文件夹路径、文件路径、不存在的路径。 {path=“d:/abc”}
    方法

    • getName() 获取文件名
    • getPatrent() 获取父目录
    • getAbsolutePath()完整路径
    • length() 文件字节量,对文件夹无效,会返回假数据
    • isFile() 判断是否是文件
    • isDirectory()是否是文件夹

    创建、删除

    • createNewFile()新建文件,文件已存在不会新建,返回false;文件夹不存在会出现异常
    • mkdirs()逐层创建多层文件夹
    • delete()删除文件、空目录

    目录列表

    • list()得到String[] 包含所有文件名 [“a.txt”, “b.mp3”, “c.jpg”]
    • listFiles() 得到 File[],包含所有文件的封装的File对象 [{…}, {…}, {…}]

    流 Stream
    数据的读写操作(io操作),抽象成数据在管道中流动
    单方向流动

    • 输入流,只能用来读取数据(读入内存)
    • 输出流,只能用来输出数据(内存数据向外输出)

    只能从头到尾,顺序流动一次,不能反复流动,如果要重复流动,可以重新创建新的流

    InputStream,OutputStream
    字节流的抽象父类
    方法:

    • write(int b) 只输出int四个字节中,末尾的一个字节值 [1][2][3][4] —> [4]
    • write(byte[], start, length) 输出byte[] 数组中,从start开始的length个字节值
    • read() 读取一个字节值,补三个0字节,变成int [4] —> [1][2][3][4],读取结束后,再读取会返回 -1。
    • read(byte[] buff) 按数组的长度,读取一批字节值,存放到指定的数组中,并返回这一批的字节数量,读取结束后,再读取会返回 -1。
    • FileInputStream,FileOutputStream — 文件流
    • ObjectInputStream,ObjectOutputStream —对象序列化、反序列化

    序列化 把一个对象的信息,按固定的字节格式,变成一串字节序列输出

    方法:

    • writeObject(Object obj) 把对象变成一串字节序列输出
    • readObject() 读取序列化数据,反序列化恢复对象
    • Serializable 接口——被序列化的对象,必须实现 Serializable 接口

    不序列化的变量
    Static — 属于类,不随对象被序列化输出
    Transient —临时,只在程序运行期间,在内存中存在,不会被序列化持久保存
    字符编码

    • ASC-II 0到 127,英文、指令字符
    • iso-8859-1 Latin-1 西欧编码 ,把ASC-II扩展到255
    • CJK 编码 亚洲编码,中日韩
    • GBK 国标码 英文单字节,中文双字节
    • Unicode 万国码 常用表,双字节 生僻字 三字节或四字节
    • UTF-8 Unicode 的传输格式 Unicode Transformation format英文,单字节某些字符,双字节;中文,三字节;特殊符号,四字节

    Java的char类型是 Unicode
    Java的转码运算

    InputStreamReader,OutputStreamWriter
    字符编码转换流 OutputStreamWriter — 把Java的Unicode编码字符,转成其他编码输出
    InputStreamReader —读取其他编码字符,转成Unicode字符

    17.内部类

    • 定义在类内部、方法内部或局部代码块内部的类,用来辅助外部实例运算,封装局部数据,或局部的运算逻辑。
    • 非静态内部类、属于实例的内部类 非静态内部类实例,必须依赖于一个外部类的实例才能存在。
    • 静态内部类 静态内部类,与普通的类没有区别。
    • 局部内部类
    • 局部定义的类型,类似于局部变量,有作用范围,只能在局部代码块内使用这种类型

    局部内部类中,使用外面的局部变量,必须加 final,jdk1.8,缺省。

    匿名内部类

    Weapon w = new Weapon() {...};
    
    //{} - 匿名类
    //new - 新建匿名类的实例
    // Weapon - 父类型
    // () - super(),可传参数super(1,2,3)

    18.Java内存管理
    堆内存 用来存放由new创建的对象实例和数组。Java堆是所有线程共享的一块内存区域,在虚拟机启动时创建,此内存区域的唯一目的就是存放对象实例。注意创建出来的对象只包含属于各自的成员变量,并不包括成员方法。
    栈内存 保存的是堆内存空间的访问地址,或者说栈中的变量指向堆内存中的变量(Java中的指针)
    l 栈:保存局部变量的值,包括:1.用来保存基本数据类型的值;2.保存类的实例,即堆区对象的引用(指针)。也可以用来保存加载方法时的帧。常量池存在于堆中(1.7b后的新版本)。
    普通类型的变量在栈中直接保存它所对应的值,而引用类型的变量保存的是一个指向堆区的指针,通过这个指针,就可以找到这个实例在堆区对应的对象。因此,普通类型变量只在栈区占用一块内存,而引用类型变量要在栈区和堆区各占一块内存。
    方法区是各个线程共享的内存区域,它用于存储已被虚拟机加载的类信息、常量、静态变量、即时编译器编译后的代码等数据。

    19.线程
    在进程内部,并行执行的任务
    创建线程(两种方式)

    • 继承 Thread
    • 实现 Runnable

    继承 Thread
      编写 Thread 的子类,并重写 run() 方法。启动之后,自动运行 run() 方法中的代码
    实现 Runnable
      实现 Runnable 接口,实现它的 run() 方法,Runnable 封装在线程中执行的代码,新建线程对象时,把Runnable对象放在线程内,启动
    线程的状态

    线程的方法

    • Thread.currentThread() 获得正在执行的线程实例
    • Thread.sleep(毫秒值) 让正在执行的线程,暂停指定的毫秒值时长
    • getName(),setName() 线程名
    • start() 启动线程 interrupt() 打断线程的暂停状态
    • join() 当前线程暂停,等待被调用的线程结束
    • setDaemon(true) 后台线程、守护线程

    JVM虚拟机退出条件,是所有前台线程结束,当所有前台线程结束,虚拟机会自动退出
    不会等待后台线程结束 例如:垃圾回收器是一个后台线程。
    线程同步 synchronized
    让多个线程共享访问数据时,步调一致的执行。一个线程修改时,其他线程等待修改完成后才能执行;一个线程访问时,其他线程等待访问结束
    任何实例,都有一个“同步锁”,synchronized 关键字,要求一个线程必须抢到同步锁才能执行

    synchronized(对象) {
    // 共享的数据访问代码
    } // --抢对象的锁
    synchronized void f() {
    } // -- 抢当前实例的锁
    static synchronized void f() {
    }//  --抢类的锁


    生产者、消费者模型
    线程之间传递数据
    等待和通知方法必须在synchronized 代码内调用, 等待和通知的对象,必须是加锁的对象。

  • 相关阅读:
    小孩抓周
    psychology
    绝恋诗词
    一万小时定律
    王国维的人生三重境界
    2017年日历
    018 cisco 3560 MAC地址绑定
    017 SSH
    016 ppp authentication
    unity Tilemap
  • 原文地址:https://www.cnblogs.com/blmlove/p/12748197.html
Copyright © 2020-2023  润新知