static关键字和继承
案例:实现People类的封装
//编程实现People类的封装
public class People{
//1、私有化成员变量,使用private关键字修饰
private String name;
private int age;
//private String country;//隶属于对象层级,也就是每个对象都拥有独立一份
private static String country;//隶属于类层级,也就是整个类只有一份且被所有对象共享
//3、在构造方法中调用set方法进行合理值得判断
public People(){}//构造方法中不需要
public People( String name, int age/*, String country*/ ){
setName( name );
setAge( age );
//setCountry( country );
}
//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 String getCountry(){
return country;
}
public void setCountry( String country ){
//this.country = country;不在属于对象层级
People.country = country;
}
//4、自定义其他成员方法
public void show(){
System.out.println("我是" + getName() + ",今年" + getAge() + "岁了,来自" + getCountry());
}
}
//编程实现People类得测试
public class PeopleTest{
public static void main( String[] args ){
//1、使用有参方式构造两个people类型得对象并打印特征
People p1 = new People("zhangfei", 30, "china");
p1.show(); //"zhangfei", 30, "china"
People p2 = new People("guanyu", 35, "china");
p2.show(); //"guanyu", 35, "china"
}
}
使用static关键字修饰成员变量表示静态的含义,此时成员变量由对象层级提升为类层级,也就是整个类只有一份并被所有对象共享,该成员变量随着类的加载准备就绪,与是否创建对象无关。
static关键字修饰的静态成员变量可以被类的所有成员访问,改变其中一个则所有的就改变。
使用方式:
- 在非静态成员方法中既能访问非静态成员又能访问静态成员。
( 成员:成员变量 + 成员方法, 静态成员被所有对象共享 ) - 在静态成员方法中只能访问静态成员不能访问非静态成员
( 成员:成员变量 + 成员方法,因为此时可能还没有创建对象 ) - 在以后的开发中只有隶属于类层级并被所有对象共享的内容才可以使用static关键字修饰。(不能滥用static关键字)
构造块:在类体中直接使用{}括起来的代码块。
作用:当需要在执行构造方法体之前做一些准备工作时,则将准备工作的相关代码写在构造块中即可,比如:对成员变量进行统一初始化操作
特点:每创建一次对象就会执行一次构造块。
静态代码块:在括号前面加上一个static即可,
静态代码块会随着类的加载而准备就绪,会先于构造快执行;
当需要在执行代码块之前随着类的加载做一些准备工作时,则编写代码到静态代码块中,例如:加载数据库的驱动包等;
案例:编程实现单例模式的封装(只能创建该类一个对象(有且仅有))
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(){
if( null == sin ){
sin = new Singleton();
}
return sin;
}
}
//对上面代码的测试
public static SingletonTest{
public static void main( String[] args ){
Singleton s1 = new Singleton.getInstance();
Singleton s2 = new Singleton.getInstance();
System.out.println( s1 == s2 ); //true
}
}
单例模式的实现方式有两种:饿汉式 和 懒汉式,在以后的开发中推荐饿汉式。
3.2 继承
当多个类之间有相同的特征和行为式,可以将相同的内容提取出来组成一个公共类,让多个类吸收公共类中已有特征和行为而在多个类型只需要编写自己独有特征和行为的机制,叫做继承。
使用extends( 扩展 )关键字来表示继承关系。
使用继承提高了代码的复用性,可维护性以及扩展性,是多态的前提条件。
public class Worker extends Person(){} - 表示Worker类继承自Person类
其中Person类叫做超类、父类、基类。
其中Worker类叫做派生类、子类、孩子类。
案例:实现Person类封装
//实现Person类封装
public class Person{
//1、私有化成员变量,使用private关键字修饰
private String name;
private int age;
//3、在构造方法中调用set方法进行合理值判断
public Person(){}
public Person( String name, int age ){
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 Person{
private int salary;
public Worker(){
super();//表示调用父类的无参构造函数,若没有则编译器自动添加
}
public Worker( String name, int age, int salary ){
super( name, age );//表示调用父类的有参构造方法;下面两行可注释
// 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() );
}
}
//自定义Teacher类继承自Person类
public class Teacher extends Person{
}
//编程实现Worker类测试
public class WorkerTest{
public static void main( String[] args ){
//1、使用无参方式构造worker类型对象并打印特征
Worker w1 = new Worker();
//当子类重写show方法后,则下面调用的是重写以后的版本
w1.show(); // null 0
//2、使用有参方式来构造worker类型的对象并打印特征
Worker w2 = new Worker("zhangfei", 30, 3000);
w2.show(); // "zhangfei", 30
//3、调用成员方法测试
w2.eat("豆芽");
w2.play( "王者" );
w2.work();
}
}
继承特点:
- 子类不能继承父类的构造方法和私有方法,但私有成员变量可以被继承只能不能直接访问。
- 无论使用何种方式构造子类的对象时都会自动调用父类的无参构造方法,来初始化从父类继承的成员变量,相当于在构造方法第一行增加**super()**的效果。
- 使用继承应该满足一个逻辑关系: 子类 is a 父类,也就是不能滥用继承。
- Java语言中只支持单继承不支持多继承,也就是说一个子类只能有一个父类,但一个父类可以有多个子类。
方法重写:从父类中继承下来的方法不满足子类的需求时,就需要在子类中重新写一个和父类一样的方法覆盖从父类中继承下来的版本,该方法就叫做方法重写(override).
重写原则:
- 要求方法名相同,参数列表相同以及返回值类型相同,从javas5开始允许返回子类类型。
- 要求方法的访问权限不能变小,可以相同或者变大。
- 要求方法不能抛出更大的异常(异常机制)。