9.29-Static关键字与继承
Static关键字
特点
static是一个修饰符,用于修饰成员
static修饰的成员被所有的对象所共存
static优先于对象而存在,因为static修饰的成员随着类的加载已经存在了
static修饰的成员多了一种调用方式,可以直接被类名.静态成员的方式来调用
static修饰的数据是共享数据,对象中储存的数据是特有数据
例子
package day02;
public class StaticDemo {
public static void main(String[] args) {
Person.method();
Person p = new Person("张三",23);
p.show();
}
}
class Person{//描述中国人
private String name;
private int age;
static String country = "CN";//国籍 静态变量
public Person(String name,int age) {
this.name = name;
this.age = age;
}
/*
* ①静态方法中只能访问静态的成员
* ②静态方法中不能使用this和super关键字
*/
public /*static*/ void show() {
System.out.println
(Person.country+":"+this.name+":"+this.age);
}
public static void method() {
System.out.println(Person.country);
}
}
成员变量与静态变量的区别
两个变量的生命周期不同
成员变量随着对象的创建而存在,随着对象的被回收而回收
静态变量随着类的加载而存在,随着类的消失而消失
调用方式不同
成员变量只能被对象调用
静态变量可以被对象调用,也可以被类名调用
别名不同
成员变量也叫实例变量
静态变量也叫做类变量
数据的存储位置不同
成员变量的数据储存在堆内存的对象中,也叫做对象的特有数据
静态变量数据储存在方法区的静态方法区(数据共享区)中,所以也叫做对象的共享数据
静态的使用场景
静态变量
当分析对象中所具备的值都是相同的,这时就可以被静态修饰,只要数据在对象中是不同,就是对象的特有数据,必须储存在对象中,是非静态的
静态方法
方法中是否静态修饰,参考该方法是否有访问到对象的特有数据,如果有,就定义成非静态的,如果没有则定义成静态。
静态代码块(定义在类中)
package day9_29;
public class StaticCodeDemo {
public static void main(String[] args) {
new StaticCode().show();
new StaticCode().show();
}
}
class StaticCode{
/*
* 静态代码块
* 静态代码块随着类的加载而执行,且只执行一次
* 作用:给类进行初始化
*/
static {
System.out.println("Hello,Static Code!");
}
void show() {
System.out.println("Show Run!");
}
}
构造代码块(定义在类中)
package day9_29;
public class ConsCodeDemo {
public static void main(String[] args) {
baby b1 = new baby();
b1.speak();
baby b2 =new baby("旺财");
b2.speak();
baby b3 = new baby("张三",3);
b3.speak();
}
}
class baby{
{//构造代码块,用于给全体对象进行初始化
cry();
}
private String name;
private int age;
public baby(){
this.name="baby";
this.age=1;
// cry();
}
public baby(String name) {
this.name=name;
// cry();
}
public baby(String name,int age) {
this.name=name;
this.age=age;
// cry();
}
public void speak() {
System.out.println(name+","+age);
}
public void cry() {
System.out.println("wawa");
}
}
面试小问题
一个类中有静态代码块、构造代码块、构造器,它们执行的先后顺序是什么?
静态代码块、构造代码块、构造器
继承(extends)
例子
package day9_29;
public class ExtendsDemo01 {
public static void main(String[] args) {
Student s = new Student();
s.name="张三";
s.age=23;
s.study();
}
}
//父类
class People{
String name;
int age;
}
//学生类(子类)
class Student extends People{
void study() {
System.out.println("student study,"+name+","+age);
}
}
//工人类(子类)
class Worker extends People{
void work() {
System.out.println("worker work,"+name+","+age);
}
}
好处
提高了代码复用性
让类与类之间产生了父子关系(继承关系/父子关系),给面向对象的第三个特征多态提供了前提
Java中的单继承/多继承
Java中支持单继承,不直接支持多继承,但是对C++中的多继承机制进行了改良(多实现)
单继承
一个子类只能有一个直接父类
多继承
一个子类可以有多个直接父类(Java中不允许)
多继承会产生调用的不确定性,所以Java中不受支持
多层(重)继承
A继承B,B继承C,C继承D,此时,A、B、C都拥有D的内容继承
在子父类中成员的特点体现
成员变量
当本类中成员和局部变量重名时,使用this区分重名变量;当子父类中的成员变量重名时,使用super区分父类
简单来说,this可以在本类访问本类的成员变量和成员方法,super可以在子类访问父类的成员变量和方法
this代表的是一个本类对象的引用(当前对象)
super代表的是一个父类空间
package day9_29;
public class ExtendsDemo02 {
public static void main(String[] args) {
Son s = new Son();
s.show();
}
}
class Father{
int num=4;
}
class Son extends Father{
int num=5;
void show() {
System.out.println(this.num+","+super.num);
}
}
package day9_29;
public class ExtendsDemo02 {
public static void main(String[] args) {
Son s = new Son();
s.show();
}
}
class Father{
private int num=4;
public int getNum() {
return num;
}
public void setNum(int num) {
this.num=num;
}
}
class Son extends Father{
int num=5;
void show() {
System.out.println(this.num+","+super.getNum());
}
}
注意,super与this均可以正常调用父类方法,但this是由继承而来的间接调用,super则是直接调用
成员方法
特点
当子父类中,出现一模一样的方法时,会运行子类中的方法,这种现象称之为覆盖操作,也称之为方法的重写;重写是方法在子父类中的特性
方法的两个特性:
重载,发生在同一个类中(overload)
重写,发生在子类中(override)
package day9_29;
public class ExtendsDemo03 {
public static void main(String[] args) {
Son s = new Son();
s.show();
s.show();
}
}
class Father{
void show(){
System.out.println("father show run");
}
}
class Son extends Father{
void show(){
System.out.println("son show run");
}
}
注意事项
子类重写父类方法时,子类权限必须大于等于父类权限
静态只能覆盖静态或被静态覆盖
构造器
子类继承了父类,获取到父类的内容(属性),所以在使用自己的父类属性之前,要看父类是如何在自己的构造器中对自己的属性进行初始化的;所以在子类构造对象时,必须访问父类中的构造器,为了完成这个必须的动作,子子类中隐入super(语句),super()调用的是父类的无参构造器,那么必须必须在子类构造器中使用super明确的调用父类的有参构造器,在()中增加参数即可。
同时子类构造器中,如果使用了this调用了本类的其他构造器,那么super则无效,因为super与this都是必须被定义在第一行,所以只能有一个,但是可以保证的是,子类中肯定有其他的构造器能够访问父类的构造器
例子
package day02;
public class ExtendsDemo05 {
public static void main(String[] args) {
Son s = new Son();
}
}
class Father{
int num;
public Father() {
num = 10;
System.out.println("Father run");
}
public Father(int x) {
System.out.println("Father run"+x);
}
}
class Son extends Father{
/*
* 在子类构造器中的第一行有一个默认的隐式语句
* super(),super()调用的是父类的无参构造器
* 如果父类中没有无参构造器,那么必须在子类
* 构造器中使用super明确的调用父类的有参构造器
* 在()中指定参数即可
*/
public Son() {
// super(5);
System.out.println("Son run"+num);
}
public Son(int x) {
this();
// super();//必须定义在第一行(语法规则)
System.out.println("Son run"+x);
}
}
最后更新于