类的成员
对Java中类的成员,属性、方法、构造器、代码块、内部类的简要介绍
Author: Msuenb
Date: 2023-02-08
属性
-
语法格式
【修饰符】 数据类型 属性名 = 初始化值
修饰符有:private、缺省、protected、public、static、final...
-
示例
public class Person { private String name = "Tom"; private int age; }
成员变量与局部变量
-
声明在类体内,方法体外的变量称为成员变量。
-
声明在方法体内部的变量称为局部变量。
- 成员变量:在方法体外,类体内声明的变量
- 实例变量(不以
static
修饰) - 类变量(以
static
修饰)
- 实例变量(不以
- 局部变量:在方法体外声明的变量
- 方法局部变量(在方法内定义)
- 代码块局部变量(在代码块内定义)
- 形参(方法、构造器中定义的变量)
- 成员变量:在方法体外,类体内声明的变量
成员变量(属性)与局部变量的区别
成员变量 | 局部变量 | |
---|---|---|
声明的位置 | 直接声明在类中 | 方法形参或内部、代码块内、构造器内 |
修饰符 | private、public、final... | 不能用权限修饰符和static,只可以用final修饰 |
初始化值 | 有默认初始化值 | 没有默认初始化值,必须显式赋值 |
作用域 | 整个类中 | 函数/代码块/内部类 内部 |
生命周期 | 和类/对象生命周期一样 | 和方法调用生命周期一样 |
内存加载位置 | 堆空间 或 静态域内(静态变量) | 栈空间 |
说明:
-
声明的位置
public class Person { String name = "Tom"; // 成员变量 int age = 18; // 成员变量 public void show(String loc) { // loc 局部变量 String subject = "大数据"; // 局部变量 } }
-
修饰符
public class Person { public String name = "Tom"; // public 修饰 private int age = 18; // private 修饰 public static final double PI = 3.14; // 组合使用 public void show(String loc) { //publilc String subject = "大数据"; // 错误 //static int a = 3; // 错误 final int b = 4; //正确 } }
-
初始化值
class Person { String name; // 成员变量 int age; // 成员变量 public void show(String loc) { // loc 局部变量 String subject; // 局部变量 //System.out.println(subject); // 编译错误 subject未初始化 须显式赋值 } } public class Test { public static void main(String[] args) { Person p = new Person(); p.show("上海"); System.out.println(p.name); // null System.out.println(p.age); // 0 } }
成员变量的默认初始化值
分类 数据类型 默认值 基本类型 整数(byte,short,int,long) 0 浮点数(float,double) 0.0 字符(char) '\u0000' 布尔(boolean) false 数据类型 默认值 引用类型 数组,类,接口 null -
生命周期
- 成员变量:静态变量的生命周期和类的一样。实例变量的生命周期和对象一样,随着对象创建而存在,随着对象被GC回收而消亡。
- 局部变量:和方法调用的生命周期一样,随着方法被调用而存在,方法执行结束而消亡。
-
内存加载位置
class Person { private String name = "Tom"; private int age = 18; public void show(String loc) { // loc 局部变量 String subject = "大数据"; // 局部变量 } } public class Test { public static void main(String[] args) { Person p = new Person(); p.show("上海"); } }
成员变量和局部变量在内存中的位置
说明:在方法中声明的变量可以是基本数据类型的变量,也可以是引用数据类型的变量。
- 当声明的是基本数据类型的变量时,其变量名和值都放在虚拟机栈中。
- 当声明的时引用数据类型的变量时,虚拟机栈中存放的是变量名和地址值,该变量所指的对象是存放在堆内存中的。
类变量(静态变量)会被加载到
JVM
内存中方法区(静态域)中,详见:final_static关键字的使用说明
方法
方法也叫函数,是一组代码语句的封装,用来完成某个功能操作。方法能够实现代码重用,减少代码冗余。方法不能独立存在,必须定义在类中方法外。
方法的声明和调用
-
语法格式
【修饰符】返回值类型 方法名(【参数类型 形参1, 参数类型 形参2...】) 【throws 异常列表】 { 方法体代码 }
修饰符有:public、缺省、private、protected
返回值类型:
- 没有返回值:void
- 有返回值:声明返回值的类型,如int、String...
注意:
一般情况下,方法中的多个return语句只会执行一个。
特殊情况(finally语句)下,方法中的多个return语句会被执行多个。
-
正确示例
class MethodDefineDemo { // 无参无返回值方法的演示 void sayHello(){ System.out.println("hello"); } // 有参无返回值方法的演示 void printRectangle(int length, int width, char sign){ for (int i = 1; i <= length ; i++) { for(int j=1; j <= width; j++){ System.out.print(sign); } System.out.println(); } } // 无参有返回值方法的演示 int getIntBetweenOneToHundred(){ return (int)(Math.random()*100+1); } // 有参有返回值方法的演示 int max(int a, int b){ return a > b ? a : b; } }
错误示例
类{ 方法1(){ 方法2(){ //位置错误 } } }
-
方法调用
对象.方法名(【实参1, 实参2...】);
-
示例
public class MethodInvokeDemo { public static void main(String[] args) { //创建对象 MethodDefineDemo md = new MethodDefineDemo(); //调用MethodDefineDemo类中无参无返回值的方法sayHello md.sayHello(); md.sayHello(); //调用一次,执行一次,不调用不执行 //调用MethodDefineDemo类中有参无返回值的方法printRectangle md.printRectangle(5,10,'@'); //调用MethodDefineDemo类中无参有返回值的方法getIntBetweenOneToHundred md.getIntBetweenOneToHundred();//语法没问题,就是结果丢失 int num = md.getIntBetweenOneToHundred(); System.out.println("num = " + num); //调用MethodDefineDemo类中有参有返回值的方法max int bigger = md.max(5,6); System.out.println("bigger = " + bigger); } }
-
可变形参说明
JavaSE 5.0 中提供了 Varargs 机制,允许直接定义能和多个实参相匹配的形参。
-
声明格式
方法名(参数类型名... 参数名){}
-
示例
public static void test(int... nums) {}
注意事项
-
方法内部有可变形参,需要放在形参声明的最后。
public static void test(int... nums, String str) {}
错误 -
在一个方法的形参位置,最多只能有一个可变形参
public static void test(int... nums, String... strs) {}
错误 -
可变参数的本质就是数组,注意重载的问题
-
方法参数传递机制
- 形参:方法声明时的参数
- 实参:方法调用时实际传给形参的参数值
Java 里方法的参数传递方式只有一种:值传递。即将实际参数值的副本传入方法内,而参数本身不受影响。
- 形参是基本数据类型:将实参的 "数据值" 传递给形参 。形参值的改变不影响实参。
- 形参是引用数据类型:将实参的 "地址值" 传递给形参。形参地址值的改变不影响实参,但是形参地址值指向的数据的改变会影响实参。
-
形参是基本数据类型
package com.atguigu.test05.param; public class PrimitiveTypeParam { void swap(int a, int b){//交换两个形参的值 int temp = a; a = b; b = temp; } public static void main(String[] args) { PrimitiveTypeParam tools = new PrimitiveTypeParam(); int x = 1; int y = 2; System.out.println("交换之前:x = " + x +",y = " + y);//1,2 tools.swap(x,y);//实参x,y是基本数据类型,给形参的是数据的“副本”,调用完之后,x与y的值不变 System.out.println("交换之后:x = " + x +",y = " + y);//1,2 } }
-
形参是引用数据类型
public class ReferenceTypeParam { void swap(MyData my){//形参my是引用数据类型,接收的是对象的地址值,形参my和实参data指向同一个对象 //里面交换了对象的两个实例变量的值 int temp = my.x; my.x = my.y; my.y = temp; } void change(MyData my) { my = null; } public static void main(String[] args) { ReferenceTypeParam tools = new ReferenceTypeParam(); MyData data = new MyData(); data.x = 1; data.y = 2; System.out.println("交换之前:x = " + data.x +",y = " + data.y);//1,2 tools.swap(data);//实参是data,给形参my的是对象的地址值,调用完之后,x与y的值交换 System.out.println("交换之后:x = " + data.x +",y = " + data.y);//2,1 tools.change(my); System.out.println("修改之后:x = " + data.x +",y = " + data.y);//2,1 没有改变 } }
public class MyData{ int x; int y; }
方法重载
在同一个类中,允许存在一个以上的同名方法,只要它们的参数列表不同即可,与修饰符和返回值类型无关。
详见:方法重载与重写
构造器
构造器又叫构造方法,用来创建对象,并在创建对象的时候为实例变量赋初值。
构造器声明和使用
-
构造器语法格式
【修饰符】 class 类名{ 【修饰符】 构造器名() { // 实例初始化代码 } 【修饰符】 构造器名(参数列表) { // 实例初始化代码 } }
注意事项:
- 构造器名必须与它所在的类名必须相同。
- 它没有返回值,所以不需要返回值类型,甚至不需要void
- 如果你不提供构造器,系统会默认给出无参数构造器,并且该构造器的修饰符默认与类的修饰符相同
- 如果你提供了构造器,系统将不再提供无参数构造器,除非你自己定义。
- 构造器是可以重载的,既可以定义参数,也可以不定义参数。
- 构造器的修饰符只能是权限修饰符(
public
、protected
、缺省
、private
都可以),不能被其他任何修饰
-
示例
public class Student { private String name; private int age; public Student() {} // 无参构造 // 构造器重载 public Student(String name,int age) { // 有参构造 this.name = name; this.age = age; } }
-
使用
new
创建对象public class TestStudent { public static void main(String[] args) { Student s1 = new Student(); //调用无参构造创建学生对象 Student s2 = new Student("张三",23); //调用有参构造创建学生对象 } }
在其他构造器调用构造器
在同一个类中可以使用this
关键字调用本类的构造器;子类继承父类时,可以使用super
关键字调用父类中的构造器。
代码块
代码块(或初始化块)的主要作用是,对 Java 类和对象进行初始化。详见:代码块的使用细节
内部类
在 Java 中,允许在一个类的内部定义另一个类,前者称为外部类,后者称为内部类。
详见:Java 的四种内部类