Java:14-static关键字和继承

static关键字和继承

案例题目------------------------------
编程实现People类的封装,特征有:姓名,年龄,国籍,要求提供打印所有特征的方法
编程实现PeopleTest类,main方法中使用有参方式构造两个对象并打印
/*
    编程实现People类的封装
 */
public class People {
	//私有化成员变量 使用private关键字修饰
	private String name;
	private int age;
	//private String country; //隶属于对象层级,也就是每个对象都拥有独立的一份
	//public static String country; //隶属于类层级,也就是整个类只有一份并且被所有对象共享
	private static String country; //不可以在类外使用
	//在构造方法中调用set方法进行合理值的判断
	public People(){
		
	}
	public People(String name,int age/*,String country*/){
		setName(name);
		setAge(age);
		//setCountry(country);
	}
	//提供公有的get和set方法,并在方法体中进行合理值的判断
	public String getName(){
		return name;
	}
	public void setName(String name){
		this.name = name;
	}
	public int getAge(){
		return age;
	}
	public void setAge(int age){
		if(age > 0 && age < 150){
		this.age = age;
		}else{
			System.out.println("年龄不合理");
		}
	}
	public static String getCountry(){
		return country;
	}
	public static void setCountry(String country){
		//this.country = country;
		People.country = country;
	}
	public void show(){
		System.out.println("该学生的姓名是:" + 
		getName() + ",年龄是:" + getAge() + ",国籍是:" + getCountry());
	}
	
	
	
	
}
/*
    编程实现People类的测试
 */
public class PeopleTest {
	
	public static void main(String[] args) {
		//验证static关键字修饰的静态成员(类成员)是否与创建对象无关 类名.的方式 =>无关
		//System.out.println("国籍是" + People.country); //null
		System.out.println("国籍是" + People.getCountry()); //null
		//使用有参方式构造两个People类型的对象并打印特征
		People p1 = new People("张三",14/*,"中国"*/);
		p1.show(); //张三 14 中国
		People p2 = new People("李四",15/*,"中国"*/);
		p2.show(); //李四 15 中国
		System.out.println("-----------------------------------------------");
		//验证static关键字修饰的静态成员(类成员)是否被所有对象共享 =>
		//p1.country = "蜀国";
		p1.setCountry("蜀国");
		//System.out.println("第一个国籍是" + p1.country);
		//System.out.println("第二个国籍是" + p2.country);
		System.out.println("第一个国籍是" + p1.getCountry());
		System.out.println("第二个国籍是" + p2.getCountry());
		People p3 = new People();
		//System.out.println("第三个国籍是" + p3.country);
		System.out.println("第三个国籍是" + p3.getCountry());
		
	}
	
	
}
使用static关键字修饰成员变量表示静态的含义,此时成员变量由对象层级提升为类层级
也就是整个类只有一份并被所有对象共享,该成员变量随着类的加载准备就绪,与是否创建对象无关
而被静态static修饰的东西(变量,方法)都放在方法区中

在这里插入图片描述

static关键字修饰的成员变量可以使用引用.的方式访问(但最终也是去方法区里而已,即也操作类名.的方式的,这也是为什么this不能操作静态的原因,因为this就不会去方法区里面获取),但推荐类名.的方式
但是一般类名.的方式只有在public下才可以,否则是不行的,这个时候基本只能操作引用了,因为类名.的方式代表是项目全局的,这是一个规定
static关键字的使用方式------------------------------
在非静态成员方法中既能访问非静态的成员又能访问静态的成员
(成员:成员变量 + 成员方法,静态成员被所有对象共享)
在静态成员方法中只能访问静态成员变量不能访问非静态成员
(成员:成员变量 + 成员方法,因为此时可能还没有创建对象)
在以后的开发中只有隶属于类层级并被所有对象共享的内容才可以使用
static关键字修饰(不能滥用static关键字)
/*
    编程实现static关键字的使用
 */
public class StaticTest {
	
	private int cnt = 1; //隶属于对象层级,也就是每个对象都拥有独立一份
	private static int snt = 2; //隶属于类层级,也就所有对象都共享同一份
	
	//自定义非静态的成员方法 需要使用引用.的方式访问
	public void show(){
		System.out.println("cnt = " + this.cnt); // 1
		System.out.println("snt = " + this.snt); // 2 //静态成员被所有对象共享,this关键字可以省略
	}
	//自定义静态的成员方法 推荐使用类名.的方式访问
	public static void test(){
		//System.out.println("cnt = " + this.cnt); // 错误: 无法从静态上下文中引用非静态 变量 this
		//System.out.println("snt = " + this.snt); // 错误: 无法从静态上下文中引用非静态 变量 this
		//静态方法中没有this关键字,因为是可以通过类名.方式调用的
		//StaticTest st = new StaticTest();
		//System.out.println("cnt = " + cnt); // 错误: 无法从静态上下文中引用非静态 变量 cnt (默认有this)
		//对象层级 需要对象
		System.out.println("snt = " + snt); //类层级,对于静态来说,默认不加this,而是类.
		//因为有没创建对象的可能性,所以就算是引用.方式,也要在里面创建对象
	}
	public static void main(String[] args) {
		StaticTest st = new StaticTest();
		st.show();
		System.out.println("-----------------------------------------------");
		StaticTest.test(); 
		
	}
	
}
构造块和静态代码块------------------------------
构造块:在类体中直接使用{}括起来的代码块
每创建一个对象都会执行一次构造块
静态代码块:使用static关键字修饰的构造块
静态代码块随着类加载时执行一次
/*
    编程实现构造块和静态代码块的使用
 */
public class BlockTest {
	//当需要在执行构造方法体之前做一些准备工作时,则将准备工作的相关代码写在构造块中即可
	//比如:对成员变量进行的统一的初始化操作
	//这样就可以不通过其他不同的构造方法来初始化不同的结果了
	{
		System.out.println("构造块");
	}
	//静态代码块先运行 静态代码块>构造块>构造方法
    //对于有父类的则会先调用父类的静态代码块,其他依次执行
	//静态代码块会随着类的加载而准备就绪,所以会先于构造块
    //而类只加载一次 所以静态代码块就执行一次
	//当需要在执行代码块之前随着类的加载做一些准备工作,则编写代码到静态代码块中
	//比如:加载数据库的驱动包等
	static{ 
		System.out.println("静态代码块");
	}
	
	//自定义构造方法
	public BlockTest(){
		System.out.println("构造方法体!");
	}
	
	
	public static void main(String[] args){
		
		BlockTest bt = new BlockTest(); //构造块先运行
		BlockTest bt2 = new BlockTest();
		
	}
	
	
}
main方法的详解------------------------------
语法格式
public static void 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]);
			
		}
		//要给main传参需要在执行的后面写上某个数,即该数为传的参数
		//如编译后 java MainTest 80 ,其中80是你传入的参数,即给args初始化了
		//即args的长度为1,args[0] = 80;
		
		
	}
	
}
案例题目------------------------------
编程实现Singleton类的封装
编程实现singletonTest类对Singleton类进行测试,要求main方法中能得到且只能得到该类的一个对象
/*
    编程实现Singleton类的封装
 */
public class Singleton {
	
	// 2.声明本类类型的引用指向本类类型的对象,使用private static关键字共同修饰
	//private static Singleton sin = new Singleton();  // 饿汉式
	private static Singleton sin = null;               // 懒汉式
	
	// 1.私有化构造方法,使用private关键字修饰
	private Singleton() {}
	
	// 3.提供公有的get方法负责将对象返回出去,使用public static关键字共同修饰
	public static Singleton getInstance() {
		//return sin;
		if(null == sin) {
			sin = new Singleton();
		}
		return sin;
	}
}
/*
    编程实现Singleton类的测试
 */
public class SingletonTest {
	
	public static void main(String[] args) {
		
		// 1.声明Singleton类型的引用指向该类型的对象
		//Singleton s1 = new Singleton();
		//Singleton s2 = new Singleton();
		//System.out.println(s1 == s2); // 比较变量s1的数值是否与变量s2的数值相等  false
		//Singleton.sin = null;  可以使得引用变量无效
		Singleton s1 = Singleton.getInstance();
		Singleton s2 = Singleton.getInstance();
		System.out.println(s1 == s2); // true
	}
}
对于封装------------------------------
当对非静态,静态,对象的东西都进行封装操作时,都是防止其他类乱用封装的类的一些东西而设置的

在这里插入图片描述

静态变量隶属于类层级并被所有对象共享,所以静态变量的内存空间依然在方法区
在某些特殊场合中,一个类对外提供且只提供一个对象时,这样的类叫做单例类,而设计单例的流程和思想叫做单例模式
私有化构造方法,使用private关键字修饰
声明本类类型的引用指向本类类型的对象,并使用private static关键字共同修饰
提供公有的get方法负责将对象返回出去,并使用public static关键字共同修饰
单例设计模式的实现方式有两种:饿汉式和懒汉式,在以后的开发中推荐饿汉式(虽然没有使用时,会多一个对象,但是考虑锁或者多线程来说,一般需要大量的多线程,那么是好的,而公司用户多,线程自然多,所以公司一般使用饿汉式,虽然也可以使用懒汉式,具体看自己如何操作了)
之所以不用懒汉式则是考虑多线程资源占用
继承的由来和概念------------------------------
当多个类之间有相同的特征和行为时,可以将相同的内容提取出来组成一个公共类
让多个类吸收公共类中已有的特征和行为而在多个类型只需要编写自己独有特征和行为的机制,叫做继承
在Java语言中使用extends(扩展)关键字来表示继承关系
如:
public class Worker extends Person2{} -表示Worker类继承自Person2类
其中Person2类叫做超类,父类,基类
其中Worker类叫做派生类,子类,孩子类
/*
    编程实现Person类的封装
 */
public class Person2 {
	
	// 1.私有化成员变量,使用private关键字修饰
	private String name;
	private int age;
	//private boolean gender; // 性别 增加性别即所有的子类都有
	
	// 3.在构造方法中调用set方法进行合理值的判断
	public Person2() {
		System.out.println("Person2()");
	}
	public Person2(String name, int age) {
		System.out.println("Person2(String, int)");
		setName(name);
		setAge(age);
	}
	
	// 2.提供公有的get和set方法并在方法体中进行合理值的判断
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	public int getAge() {
		return age;
	}
	public void setAge(int age) {
		if(age > 0 && age < 150) {
			this.age = age;
		} else {
			System.out.println("年龄不合理哦!!!");
		}
	}
	
	// 自定义成员方法实现特征的打印
	public void show() {
		System.out.println("我是" + getName() + ",今年" + getAge() + "岁了!");
	}
	// 自定义成员方法描述吃饭的行为
	public void eat(String food) {
		System.out.println(food + "真好吃!");
	}
	// 自定义成员方法描述娱乐的行为
	public void play(String game) {
		System.out.println(game + "真好玩!");
	}
}
/*
    自定义Worker类继承自Person类
 */
public class Worker extends Person2 {
	private int salary;
	public Worker() {
		super(); // 表示调用父类的无参构造方法,若没有加则编译器自动添加,且是最前面,与this也是一样的哦(加在前面的理由也是对应的主观问题)
		System.out.println("Worker()");
	}
	public Worker(String name, int age, int salary) {
		super(name, age); // 表示调用父类的有参构造方法
		System.out.println("Worker(String, int, int)");
		//setName(name);
		//setAge(age);
		setSalary(salary);
	}
	public int getSalary() {
		return salary;
	}
	public void setSalary(int salary) {
		if(salary >= 2200) {
			this.salary = salary;
		} else {
			System.out.println("薪水不合理哦!!!");
		}
	}
	
	// 自定义成员方法描述工作的行为
	public void work() {
		System.out.println("今天的砖头有点烫手...");
	}
	// 自定义show方法覆盖从父类中继承的版本
	@Override  // 标注/注解,用于说明下面的方法是对父类方法的重写,若没有构成重写则编译报错
	public void show() {
		super.show(); // 表示调用父类的show方法
		System.out.println("我的薪水是:" + getSalary());
	}
}

在这里插入图片描述

使用继承提高了代码的复用性,可维护性及扩展性,是多态的前提条件(因为主要需要类来进行操作,而不是接口(不能操作),内部类也是类哦)
子类不能继承父类的构造方法,私有方法和私有成员变量可以被继承只是不能直接访问,其他的基本上都可以被继承(包括静态)
这个继承的意思可以说是子类算作大格子,父类算小格子
且该小格子在大格子里,即大格子可以调用小格子的东西,但私有的不可以直接调用
即可以说子类继承父类的私有的东西,也可以说子类不继承父类的私有的东西
无论使用何种方式构造子类的对象时都会自动调用父类的无参构造方法
来初始化从父类中继承的成员变量,相当于在构造方法的第一行增加代码super()的效果
/*
    编程实现Worker类的测试
 */
public class WorkerTest {
	
	public static void main(String[] args) {
		
		// 1.使用无参方式构造Worker类型的对象并打印特征
		Worker w1 = new Worker();
		// 当子类重写show方法后,则下面调用的是重写以后的版本
		w1.show(); // null  0
		
		System.out.println("----------------------------------");
		// 2.使用有参方式构造Worker类型的对象并打印特征
		Worker w2 = new Worker("zhangfei", 30, 3000);
		w2.show(); // zhangfei ...
		// 调用成员方法测试
		w2.eat("豆芽");
		w2.play("王者荣耀");
		w2.work();
		System.out.println(w2.getName()); //zhangfei
	}
}
/*
    编程实现Teacher类继承自Person类
 */
public class Teacher extends Person {   
	
}
/*
     编程实现Teacher类的测试
 */
public class TeacherTest {
	
	public static void main(String[] args) {
		
		// 1.使用无参方式构造Teacher类型的对象并打印特征
		Teacher t1 = new Teacher();
		t1.show(); // null 0
	}
}
/*
    编程实现ComputerTeacher类继承自Teacher类
 */
public class ComputerTeacher extends Teacher {
	
}

在这里插入图片描述

使用继承必须满足逻辑关系:子类 is a 父类(is a:一种),也就是不能滥用继承
Java语言中只支持单继承不支持多继承,也就是说一个子类只能有一个父类,但一个父类可以有多个子类
C++可以多继承,可能各有优点,具体可以百度
从父类中继承下来的方法不满足子类的需求时,就需要在子类中重新写一个和父类一样的方法来覆盖从父类中继承下来的版本
该方式就叫做方法的重写(Override),注意:无论是继承类,还是实现接口(后面会说明的)基本都是如此
方法重写的原则------------------------------
要求方法名相同,参数列表相同以及返回值类型相同,从Java5开始允许返回子类类型
即当返回值类型为父类时,重写的返回值类型可以改变为子类类型(考虑多态了)
要求方法的访问权限不能变小,可以相同或者变大,extends(继承)可以叫做扩展,即扩展类的东西
要求方法不能抛出更大的异常(异常机制)
注意:super一般不会改变this,this还是子的
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值