Java教程

JavaSE(九):static关键字和继承

本文主要是介绍JavaSE(九):static关键字和继承,对大家解决编程问题具有一定的参考价值,需要的程序猿们随着小编来一起学习吧!

1、static关键字

1.1 static关键字的基本概念

  • 使用static关键字修饰成员变量表示静态的含义,此时成员变量由对象层级提升为类层级,也就是整个类只有一份并被所有对象共享,该成员变量随着类的加载准备就绪,与是否创建对象无关。
  • static关键字修饰的成员可以使用引用.的方式访问,但推荐类名.的方式。
  • 如下列代码所示,在类中声明成员变量时,使用static关键字修饰,表明该成员变量属于类层级,被该类的所有对象共享。
private String name;
private int age;  // 隶属于对象层级,也就是每个对象都拥有独立的一份
private static String country;  // 隶属于类层级,也就是整个类只有一份并且被所有对象共享

static关键字的作用

1.2 static关键字的使用方式

  • 在非静态成员方法中既能访问非静态的成员又能访问静态的成员。(成员:成员变量 + 成员方法, 静态成员被所有对象共享)
  • 在静态成员方法中只能访问静态成员不能访问非静态成员。(成员:成员变量 + 成员方法, 因为此时可能还没有创建对象)
  • 在以后的开发中,只有隶属于类层级并被所有对象共享的内容才可以使用static关键字修饰。(不能滥用static关键字)

1.3 构造块和静态代码块

1.3.1 构造块

  • 构造块:在类体中直接使用 { } 括起来的代码块。
  • 每创建一个对象都会执行一次构造块。
  • 作用:当需要在执行构造方法体之前做一些准备工作时,则将准备工作的相关代码写在构造块中即可,比如对成员变量进行的统一初始化操作。

1.3.2 静态代码块

  • 静态代码块:使用static关键字修饰的构造块。
  • 静态代码块随着类的加载而执行一次。
  • 作用:当需要在执行代码块之前随着类的加载做一些准备工作时,则编写代码到静态代码块中,比如:加载数据库的驱动包等。
  • 执行顺序:静态代码块 -> 构造块 -> 构造方法体
public class BlockTest {
	
	// 每创建一个对象,都会执行一次构造块
	{
		System.out.println("构造块!");  // (2)
	}
	
	// 静态代码块会随着类的加载而准备就绪,会先于构造块执行
	static {
		System.out.println("静态代码块!");  // (1)
	}
	
	// 自定义构造方法
	public BlockTest() {
		System.out.println("构造方法体!");  // (3)
	}
	
	public static void main(String[] args) {
		
		BlockTest bt = new BlockTest();
		BlockTest bt2 = new BlockTest();
	}
}
/*
执行结果:
静态代码块!
构造块!
构造方法体!
构造块!
构造方法体!
*/

1.4 main方法的详解

  • 语法格式:
public static void main(String[] args) {}
  • 修饰main方法的关键字:
    • public 表示main方法是公有的;
    • static 表示main方法是静态的,属于类层级;
    • void 表示main方法没有返回值;
  • main方法的形参列表是一个String类型、名为args的一维数组;
// 编程实现main方法形参列表的使用
public class MainTest {
	
	public static void main(String[] args) {
		
		System.out.println("参数数组中元素的个数是:" + args.length);
		System.out.println("传递给main方法的实际参数为:");
		for(int i = 0; i < args.length; i++) {
			System.out.println("下标为" + i + "的形参变量数值为:" + args[i]);
		}
	}
}
  • 在cmd中执行上面的代码,结果如下图所示:
    在这里插入图片描述

1.5 单例设计模式

1.5.1 案例引入

  • 案例题目:(1) 编程实现Singleton类的封装。(2) 编程实现SingletonTest类对Singleton类进行测试,要求main方法中能得到且只能得到该类的一个对象。
  • Singleton的封装类:
public class Singleton {
	
	// 2.声明本类类型的引用指向本类类型的对象,使用private static关键字共同修饰
	private static Singleton sin = new Singleton();
	
	// 1.私有化构造方法,使用private关键字修饰
	private Singleton() {}
	
	// 3.提供公有的get方法负责将对象返回出去,使用public static关键字共同修饰
	public static Singleton getInstance() {
		return sin;
	}
}
  • Singleton的测试类:
public class SingletonTest {
	
	public static void main(String[] args) {
		
		Singleton s1 = Singleton.getInstance();
		Singleton s2 = Singleton.getInstance();
		System.out.println(s1 == s2);
	}
}
// 执行结果:true

单例设计模式的执行流程

1.5.2 单例设计模式的概念

  • 在某些特殊场合中,一个类对外提供且只提供一个对象时,这样的类叫做单例类,而设计单例的流程和思想叫做单例设计模式

1.5.3 单例设计模式的实现流程

  1. 私有化构造方法,使用private关键字修饰。
  2. 声明本类类型的引用指向本类类型的对象,并使用private static关键字共同修饰。
  3. 提供公有的get方法负责将对象返回出去,并使用public static关键字共同修饰。

1.5.4 单例设计模式的实现方式

  • 单例设计模式的实现方式有两种:饿汉式 和 懒汉式,在以后的开发中推荐饿汉式
  • 上面Singleton的封装类用的是饿汉式,下面为懒汉式。
public class Singleton {
	
	// 2.声明本类类型的引用指向本类类型的对象,使用private static关键字共同修饰
	private static Singleton sin = null;  // 懒汉式
	
	// 1.私有化构造方法,使用private关键字修饰
	private Singleton() {}
	
	// 3.提供公有的get方法负责将对象返回出去,使用public static关键字共同修饰
	public static Singleton getInstance() {
		if(null == sin) {
			sin = new Singleton();
		}
		return sin;
	}
}

2、继承

2.1 继承的概念

  • 当多个类之间有相同的特征和行为时,可以将相同的内容提取出来组成一个公共类,让多个类吸收公共类中已有特征和行为而在多个类型只需要编写自己独有特征和行为的机制,叫做继承
  • 在Java语言中使用extends(扩展)关键字来表示继承关系。
  • 如:
    • public class Worker extends Person { } 表示Worker类继承自Person类。
    • 其中Person类叫做超类、父类、基类。
    • 其中Worker类叫做派生类、子类、孩子类。

2.2 继承的意义

  • 使用继承提高了代码的复用性,可维护性及扩展性,是多态的前提条件。

2.3 继承的特点

  1. 子类不能继承父类的构造方法和私有方法,但私有成员变量可以被继承只是不能直接访问。
  2. 无论使用何种方式(无参构造或有参构造)构造子类的对象时都会自动调用父类的无参构造方法,来初始化从父类中继承的成员变量,相当于在构造方法的第一行增加代码super()的效果。下图说明创建子类对象时的原理。
// 父类中的无参构造方法
public Person() {}
// 父类中的有参构造方法
public Person(String name, int age) {
	setName(name);
	setAge(age);
}
// 子类中的无参构造方法
public Worker() {}
// 子类中的有参构造方法
public Worker(String name, int age, int salary) {
	setName(name);
	setAge(age);
	setSalary(salary);
}

// 上面子类的构造方法相当于在构造方法的第一行增加代码super()
public Worker() {
	super(); // 表示调用父类的无参构造方法,若没有加则编译器自动添加
}
public Worker(String name, int age, int salary) {
	super(); // 表示调用父类的无参构造方法
	setName(name);
	setAge(age);
	setSalary(salary);
}

// 在实际开发中,使用的是下面的子类构造方法
public Worker() {
	super(); // 表示调用父类的无参构造方法,若没有加则编译器自动添加
}
public Worker(String name, int age, int salary) {
	super(name, age); // 表示调用父类的有参构造方法
	setSalary(salary);
}
  1. 使用继承必须满足逻辑关系:子类 is a 父类,也就是不能滥用继承。
  2. Java语言中只支持单继承不支持多继承,也就是说一个子类只能有一个父类,但一个父类可以有多个子类。
    子类对象创建的原理分析
    继承关系的框架

2.4 方法重写

2.4.1 方法重写的概念

  • 从父类中继承下来的方法不满足子类的需求时,就需要在子类中重新写一个和父类一样的方法来覆盖从父类中继承下来的版本,该方式就叫做方法的重写(Override)。举例说明:
  • 父类Person类中的show方法:
public void show() {
	System.out.println("我是" + getName() + ",今年" + getAge() + "岁了!");
}
  • 子类Worker类中,重写show方法:
@Override  // 标注/注解,用于说明下面的方法是对父类方法的重写,若没有构成重写则编译报错
public void show() {
	super.show(); // 表示调用父类的show方法
	System.out.println("我的薪水是:" + getSalary());
}

2.4.2 方法重写的原则

  • 要求方法名相同、参数列表相同以及返回值类型相同,从Java5开始允许返回子类类型。
  • 要求方法的访问权限不能变小,可以相同或者变大。
  • 要求方法不能抛出更大的异常(异常机制)。

2.5 Java开发的常用工具

  • 文本编辑器(TE,Text Editor)
    • 记事本、Notepad++、Edit Plus、UltraEdit、…
  • 集成开发环境(IDE,Integrated Development Environment )
    • Jbuilder、NetBeans、Eclipse、MyEclipse、IDEA、…
  • IDEA下载和安装方式
    • 下载地址:https://www.jetbrains.com/
    • 安装方式:一路点击下一步默认安装即可

2.6 构造块和静态代码块的考点

  • 构造块和静态代码块的执行顺序:
    1. 先执行父类的静态代码块,再执行子类的静态代码块。
    2. 执行父类的构造块,执行父类的构造方法体。
    3. 执行子类的构造块,执行子类的构造方法体。
// 自定义父类SuperTest类
public class SuperTest {

    {
        System.out.println("SuperTest类中的构造块!"); // (3)
    }

    static {
        System.out.println("SuperTest类中的静态代码块!"); // (1)
    }

    public SuperTest() {
        System.out.println("SuperTest类中的构造方法体!"); // (4)
    }
}
// 自定义子类SubSuperTest类
public class SubSuperTest extends SuperTest {

    {
        System.out.println("SubSuperTest类中的构造块!"); // (5)
    }

    static {
        System.out.println("SubSuperTest类中的静态代码块!"); // (2)
    }

    public SubSuperTest() {
        System.out.println("SubSuperTest类中的构造方法体!"); // (6)
    }

    public static void main(String[] args) {

        // 使用无参方式构造子类的对象
        SubSuperTest sst = new SubSuperTest();
    }
}
/*
执行结果:
SuperTest类中的静态代码块!
SubSuperTest类中的静态代码块!
SuperTest类中的构造块!
SuperTest类中的构造方法体!
SubSuperTest类中的构造块!
SubSuperTest类中的构造方法体!
*/

3、访问控制

3.1 权限修饰符

3.1.1 常用的权限修饰符

修饰符本类同一个包中的类子类其他类
public可以访问可以访问可以访问可以访问
protected可以访问可以访问可以访问不能访问
默认可以访问可以访问不能访问不能访问
private可以访问不能访问不能访问不能访问

3.1.2 注意事项

  • public修饰的成员可以在任意位置使用。
  • private修饰的成员只能在本类内部使用。
  • 通常情况下,成员方法都使用public关键字修饰,成员变量都使用private关键字修饰。

3.2 包

3.2.1 package语句的由来

  • 定义类时需要指定类的名称,但如果仅仅将类名作为类的唯一标识,则不可避免的出现命名冲突的问题。这会给组件复用以及团队间的合作造成很大的麻烦!
  • 在Java语言中,用包(package)的概念来解决命名冲突的问题。

3.2.2 包的定义

  • 在定义一个类时,除了定义类的名称一般还要指定一个包名,格式如下:
package 包名;
package 包名1.包名2.包名3...包名n;
  • 意义:为了实现项目管理、解决命名冲突以及权限控制的效果。

3.2.3 定义包的规范

  • 如果各个公司或开发组织的程序员都随心所欲的命名包名的话,仍然不能从根本上解决命名冲突的问题。因此,在指定包名的时候应该按照一定的规范。
org.apache.commons.lang.StringUtil
  • 其中StringUtils是类名,而org.apache.commons.lang是多层包名,其含义如下:
    • org.apache表示公司或组织的信息(是这个公司(或组织)域名的反写);
    • commons 表示项目的名称信息;
    • lang 表示模块的名称信息。

3.2.4 包的导入

  • 使用import关键字导入包。
  • 使用import关键字导入静态成员,从Java5.0开始支持。

4、final关键字

4.1 基本概念

  • final本意为"最终的、不可改变的",可以修饰类、成员方法以及成员变量。
  • 语法格式:
public final class 类名 {};
public static final 数据类型 成员变量名;
public static final 返回值类型 成员方法名() {};

4.2 使用方式

  • final关键字修饰类体现在该类不能被继承。
    • 主要用于防止滥用继承,如:java.lang.String类等。
  • final关键字修饰成员方法体现在该方法不能被重写但可以被继承。
    • 主要用于防止不经意间造成重写,如:java.text.Dateformat类中format方法等。
  • final关键字修饰成员变量体现在该变量必须初始化且不能改变。
    • 主要用于防止不经意间造成改变,如:java.lang.Thread类中MAX_PRIORITY等。

4.3 常量的概念

  • 在以后的开发中很少单独使用final关键字来修饰成员变量,通常使用public static final关键字共同修饰成员变量来表达常量的含义,常量的命名规范要求是所有字母都要大写,不同的单词之间采用下划线连接。
public static final double PI = 3.14;
这篇关于JavaSE(九):static关键字和继承的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!