• 面向对象中的变量和运行机制及自动装拆箱


    成员变量和局部变量及运行机制

    两者的区别在于定义变量的位置不同,运行的机制也有差异。成员变量定义在类中,局部变量定义在定义在方法中。

    成员变量分为类变量和实例变量两种,局部变量分为形参(方法内)、方法局部变量和代码块内局部变量,比如循环内的。
    变量分类
    类变量的生命周期和类一样,从类准备阶段开始,到完全销毁这个类,作用域则与类的生存范围相同。而实例变量从实例被创建起开始存在,直到实例被销毁,作用域对应实例作用域。可以发现,成员变量之所以称为成员变量,是因为其与所在的整体共存亡的。

    注意:类变量是属于类的,通过实例.类变量访问的依然是类变量,如果该实例修改了变量值,则其他实例访问时也将使用修改过的变量值。即访问了同一片内存区!

    与成员变量不同,局部变量除了形参外,都必须显式初始化;而上面的成员变量可以进行默认初始化,赋值规则与数组动态初始化时赋值规则相同。

    当通过类或对象调用某个方法时,系统1会在调用该方法栈区内为所有形参分配内存,并将实参值赋值给对应形参,即完成形参初始化。

    Java允许局部变量和成员变量同名,如果需要在方法内引用被覆盖的成员变量(局部变量和成员变量同名),可以使用this关键字。

    public class Test{
        public String name = "猴子";
        public static int age = 500;
        public void outPut(){
            String name = "悟空";
            System.out.println(name);//"悟空"
            System.out.println(this.name);//"猴子"
        }
        public static void main(String[] args){
            double age = 100000.0;
            System.out.println(age);//100000.0
            System.out.println(Test.age);//500
            new Test().outPut();
        }
    }
    

    成员、局部变量初始化及运行机制

    在类初始化或对象初始化时,系统会为成员变量分配内存空间,并指定默认初始值。需要关注的是,在创建一个对象时,不需要给类变量分配内存空间,只是为实例变量分配内存空间,因为类初始化时已经分配好了。在创建多个对象时,同样如此,也需要为实例变量分配内存空间,而且,实例变量是单个实例的,与类或其他实例无关。

    局部变量定义后,必须经过显式初始化后才能使用,系统不会为局部变量执行初始化,就不会为变量分配内存空间,直到变量被初始化。与成员变量不同,局部变量不属于任何实例或类,因此它被保存在所在的方法栈中。如果变量是基本类型的变量,则会把值直接保存在对应内存中;但是变量是引用类型,则它存放的是地址,地址是所引用的对象或数组的地址。

    局部变量的生命周期是和方法或代码块一致,但所在栈内存无需垃圾回收,因为局部变量只保存基本类型的值或引用,所以所占内存比较小。

    包装类

    基本数据类型不具备对象特性:无成员变量,方法被调用。但有些时候显得不那么好,比如方法需要object类型的参数,并且需要提供实际值,像2,3,4,这就麻烦了。Java提供了包装类概念,并为8种基本数据类型定义了引用类型(基本数据类型的包装类)。

    基本数据类型 包装类
    byte Byte
    short Short
    int Integer
    long Long
    char Character
    float Float
    double Double
    boolean Boolean

    上述除Character外,其他包装类可传入参数创建一个包装类对象,

    由于基本数据类型和包装类对象之间转换麻烦,JDK1.5提供了自动装箱和拆箱功能,去解决该问题。

    自动装箱:基本类型变量赋值给包装类(或者Object变量);自动拆箱:包装类对象赋值给基本类型变量

    Integer a = 5;//基本类型赋值给Integer对象
    Object b = true;//把布尔类型赋值给Object对象
    int c = a;//Integer对象拆箱赋值给基本类型
    

    虽然包装类是引用类型,但是实例是可以与数值比较的,比较时直接取出包装类的值进行比较。而包装类对象之间比较,只有指向同一对象时返回true。

    System.out.println(new Integer(1) == new Integer(1));//false
    Integer a = 6;
    Integer b = 6;
    System.out.println(a == b);//true,待会解释
    //注意,Integer数据范围在-128~127之间,若不在会重新创建实例
    

    从上面来看,系统将整数装箱成实例,会放入一个cache数组(长度为256,Java就是这样设计的)中缓存起来,以后如需自动装箱则直接指向数组元素(若在-128~127之间),即引用同一个实例对象。这样的缓存设计有利程序的运行性能,节省开销。

    字符串与基本类型的转换

    字符串转基本类型有两种方式:

    1. 包装类的parseXxx(String s)方法(除了Character包装类外)
    2. 对应的构造器方法,Xxx(String s)

    基本类型转字符串则使用String的多个重载valueOf方法。上述代码示例:

    String str = "123";
    int a = Integer.parseInt(str);//第一种方法
    int b = new Integer(str);//构造器创建对象,之后拆箱赋值给变量b
    //基本数据类型转字符串
    String str1 = String.valueOf(3.14159f);
    String str2 = String.valueOf(true);
    

    Java7、8增强包装类

    Java7开始为所有包装类提供静态的compare(v1,v2)方法,则可以通过该方法比较基本值的大小。比如:

    System.out.println(Boolean.compare(true,false));//1
    System.out.println(Boolean.compare(true,true));//0
    System.out.println(Boolean.compare(false,true));//-1
    

    Java8再次增强,开始支持无符号算术运算。如为Integer、Long增强了静态的toUnsignedString(int/long v)整型转化成无符号整数对应的字符串、toUnsignedString(int/long v,int radix)转化成指定进制无符号整数对应的字符串。

    无符号整数的二进制最高位不再当作符号位看,即最小值为0。例如-2,对应的无符号整数为252


    公众号: 菜鸡干Java
    流浪舟 https://index.maliaoblog.cn

  • 相关阅读:
    [iOS]UIDynamicAnimator动画
    [iOS]被忽略的main函数
    [iOS]app的生命周期
    vue 封装http请求时错误信息提示使用element-ui message,只提示一次
    angular8 Vue 导出excel文件
    python3 tornado api + angular8 + nginx 跨域问题
    ubutu tornado python3.7.5 nginx supervisor 部署web api
    angular cli 反向代理实现跨域
    angular8自定义管道、指令以及获取dom值
    angular cli 使用echarts
  • 原文地址:https://www.cnblogs.com/coderma/p/13697573.html
Copyright © 2020-2023  润新知