zoukankan      html  css  js  c++  java
  • 面向对象中的变量和运行机制及自动装拆箱

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

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

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

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

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

    当通过类或对象调用某个方法时,系统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

  • 相关阅读:
    Java Spring Boot VS .NetCore (十) Java Interceptor vs .NetCore Interceptor
    Java Spring Boot VS .NetCore (九) Spring Security vs .NetCore Security
    IdentityServer4 And AspNetCore.Identity Get AccessToken 问题
    Java Spring Boot VS .NetCore (八) Java 注解 vs .NetCore Attribute
    Java Spring Boot VS .NetCore (七) 配置文件
    Java Spring Boot VS .NetCore (六) UI thymeleaf vs cshtml
    Java Spring Boot VS .NetCore (五)MyBatis vs EFCore
    Java Spring Boot VS .NetCore (四)数据库操作 Spring Data JPA vs EFCore
    Java Spring Boot VS .NetCore (三)Ioc容器处理
    Java Spring Boot VS .NetCore (二)实现一个过滤器Filter
  • 原文地址:https://www.cnblogs.com/coderma/p/13697573.html
Copyright © 2011-2022 走看看