【Java学习笔记(三)】变量、方法和初始化块

变量

Java中的变量

  • 根据定义位置的不同,可以将变量分为两大类:成员变量和局部变量。这两种变量的运行机制存在较大的差异
  • 成员变量
    • 成员变量是指定义在类里定义的变量,即字段(field)
    • 成员变量又分为类变量和实例变量
      • 类变量:用static修饰的成员变量
        • 类变量从该类的准备阶段开始就存在,知道系统完全销毁这个类,类变量的作用域与这个类的生存范围相同
      • 实例变量:没有static修饰的成员变量即实例变量
        • 实例变量则从该类的实例被创建开始存在,知道系统完全销毁这个实例,变量的作用域与对应实例的生存范围相同
    • 成员变量的初始化和内存中的运行机制
      • 当系统加载类或创建类的实例时,系统自动为成员变量分配内存空间,并在分配内存空间后,自动为成员变量指定初始值
      • 可以通过对象名.类变量的语法格式来访问类变量,但是这样会产生歧义,降低程序的可读性,因为类变量最好使用类名.类变量的语法格式访问
  • 局部变量
    • 在方法里定义的变量
    • 根据定义形式的不同,可以分为三种
      • 形参
        • 整个方法内有效
      • 方法局部变量
        • 从开始定义的地方到方法结束时有效
      • 代码块局部变量
        • 从开始定义的方法到代码块结束时有效
    • 局部变量的初始化和内存中运行的机制
      • 局部变量定义后,必须经过显示初始化后才能使用,系统不会对局部变量执行初始化。
      • 定义局部变量后,系统并未为这变量分配内存空间,直到等到程序为这个变量赋初值时,系统才会为局部变量分配内存,并将初值保存到这块内存中
      • 局部变量不属于任何类或实例,因此它总是保存在其所在方法的栈内存中。如果局部变量是基本类型的变量,则直接把这个变量的值保存在该变量对应的内存中;如果局部变量是一个引用类型的变量,则这个变量里存放的是地址,通过该地址引用到该变量实际引用的对象或数组
  • Java允许局部变量和成员变量同名,如果方法里的局部变量与成员变量同名,局部变量会覆盖成员变量,如果需要在这个方法里引用被覆盖的成员变量,则可使用this(对于实例变量)或类名(对于类变量)作为调用者来限定访问成员变量
  • 变量的使用规则
    • 变量的作用范围扩大的害处
      • 增大了变量的生存时间,这将导致更大的内存开销
      • 扩大了变量的作用域,这不利于提高程序的内聚性
    • 以下几种情形,则应该考虑使用成员变量
      • 如果需要定义的变量是用于描述某个落或者某个对象的固有信息;这种信息对这个类的所有实例完全相同,或者说是类相关的,则定义成类变量,如果信息是实例相关的,则定义成实例变量
      • 如果在某个类中需要一个变量来保持该类或者实例运行时的状态信息则通常应该使用成员变量
      • 如果某个信息需要在某个类的多个方法之间进行共享,则这个信息应该使用成员变量
    • 即使在程序中使用局部变量,也应该尽可能地缩小局部建立的作用范围,局部变量的作用范围越小,它在内存里停留的时间就越短,程序运行性能就越好

静态属性

(此部分内容引用自:nianzhilian的博文,有一定的修改和补充)

  • 简介
    • 静态属性和方法必须用static修饰符
    • static可以修饰属性、方法、代码块、内部类
  • 静态属性和非静态属性的区别
    • 在内存中存放位置不同,静态属性或者方法存放在内存中的方法区,而非静态属性存放在内存中的堆区
    • 出现时机不同,静态属性或方法在没创建对象之前就已经存在,而非静态属性在创建对象后才存在
    • 静态属性是在某个类中的所有对象是共享的
    • 声明周期不同 静态属性在类消失之后才销毁,而非静态属性在对象销毁之后才销毁
  • 用法
    • 静态属性可以直接通过类名访问,非静态属性不可
    • 二者的相同点是都可以在创建完对象后使用
  • 注意事项
    • 带有静态修饰符的方法只能访问静态属性
    • 非静态方法既能访问静态属性也可以访问非静态属性
    • 非静态方法不能定义静态变量
    • 静态方法中不可以使用this关键字
    • 静态方法不能调用非静态方法,反之可以

方法(method)

方法的基本定义

  • 修饰符 返回值类型 方法名(参数列表){ return返回值}
  • 方法可以广义非的分为两大类
    • Getter方法
    • Setter方法

方法的参数传递机制

  • 方法中的形参与实参
    • 形参变量隶属于方法体,是方法的局部变量,在方法被调用时才被创建分配内存,调用结束后立即释放分配的内存单元
    • 在调用方法时,实参和形参必须完全匹配
  • 在Java中,方法的参数传递方式只有一种:值传递
  • 值传递的两种情形
    • 基本数据类型的传递
      • 传入实际参数值的副本(复制品),参数本身不会受到任何影响
    • 引用数据类型的传递
      • 此时传递的也是值,但是这个值是内存地址,可以理解成——此时传递的是引用数据类型的指向,因此如果此时方法内对指向的对象所包含的变量进行操作修改时,原来的实参引用型变量所指向的对象包含的变量也会发生改变

形参个数可变的方法

  • 在JDK1.5之后,Java允许定义形参数量可变的参数,从而允许方法指定数量不确定的形参
  • 定义语法
    • 修饰符 返回值类型 方法名(param1,param2,String… param3)
      { return返回值}
    • 此时param3会当成一个String类型的数组来处理,param只能写在形参列表的最后,也就是说,一个方法最多允许一个个数可变的形参

方法的重载

  • 方法的名称及其参数列表一起构成方法的签名。可用于区分不同的方法,这种机制叫做方法的重载

构造方法(Constructor)

  • 构造方法又叫构造器,是一种特殊的方法。它与普通方法的差别在于,它是专用语在构造对象时初始对象成员的,其名称和其所属类名相同
  • class 类名称 { 访问权限 类名称(类型1 参数1,类型2 参数2,…)//构造方法 {程序语句;//构造方法没有返回值} }
  • 注意事项
    • 构造方法名称与所属类名必须一致
    • 没有返回值,也不可以使用void
    • 也可以被重载
    • 不能用static和final修饰
    • 不能被继承
  • 使用构造方法执行初始化
    • 构造方法最大的用处就是在创建对象时执行初始化。当创建一个对象时,系统为这个对象的实例变量进行默认初始化,如果想改变这种默认的初始化,就可以通过自定义构造方法来实现
    • 在没有定义构造方法时,系统会自动定义“隐式的”构造方法,在定义了有参的构造方法时,则创建相关类的对象时必须加入参数,或者增加一个无参的构造方法
  • 构造方法的重载
    • 同一个类里具有多个构造方法,它们的形参列表不同,即称为构造方法的重载
    • 如果存在多个构造方法时,可以通过使用this来调用其它构造方法的初始代码
      • 例如:
        public class Person{
           private String name;
           private String sex;
           private int age;
           public Person(){}
           public Person(String name,int age){
            this.name=name;
            this.age=age;  
           }
           public Person(String name,String sex,int age){
            this(name,age);//调用带有着两个形参的构造方法的初始化代码
            this.sex=sex;
           }
        }        
        
      • 这种方法只能在构造方法里面使用,而且必须作为构造方法执行体的第一条语句,使用this调用重载的构造方法时,系统会根据this后括号里的实参来调用形参列表与之对用的构造方法
      • 应该尽量避免重复代码出现,充分利用每一段代码,既可以让程序代码更加简洁,也可以降低软件的维护成本
  • 构造方法的私有化
    • 如果构造方法被private修饰,那么其他类中就无法调用该构造方法,也就是说,在本类之外,不能通过new关键字调用该构造方法创建该类的实例化对象
    • 可通过增加共有方法的方式去调用私有方法,方法与方法可以相互调用
  • 方法的递归调用
    • 递归方法求解可分为为回推和递推
    • 递归操作虽然可以大大减少代码量,但递归操作的运行速度比不用慢,而且容易陷入死循环,一定要设置递归操作的终止条件;

方法与数组

  • 数组引用传递
    • 定义两个数组a和b,b=a,就是将a起个“别名”b,a和b就此指向同一个对象
    • 在Java中,这种变量去别名的机制称之为引用
    • 给地址取个名称,就是引用变量,引用变量存储在一块名叫做“堆内存”的区域
    • 在Java中不允许直接修改内存,所有的对象都是通过引用就行操作的,数组就是一种对象
    • 数组引用传递,就是将一块数组的堆内存空间交由多个栈内存所指向
  • 在方法中实现排序
  • 让方法返回数组

与数组有关的操作方法

  • 数组的克隆
    • 数组名.clone()
    • 复制数组的整个元素,返回一个新的引用
    • 属于java.lang.Object类
  • 数组的排序
    • java.util.Arrays.sort(数组名)

初始化块(代码块)

初始化块,又叫代码块,是Java类里可出现的第四种成员(前面依次有成员变量、方法和构造器),一个类里可以有多个初始化块,相同类型的初始化块之间有顺序;前面定义的初始化块先执行,后面定义的初始化块后执行

语法格式:

[修饰符] {
//初始化块的可执行代码
...
}
  • 修饰符只能是static,使用static修饰的初始化块被称为静态初始化块。
  • 初始化块里的代码可以保护任何可执行语句,包括定义局部变量、调用其它对象的方法,以及使用分支、循环语句等

方法就是一种重复调用的代码块

初始化块虽然也是Java类的一种成员,但它没有名字,也就没有标识,因此无法通过类、对象来调用初始化块。初始化块只在创建Java对象时隐式执行,而且在执行构造器之前执行

初始化代码块和构造方法

  • 初始化块只是一段固定执行的代码,它不能接受任何参数。因此如果有一段初始化处理代码对所有对象完全相同,且无须接受任何参数,就可以把这段初始化代码放在初始化代码块中
  • 实际上初始化块是一个假象,使用javac命令编译Java类后,该Java类中的初始化代码块会消失,其中代码会被“还原”到每个构造器中,且位于构造器代码的前面

种类

  • 普通代码块
    • 在方法名后或者方法体内,生命周期仅限于{}内
  • 构造代码块
    • 在类中直接定义的代码块,没有任何前缀、后缀以及修饰符的代码块;构造代码块不在任何方法之内,仅位于类的范围内,它的地位和其他方法体是对等的,可以理解为构造代码块是没有名称的方法体,仅限用于对类数据成员的初始化,且仅运行一次;构造代码块内的代码比构造方法先执行,可用于包含多个构造方法相同的代码部分
  • 静态代码块
    • 使用static关键字修饰的代码块,主要用于初始化静态成员变量,是最早执行的代码块,此代码块中的变量都是静态成员变量
  • 同步代码块
    • 暂略

人已赞赏
Java编程语言

【Java学习笔记(二)】类与对象&面向对象的三大特点

2020-2-21 18:14:58

DemoJava编程语言

【Java Demo】①. 将人民币数值转换为大写字符串

2020-3-1 15:20:30

0 条回复 A文章作者 M管理员
    暂无讨论,说说你的看法吧
个人中心
今日签到
有新私信 私信列表
搜索