Java面向对象编程高阶(一)
一、关键字static
static用来修饰的结构:属性、方法、代码块、内部类;
1、static修饰属性
方式一:按照数据类型:基本数据类型、引用数据类型
方式二:按照类中声明的位置:
-
成员变量:按照是否使用static修饰进行分类
- 使用static修饰的成员变量:静态变量、类变量
- 不使用static修饰的成员变量:非静态变量、实例变量
-
局部变量:方法内、方法形参、构造器内、构造器形参、代码块内
2、静态变量与实例变量的对比
个数
静态变量:在内存空间中只有一份,被类的多个对象所共享
实例变量:类的每一个实例都保存着一份实例变量
内存位置
静态变量:jdk之前,存放在方法区;jdk7之后存放在堆空间
实例变量:存放在堆空间的对象实体中
加载时机:
静态变量:随着类的加载而加载,由于类只会加载一次,所以静态变量也只有一份。
实例变量:随的对象的创建而加载。每个对象拥有一份实例变量。
调用者:
静态变量:可以被类直接调用、也可以被对象调用
实例变量:只能使用对象调用
消亡时机:
静态变量:随着类的卸载而消亡
实例变量:随着对象的消亡而消亡
3、static修饰方法
随着类的加载而加载
可以通过"类.静态方法"的方式直接调用静态方法
静态方法内可以调用静态的属性和静态的方法;(属性和方法的前缀使用的是当前类,可以省略)
不能调用非静态的属性和非静态方法。
static修饰的方法内,不能使用this和super
补充:在类的非静态方法中,可以调用当前类中的静态结构(属性、方法)或非静态结构(属性、方法)
4、什么时候将属性声明为静态的?
判断当前类的多个实例是否能够共享此成员变量,且成员变量的值是相同的
开发中我们常将一些常量声明为静态的。例如:Math中的PI
5、什么时候将属性声明为静态的?
方法内操作的变量如果是静态变量(而非实例变量)的话,则此方法建议声明为静态方法。
6、代码演示
java
package com;
/**
* package:com
*
* @Author jimmy-yan
* @Create 2024/10/26 22:21
*/
public class ChinsesTest {
public static void main(String[] args) {
Chinese c1 = new Chinese();
c1.name = "kobe";
c1.age = 19;
c1.nation = "china";
Chinese c2 = new Chinese();
c2.name = "jimi";
c2.age = 20;
System.out.println(c1);
System.out.println(c2);
System.out.println(c1.nation); //china
System.out.println(c2.nation); //china
c2.nation = "CNA";
System.out.println(c1.nation); //CNA
System.out.println(c2.nation); //CNA
}
}
class Chinese {
//非静态变量、实例变量
String name;
int age;
//静态变量、类变量
static String nation;
@Override
public String toString() {
return "Chinese{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
public void eat(String food) {
System.out.println("我喜欢吃" + food);
}
public static void show() {
System.out.println("我是中国人");
//todo 调用静态结构
System.out.println("nation=" + nation);
method1();
//todo 调用非静态结构
// System.out.println("name="+name);
// eat("饺子");
}
public static void method1() {
System.out.println("我是静态测试方法");
}
public void method2() {
System.out.println("我是非静态测试方法");
}
}
java
package com;
/**
* package:com
*
* @Author jimmy-yan
* @Create 2024/10/26 23:15
*/
public class CircleTest {
public static void main(String[] args) {
Circle c1 = new Circle();
System.out.println(c1);
Circle c2 = new Circle();
System.out.println(c2);
System.out.println(Circle.total);
Circle c3 = new Circle();
System.out.println(c3);
System.out.println(Circle.total);
}
}
class Circle {
double radius;
int id; //编号
static int total; //创建实例的个数
public Circle() {
this.id = init;
init++;
total++; //todo
}
public Circle(double radius){
this();
this.radius=radius;
}
// todo 加static,实现自动给id赋值的基数
private static int init = 1001;
@Override
public String toString() {
return "Circle{" +
"radius=" + radius +
", id=" + id +
'}';
}
}
案例:编写一个类实现银行账户的概念,包含的属性有:账号、密码、存款余额、利率、最小余额,定义封装这些属性的方法,账号要自动生成。编写主类,使用银行账户类,输入、输出3个存储的上述信息。
考虑:哪些属性可以设计成static属性
java
package com;
/**
* package:com
*
* @Author jimmy-yan
* @Create 2024/10/27 20:05
*/
public class AccountTest {
public static void main(String[] args) {
Account acc1 = new Account();
System.out.println(acc1);
Account acc = new Account("kobe", 666666);
System.out.println(acc);
}
}
class Account {
int id;
String account;
int password;
double deposit_balance;
static double rate;
static double minimum_balabce;
static int init = 1000;
public Account() {
init++;
id = init;
}
public Account(String account, int password) {
this();
this.account = account;
this.password = password;
}
@Override
public String toString() {
return "Account{" +
"id=" + id +
", account='" + account + '\'' +
", password=" + password +
", deposit_balance=" + deposit_balance +
'}';
}
}
java
Account{id=1001, account='null', password=0, deposit_balance=0.0}
Account{id=1002, account='kobe', password=666666, deposit_balance=0.0}