面向对象_static_代码块_final
in Java with 0 comment

面向对象_static_代码块_final

in Java with 0 comment

static

概述

静态变量

分类

类变量实例变量
yesno
对象yesyes

举例

public class StaticTest {
	public static void main(String[] args) {
		// 静态变量也叫类变量,是根据类的加载而加载
		// 所以静态变量比实例变量加载快
		Chinese.nation = "中国";
		System.out.println(Chinese.nation);// 中国

		Chinese c1 = new Chinese();
		c1.age = 18;
		c1.name = "张三";

		Chinese c2 = new Chinese();
		c2.age = 28;
		c2.name = "李四";

		c1.nation = "CHN";
		c2.nation = "CHINA";
		System.out.println(Chinese.nation);// CHINA
		System.out.println(c1.nation);// CHINA
		System.out.println(c2.nation);// CHINA

	}
}

class Chinese {
	// 实例变量
	String name;
	int age;
	// 类变量、静态变量
	static String nation;
}

内存解析

20200819104227

静态方法

举例

public class StaticTest {
	public static void main(String[] args) {
		
		// 类调用静态方法,yes
		Chinese.show();
		// 类调用非静态方法,no
		// Cannot make a static reference to the non-static method eat() from the type
//		Chinese.eat();

		// 对象调用静态方法,yes
		Chinese c3 = new Chinese();
		c3.show();

		// 对象调用非静态方法,yes
		c3.eat();

	}
}

class Chinese {
	// 实例变量
	String name;
	int age;
	// 类变量、静态变量
	static String nation;

	// 非静态方法
	public void eat() {
		System.out.println("中国人吃中餐");
		// 非静态方法中调用静态属性,yes
		System.out.println(nation);// nation省略了Chinese.

		// 非静态方法中调用非静态属性,yes
		age = 10;

		// 非静态方法中调用静态方法,yes
		show();
	}

	// 静态方法
	public static void show() {
		System.out.println("我是中国人");
		//静态方法中调用静态属性,yes
		System.out.println(nation);
		//静态方法中调用非静态属性,no
		//Cannot make a static reference to the non-static field age
//		System.out.println(age);
		//静态方法中调用静态方法,yes
		show2();
		//静态方法中调用非静态方法,no
		//Cannot make a static reference to the non-static method eat() from the type Chinese
		//eat();

	}

	// 静态方法
	public static void show2() {
		System.out.println("I'm Chinese");
	}
}

总结

  1. 在开发中,如何确定一个属性是否要声明为static
    • 属性是可以被多个对象所共享的,不会随着对象的不同而不同的。
  2. 在开发中,如何确定一个方法是否要声明为static
    • 操作静态属性属性的方法,通常设置为static的。
    • 工具类中的方法,习惯是声明为static的。例如Math\Arrays\Collections等。

练习

编写一个类实现银行账户的概念,包含的属性有“帐号”、“密码”、“存款余额”、“利率”、“最小余额”,定义封装这些属性的方法。账号要自动生成。 编写主类,使用银行账户类,输入、输出3个储户的上述信息。
考虑:哪些属性可以设计成static属性。

public class Account {
	private int account;// 账户
	private String password;// 密码
	private double balance;// 余额
	private static double interestRates = 0.2;// 利率
	private static double minBalance = 200000;// 最小余额
	private static int initAccount = 1001;// 初始化账号

	public Account() {
		account = initAccount++;
	}

	public Account(String password) {
		this();
		this.password = password;
	}

	public Account(String password, double balance) {
		this(password);
		this.balance = balance;
	}

	public String getPassword() {
		return password;
	}

	public void setPassword(String password) {
		this.password = password;
	}

	public double getBalance() {
		return balance;
	}

	public void setBalance(double balance) {
		this.balance = balance;
	}

	public int getAccount() {
		return account;
	}

	@Override
	public String toString() {
		return "Account [account=" + account + ", password=" + password + ", balance=" + balance + "]";
	}

}

public class AccountTest {
	public static void main(String[] args) {
		Account a1 = new Account();
		Account a2 = new Account("951591");
		Account a3 = new Account("155789", 6666.66);
		System.out.println(a1.toString());
		System.out.println(a2.toString());
		System.out.println(a3.toString());
	}
}

20200819113622

static的应用:单例设计模式

饿汉式

public class SingletonTest {
	public static void main(String[] args) {
		// 测试
		Bank b1 = Bank.getInstance();
		Bank b2 = Bank.getInstance();
		System.out.println(b1 == b2);// true
	}
}

class Bank {
	// 私有化构造器
	private Bank() {

	}

	// 创建当前类对象的静态变量
	private static Bank instance = new Bank();

	// 创建获取静态变量的方法
	public static Bank getInstance() {
		return instance;
	}
}

懒汉式

public class SingletonTest2 {
	public static void main(String[] args) {
		// 测试
		Order o1 = Order.getInstance();
		Order o2 = Order.getInstance();
		System.out.println(o1 == o2);// true
	}
}

class Order {
	// 私有化构造器
	private Order() {

	}

	// 声明当前类对象的静态变量
	private static Order instance = null;

	// 创建获取静态变量的方法
	public static Order getInstance() {
		// 目前这样写是有安全问题的,后期学到线程后在修改成没有线程安全问题的
		if (instance == null) {
			instance = new Order();
		}
		return instance;
	}
}

单例模式的应用场景

理解main()方法

  1. main()可以作为程序的入口。
public class MainTest {
	public static void main(String[] args) {
		System.out.println("程序的入口");
	}
}
  1. main()可以作为普通的静态方法。
public class MainTest {
	public static void main(String[] args) {
		// 1.作为程序的入口
		//System.out.println("程序的入口");
		// 2.作为普通方法进行调用
		Person.main(new String[100]);
	}
}

class Person {
	public static void main(String[] args) {
		for (int i = 0; i < args.length; i++) {
			args[i] = "args_" + i;
			System.out.println(args[i]);
		}
	}
}

20200819145930

  1. main()可以作为与控制台的交互方式。
    首先编写一个类
public class MainTest2 {
	public static void main(String[] args) {
		for (int i = 0; i < args.length; i++) {
			System.out.println(args[i]);
		}
	}
}

String[] args可以再运行MainTest2.class时填写String数据给到程序。

20200819150710

20200819150919

20200819150928

代码块

  1. 作用:用来初始化类、对象
  2. 格式:{ 内容 }
  3. 修饰符:如果要使用修饰,只能用static,即static { 内容 }
  4. 分类:
    • 静态代码块
    • 非静态代码块

静态代码块

非静态代码块

实例

public class BlockTest {
	public static void main(String[] args) {
		// 测试
		// 指挥执行一次静态代码块
		Person.nation = "CHN";
		// 每创建一个对象,就会执行一次非静态代码块
		Person p1 = new Person();
		Person p2 = new Person();
		System.out.println(p1.age);
	}
}

class Person {
	// 实例变量
	String name;
	int age;
	// 类变量(静态变量)
	static String nation;

	// 方法
	public void eat(String food) {
		System.out.println("爱吃:" + food);
	}

	// 静态方法
	public static void sleep() {
		System.out.println("睡觉了");
	}

	// 非静态代码块
	{
		System.out.println("非静态代码块1");
		age = 1;
	}
	{
		System.out.println("非静态代码块2");
		// 调用非静态属性
		age = 1;
		// 调用静态属性
		nation = "中国2";
		// 调用非静态方法
		eat("米饭");
		// 调用静态方法
		sleep();
	}

	// 静态代码块
	static {
		System.out.println("静态代码块1");
	}
	static {
		System.out.println("静态代码块2");
		// 调用静态方法
		sleep();
		// 调用静态属性
		nation = "中国";
	}
}

练习

public class BlockTest2 {
	public static void main(String[] args) {
		new C();
		/*
		 * A的静态代码块
			B的静态代码块
			C的静态代码块
			A的非静态代码块
			A的无参构造器
			B的非静态代码块
			B的无参构造器
			C的非静态代码块
			C的无参构造器
		 */
	}
}

class A {
	public A() {
		System.out.println("A的无参构造器");
	}

	static {
		System.out.println("A的静态代码块");
	}

	{
		System.out.println("A的非静态代码块");
	}

}

class B extends A {
	public B() {
		System.out.println("B的无参构造器");
	}

	public B(String b) {
		this();
		System.out.println("B的有参构造器");
	}

	static {
		System.out.println("B的静态代码块");
	}

	{
		System.out.println("B的非静态代码块");
	}
}

class C extends B {
	public C() {
		System.out.println("C的无参构造器");
	}

	static {
		System.out.println("C的静态代码块");
	}

	{
		System.out.println("C的非静态代码块");
	}
}

总结:由父及子,静态显性。

赋值的先后顺序(完结篇)

目前有如下几种属性赋值的方式:

  1. 默认初始化值
  2. 显性初始化值
  3. 构造器初始化值
  4. 通过类.方法类.属性赋值
  5. 通过代码块赋值

赋值的先后顺序为:
默认初始化值 - 显性初始化值/代码块赋值(谁在前面谁先执行) - 构造器初始化值 - 类.方法类.属性赋值

final

  1. final:最终的
  2. 可以用来修饰:类、方法、变量。

final修饰类

final class FinalA{
	
}

//The type FinalB cannot subclass the final class FinalA
//FinalA使用final修饰,代表此类不可以被继承
class FinalB extends FinalA{
	
}

final修饰方法

class FinalA {
	// 使用final修饰此方法
	public final void eat() {

	}
}

class FinalB extends FinalA {
	//	- Cannot override the final method from 
	// FinalA
	public void eat() {
		
	}
}

final修饰变量

属性

class FinalA {
	// 显式赋值
	final int a = 10;
	// 代码块赋值
	final int b;
	{
		b = 10;
	}
	// 构造器赋值
	final int c;

	public FinalA() {
		c = 10;
	}

}

局部变量

	public void show() {
		final int aa = 10;
		//The final local variable aa cannot be assigned. It must be blank and not using a compound  assignment
		//错误
		//aa = aa+1;
	}

形参

	public void show(final int cc) {
		//The final local variable cc cannot be assigned. It must be blank and not using a compound assignment
		//错误
		//cc = 20;
	}

static final

Day14问题

  1. static修饰的属性,相较于实例变量,有些特别之处(>=三条)

    • 通过类.属性去调用
    • 随着类的加载而加载,在内存空间只有一个
    • 早于对象的创建
    • 类或者类的对象都可以调用
    • 放在方法区的静态域中。
  2. final可以用来修饰哪些结构,分别表示什么意思

    • 类:final修饰的类不有子类
    • 方法:final修饰的方法不能被子类重写
    • 变量:
      • 属性:常量,赋值后不能修改,赋值的位置:显式赋值、代码块赋值、构造器赋值
      • 局部变量:常量,赋值后不能修改
      • 形参:带final的形参,在调用方法过程中赋值,赋值后不能修改。
  3. 代码实现单例模式的饿汉式

    • 好处不存在线程安全问题
    • 坏处占用一定内存
public class A{
	private static A instance = new A();
	public static A getInstance(){
		return instance;
	}
}
  1. 代码实现单例模式的懒汉式
    • 好处用的时候再去加载,减少内存
    • 坏处此代码存在线程安全问题,后期学完线程在修改成没有现成安全的代码
public class A{
	private static A instance = null;
	public static A getInstance(){
		if(instance == null){
			instance = new A();
		}
		return instance;
	}
}
  1. 类的属性复制位置有哪些?先后顺序为何?
    • 默认值
    • 显式赋值/代码块赋值(谁在前谁先复制)
    • 构造器赋值
    • 通过对象.方法对象.属性赋值。