类和对象
方法设计
定义和使用方法
一个方法的定义包括两个部分
- 方法声明
- 方法体的定义
- 语法格式
[修饰符] returnType methodName ([paramList]) {
//方法体
}
访问方法和修改方法
能够返回成员变量值的方法称为访问方法(accessor method)。
能够修改成员变量值的方法称为修改方法(mutator method)。
访问方法一般命名为getXxx(),因此,也称getter方法。
例如,double getSalary()
修改方法一般命名为setXxx(),因此,也称setter方法。
例如,void setSalary(double s)
方法的调用
调用类的实例方法应先创建一个对象,然后通过对象引用调用。
调用类的静态方法,通常使用类名调用。
方法调用主要使用在三种场合:
😊1)用对象引用调用类的实例方法。
😊2)类中的方法调用本类中的其他方法。
😊3)用类名直接调用static方法。
方法参数的传递
- 调用带参数的方法,需要向它传递参数。
- 定义方法指定的参数称为形式参数,调用方法指定的参数称为实际参数。
- Java语言中,方法的参数是按值传递(pass by value)的,即在调用方法时将实际参数的值的一个拷贝传递给方法中的形式参数,方法调用结束后实际参数的值并不改变。
- 当参数是基本类型时,将实际参数值的一个拷贝传递给方法,方法调用结束后,对原来的值没有影响。
- 当参数是引用类型时,实际传递的是引用值,因此在方法的内部有可能改变原来的对象。
✨方法重载
Java允许在一个类中定义多个同名的方法,这称为方法重载(overloading)。
实现方法重载,要求同名的方法
参数个数不同或参数类型不同
仅返回值不同不能区分重载的方法。
✨构造方法(构造器)
构造方法也叫构造器(Constructor) 。Java每个类都有构造方法
构造方法与普通方法的区别是:
- 构造方法的名称必须与类名相同。
- 构造方法不能有返回值,也不能返回void。
- 在创建对象时用new运算符调用。
- 构造方法定义格式:
[public | protected | private] ClassName([paramList]) {
// 方法体
}
构造方法主要作用:
创建对象并初始化对象的成员变量。
构造方法分类 - 无参数构造方法
- 带参数构造方法
注:构造方法也可以重载
默认构造方法
1️⃣如果省略构造方法,Java编译器会自动为该类生成一个默认的构造方法。
2️⃣一旦用户为某类定义了构造方法,系统就不再提供默认的构造方法。
3️⃣默认的构造方法无参数,方法体为空。
例如:public Employee(){}
4️⃣若class前面有public修饰符,则默认的构造方法前面也是public。
🚩this关键字
this关键字表示对象本身。
this关键字主要用于以下两种情况:
- 解决局部变量与成员变量同名的问题。
- 用来调用该类的另一个构造方法。
1、成员变量名与局部变量同名
在一个方法的方法体或参数中,也可能声明与成员变量同名的局部变量。此时局部变量会隐藏成员变量。
要使用成员变量就需要在其前面加上this关键字。
public void setSalary(double salary)
{ this.salary = salary;}
2、从一个构造方法调用另一个构造方法
从某一构造方法内调用另一构造方法,必须通过关键字this来调用的,否则编译出错。
this关键字必须写在构造方法内的第一行位置。
public Cylinder(){ this(2.5,5,"红色"); }
public Cylinder(double r,int h,String str){
radius=r; height=h; color=str;
}
package shujia_test1;
public class Csdn4_1 {
private double radius;
private int height;
private double pi = 3.14;
String color;
public Csdn4_1() {
this(2.5, 5, "红色");
System.out.println("无参构造方法被调用了");
}
public Csdn4_1(double r, int h, String str) {
System.out.println("有参构造方法被调用了");
radius = r;
height = h;
color = str;
}
public void show() {
System.out.println("圆柱底半径为:" + radius);
System.out.println("圆柱体的高为:" + height);
System.out.println("圆柱的颜色为:" + color);
}
double area() {
return pi * radius * radius;
}
double volume() {
return area() * height;
}
public static void main(String[] args) {
Csdn4_1 volu = new Csdn4_1();
System.out.println("圆柱底面积=" + volu.area());
System.out.println("圆柱体体积=" + volu.volume());
volu.show();
}
}
运行结果:
编程练习
定义一个名为Csdn4_2的类表圆,其中含有double型的成员变量centerX、centerY表示圆心坐标,radius表示圆的半径。定义求圆面积的方法getArea()方法和求圆周长的方法getPerimeter()。
为半径radius定义访问方法getRadius和修改方法SetRadius。
定义无参数构造方法,在该方法中调用有参数构造方法,将圆的半径设置为1.0。
编写程序测试这个圆类的所有方法。(在main方法中创建对象c,调用getRadius、SetRadius、getArea()、getPerimeter 方法)
package shujia_test1;
public class Csdn4_2 {
// 成员变量
private double centerX;
private double centerY;
private double radius;
// 无参数构造方法,调用有参数构造方法,半径默认为1.0
public Csdn4_2() {
this(1.0);
}
// 有参数构造方法
public Csdn4_2(double radius) {
this.centerX = 0.0; // 默认圆心在(0,0)
this.centerY = 0.0;
this.radius = radius;
}
// 半径的访问方法
public double getRadius() {
return radius;
}
// 半径的修改方法
public void setRadius(double radius) {
this.radius = radius;
}
// 求圆面积的方法
public double getArea() {
return Math.PI * radius * radius;
}
// 求圆周长的方法
public double getPerimeter() {
return 2 * Math.PI * radius;
}
// (可选)如果需要,也可以定义设置圆心的方法
public void setCenter(double centerX, double centerY) {
this.centerX = centerX;
this.centerY = centerY;
}
// (可选)获取圆心的方法
public double getCenterX() {
return centerX;
}
public double getCenterY() {
return centerY;
}
public static void main(String[] args) {
// 创建Circle对象c,使用无参数构造方法,半径默认为1.0
Csdn4_2 c = new Csdn4_2();
// 测试getRadius方法
System.out.println("圆的半径是: " + c.getRadius());
// 测试setRadius方法
c.setRadius(5.0);
System.out.println("修改后的圆的半径是: " + c.getRadius());
// 测试getArea方法
System.out.println("圆的面积是: " + c.getArea());
// 测试getPerimeter方法
System.out.println("圆的周长是: " + c.getPerimeter());
// (可选)测试设置和获取圆心的方法
c.setCenter(3.0, 4.0);
System.out.println("圆心的X坐标是: " + c.getCenterX());
System.out.println("圆心的Y坐标是: " + c.getCenterY());
}
}
运行结果:
静态变量和静态方法
静态变量
用static修饰,也叫类变量。
所有实例共享一块内存空间。
通常使用类名访问,也可以使用实例名访问。
对于某类的任何一个具体对象而言,静态变量是一个公共的存储单元
实例变量:
未用static修饰。
每个实例具有自己的内存空间。
必须使用实例名访问。
通常,static与final一起使用来定义类常量。例如,Java类库中的Math类中就定义了两个类常量:
public static final double E = 2.718281828459045 ;
public static final double PI = 3.141592653589793 ;
可以通过类名直接使用这些常量。例如:Math.PI
静态方法
静态方法:
用static修饰,也叫类方法。
只能直接访问静态变量和静态方法。(不通过对象调用时)
通常使用类名调用,也可以使用实例名调用。
类名.静态方法名( ); 对象名.静态方法名( );
实例方法:
未用static修饰。
必须使用实例名调用。
🌈解释:main方法的访问权限为何必须为public static?
由于JVM需要在类外调用main方法,所以该方法的访问权限必须是public;
而且在JVM运行时,并没有创建main方法所在的类的一个实例对象,所以它只能通过类名来调用main方法作为程序的入口,所以该方法必须是static。
对象初始化和清除
实例变量初始化
实例变量的初始化有下面几种方式:
1)声明时初始化或者使用默认值初始化。
2)使用初始化块。
3)使用构造方法初始化。
成员变量默认值
在类的定义中如果没有为变量赋初值,则编译器为每个成员变量指定一个默认值。
引用类型的变量,默认值为null
整型默认值是0
浮点型默认值是0.0
布尔型默认值是false
字符型是空字符( ’\u0000’)
初始化次序
如果在类中既为实例变量指定了初值,又有初始化块,还在构造方法中初始化了变量,那么它们执行的顺序如何,最后变量的值是多少?
1)首先使用默认值或指定的初值初始化,这里先将x赋值为100。
2)接下来执行初始化块,重新将x赋值为60。
3)最后再执行构造方法,再重新将x赋值为58。
静态变量的初始化
静态变量的初始化有下面几种方法:
1)声明时初始化或者使用默认值初始化。
2)使用静态初始化块。(加上static关键字)
3)使用构造方法初始化。
注意:对于static变量,不论创建多少对象(甚至没有创建对象时)都占一份存储空间。
💥垃圾回收
当一个对象不再被引用时,Java运行系统就在后台自动运行一个线程,销毁该对象并释放其所占的内存空间,这个过程称为垃圾回收(Garbage Collection,GC)。
后台运行的线程称为垃圾回收器(garbage collector)。
当一个对象不再被引用时,该对象才有可能被回收。
包与类的导入
包与package语句
Java语言使用包(package)来组织类库。包实际是一组相关类或接口的集合。
包主要有下面几个作用:
- 功能相关的类和接口放到一个包中。
- 实现命名管理机制,同名的类可以放在不同包中。
- 实现对类的访问控制。
- import导入包,格式为:
import 包名1 [.包名2[.包名3…] ] . 类名 |*
例如:import java.util.;
import java.util.Scanner;
“” 表示本层所有的类
在java程序中需要使用类的地方,都可以指明包含该类的包,这时不必用import。
例如:java.util.Scanner input = new java.util.Scanner(System.in);
Java包路径:根文件夹由环境变量CLASSPATH确定。
编译器会自动导入java.lang包和当前目录中的类。
类的导入
package com.exam; //指明Odd类属于com.exam包,源文件在\src\com\exam
import java.util.Scanner; //导入Scanner类
public class Odd {
public static void main(String[] args) {
Scanner input = new Scanner(System.in); //直接使用Scanner类
//输入一个正整数
int num = input.nextInt();
if(num % 2 ==0)
System.out.println(num + "是偶数");
else
System.out.println(num + "是奇数");
}
}
package com.exam;
public class Odd {
public static void main(String[] args) {
java.util.Scanner input = new java.util.Scanner(System.in);
//输入一个正整数
int num = input.nextInt();
if(num % 2 ==0)
System.out.println(num + "是偶数");
else
System.out.println(num + "是奇数");
}
}