JAVASE-07:static关键字、代码块的概念和继承

练习:长方形类,定义一个长方形(Rectangle)类,定义求周长(length)和面积(area)的方法,然后定义一个测试类Test,进行测试。

package org.westos.MXDX;

public class Rectangle {
    private double Chang;
    private double Kuan;

    public Rectangle() {
    }

    public Rectangle(double chang, double kuan) {
        Chang = chang;
        Kuan = kuan;
    }

    public double getChang() {
        return Chang;
    }

    public void setChang(double chang) {
        Chang = chang;
    }

    public double getKuan() {
        return Kuan;
    }

    public void setKuan(double kuan) {
        Kuan = kuan;
    }

    public double length() {
        double i = 2 * (Chang + Kuan);
        return i;

    }

    public double area() {
        double j = Chang * Kuan;
        return j;
    }
}
package org.westos.MXDX;

import javax.swing.text.ChangedCharSetException;

public class MyTestRectangle {
    public static void main(String[] args) {
        Rectangle rec = new Rectangle();
        rec.setChang(13.2);
        rec.setKuan(5.7);
        System.out.println(rec.getChang());
        System.out.println(rec.getKuan());
        System.out.println(rec.length());
        System.out.println(rec.area());
        System.out.println("--------------------------");

        Rectangle rec1 = new Rectangle(18.3, 12.1);
        System.out.println(rec1.getChang());
        System.out.println(rec1.getKuan());
        System.out.println(rec1.length());
        System.out.println(rec1.area());
    }

}

1. static 关键字

1.1 static–静态的,可以修饰成员变量和成员方法;
修饰成员变量,此变量就为一个共享变量,会被这个类的所有对象所共享

内存图:在这里插入图片描述

1.2 static的特点:
a.它随着类(.class)的加载而加载,优先于对象的创建而存在的;
b.static所修饰的成员是优先于对象而存在的;
c.被类的所有对象所共享;
d.被静态所修饰的成员/变量,是属于类的,建议使用类名直接调用(当然你可以使用对象名调用,但是不推荐)
e.静态变量我们也称之为类变量

1.3 定义静态方法
a.在静态方法里面 不能调用非静态的方法 也调用不到非静态的成员
b.静态所修饰的成员,是随着类的加载而加载,是优先于对象而存在,先有的访问不到后有的,但是后有的可以调用到先有的
c.简单说 在静态方法中,只能访问静态所修饰的成员,不能访问非静态成员
d.非静态方法中,既可以访问非静态成员,也可以访问静态成员,静态只能访问静态
e.在静态方法中,不能存在this关键字,因为this本身代表一个该类的对象,是后来才有的
f.对于提供main方法作为成员入口的这个类(测试类),在这个类中,我们一般不去定义成员变量和成员方法

1.4 为什么main方法要用public static来修饰
方便虚拟机调用

1.5 成员变量和局部变量的区别(复习):

局部变量成员变量
方法中的变量,以及方法的形参类中 方法外的变量
存储在栈内存存储在堆内存
必须赋值才能使用有默认值
属于方法,随着方法的调用而产生,随着方法的调用完毕而消失属于对象,也称之为实例变量,随着对象的创建而产生,随着对象的销毁而销毁

1.6 静态变量和成员变量的区别:

静态变量属于类,也称之为类变量;
存在方法区的静态区;
随着类的加载而产生,随着类的卸载而卸载;
可以使用对象名调用 也可以使用类名调用,推荐使用类名调用


2. Java提供的一个类:Math

之前学过Scanner,查JDK提供的帮助文档学习—

Math类包含用于执行基本数学运算的方法;java.lang包下的类,可以不用导入包;没有构造方法,因为它的成员全部是静态的。

Math.random;  // 生成随机小数(0~1之间)
// 移动代码:ctrl shift +上下键

// 生成随机整数(范围1~100,包含1和100):
int v = (int)(Math.random*10+1)

猜数字小游戏:
(不知道循环次数–用while循环)
给用户十次机会,每猜一次提示剩余次数

package org.westos.MXDX;

import java.util.Scanner;

public class guess {
    public static void main(String[] args) {
        int i = (int) (Math.random() * 10 + 1);
        for (int j = 1; j < 11; j++) {
            Scanner sc = new Scanner(System.in);
            System.out.println("请输入一个数字:");
            int k = sc.nextInt();
            if (k > i & j >= 0) {
                System.out.println("你猜大了" + "你还有" + (10 - j) + "次机会");

            } else if (k < i & j >= 0) {
                System.out.println("你猜小了" + "你还有" + (10 - j) + "次机会");
            } else if (k == i & j >= 0) {
                System.out.println("你猜对了");
                break;
            } else {
                System.out.println("你没有机会了");
                break;
            }
        }
    }
}

3. 代码块的概念

3.1 所谓代码块就是被一对大括号{}所括起来的代码;

3.2 分类:局部代码块,构造代码块,静态代码块,同步代码块(多线程讲)

局部代码块:定义在方法中的代码块,有利于资源的及早释放,提高内存利用率

构造代码块:定义在类中 方法外的代码块,每次在调用构造(创建对象)时,构造代码块执行,且构造代码块优先于构造方法执行

静态代码块:(用的比较多)定义在类中、方法外,并且被static所修饰的代码块,因为类只加载一次,所以只执行一次;静态代码块里面只能访问被静态所修饰的成员(优先于任何构造代码块执行)常用于准备的初始化工作

练习:看程序写结果

class Student {
	static {
		System.out.println("Student 静态代码块"); //3
	}

	{
		System.out.println("Student 构造代码块"); //4 6
	}
	
	public Student() {
		System.out.println("Student 构造方法");//5 7
	}
}

class StudentDemo {
	static {
		System.out.println("StudentDemo的静态代码块");  //1
	}
	
	public static void main(String[] args) {
		System.out.println("我是main方法"); //2
	
		Student s1 = new Student();
		Student s2 = new Student();
	}
}

4. 继承

继承概述:

​ 多个类中存在相同属性和行为时,将这些内容抽取到单独一个类中,那么多个类无需再定义这些属性和行为,只要继承那个类即可。

继承格式:
通过extends关键字可以实现类与类的继承

​ class 子类名 extends 父类名 {}

​ 单独的这个类称为父类,基类或者超类;这多个类可以称为子类或者派生类。

4.1 extends

作用:可以提高代码的复用性和维护性

弊端:让类和类之间产生关系,那就增加了耦合性。

程序的设计原则:高内聚(内聚:一个类能独立完成某个功能的能力),低耦合(耦合:类和类之间有一种依赖关系)

继承的特点:

a.Java只支持单继承,一个子类只能有一个父类;但是支持多层继承

b.子类只能继承父类非私有的成员(成员方法和成员变量)

c.构造方法不参与继承,但是可以通过super关键字去访问父类构造方法。

d.不要为了部分功能去继承

继承的思想:继承就是把多个子类的共性部分,向上抽取到父类当中,以实现代码的复用性和维护性

就近原则:局部变量和成员变量重名时,变量访问原则遵循就近原则:a.先在局部范围(方法内和形参),如果找到就使用,b.找不到就去该类成员范围找;如果在该类的成员范围没有找到,c.那么就去该类的父类成员范围找,d.还没有找到就报错。

// 练习:构造学生类
package org.westos.JiCheng;

public class Test {
    public static void main(String[] args) {
        Boys xiaoming = new Boys();
        System.out.println(xiaoming.name = "小明");
        System.out.println(xiaoming.age = 16);
        xiaoming.KaoShi();
        xiaoming.DaJia();

        Girls xiaohong = new Girls();
        System.out.println(xiaohong.sex = "女");
        System.out.println(xiaohong.weight = 99.9);
        xiaohong.TanLianAi();
        xiaohong.GuoJiaJia();
    }
}

class Student {
    String name;
    int age;
    String sex;
    double weight;

    public void XueXi() {
        System.out.println("学习");
    }

    public void KaoShi() {
        System.out.println("考试");
    }

    public void TanLianAi() {
        System.out.println("谈恋爱");
    }
}

class Boys extends Student {
    public void DaJia() {
        System.out.println("打架");
    }
}


class Girls extends Student {
    public void GuoJiaJia() {
        System.out.println("过家家");
    }
}
// 练习:看程序写出执行结果(考察代码块和继承)
package org.westos.demo91;

class Fu { //Fu.class
    static {
        System.out.println("静态代码块Fu"); //1
    }

    {
        System.out.println("构造代码块Fu"); //3
    }

    public Fu() {
        System.out.println("构造方法Fu"); //4
    }
}

class Zi extends Fu {
    static {
        System.out.println("静态代码块Zi");//2
    }

    {
        System.out.println("构造代码块Zi"); //5
    }

    public Zi() {

        System.out.println("构造方法Zi"); //6
    }
}

class Test {
    public static void main(String[] args) {
        //你初始化子类的时候,先要初始化父类。
        Zi z = new Zi(); //请执行结果。
    }
}

4.2 super

代表父类空间的一个标识,可以认为是父类的一个对象,可以使用在子类局部范围访问父类成员变量。

this和super的区别和应用

superthis
代表的是父类存储空间的标识(可以理解成父类的引用,可以操作父类的成员)代表本类的一个引用,你可以认为是本类的一个对象
super():访问父类的空参构造this():访问本类的空参构造
super.成员变量名 :访问父类的成员变量this.成员变量 :访问本类的成员变量
super.成员方法 :访问父类的成员的方法this.成员方法 :访问本类的成员方法
public class MyTest extends Object {
    public static void main(String[] args) {
        //Zi zi = new Zi();
        Zi zi1 = new Zi("aaa", 100);
        //父类的有参构造调用了aaa==100
        //子类的有参构造调用了aaa==100
    }
}

//Java继承体系中的顶层父类是Object类,所有类都是直接或间接继承自他
class Fu extends Object {
    int num = 100;

    public Fu() {
        super();
        System.out.println("父类的空参构造调用了");
    }

    public Fu(String name) {
        super();
        System.out.println("父类的有参构造调用了");
    }

    public Fu(String name, int age) {
        super();
        System.out.println("父类的有参构造调用了" + name + "==" + age);
    }
}

class Zi extends Fu {
    public Zi() {
        super("abc"); //调用父类有参构造
        System.out.println("子类的空参构造调用了");
    }

    public Zi(String str) {
        // this();和super(); 不能同时存在在构造方法里面
        this();//调用本类空参构造
        //this("abc",23); //调用本类有参参构造
        System.out.println("子类的有参构造调用了");
    }

    public Zi(String str, int age) {
        // this();和super(); 不能同时存在在构造方法里面
        super(str, age);
        System.out.println("子类的有参构造调用了"+ str + "==" + age);
    }

}

继承中构造方法的关系

我们在创建子类对象时,为什么会先去调用父类的构造方法呢?—因为子类要继承或使用父类的数据,所以在初始化子类的时候,先要调用父类的构造方法,来完成父类数据的初始化,这样子类才能够继承父类的数据和使用父类的数据。

在每个类的构造方法中的第一行,有一行默认语句是super(),会去调用父类的空参构造,来完成父类数据的初始化;

Java继承体系中的顶层父类是Object类,所有类都是直接或者间接继承自它。

继承中构造方法的注意事项:

当父类没有空参构造,怎么办?想办法调用父类有参构造a: 在父类中添加一个无参的构造方法;b:子类通过super去显示调用父类其他的带参的构造方法;c:子类通过this去调用本类的其他构造方法,本类其他构造也必须首先访问了父类构造

this()和super()不能同时存在在构造方法里面

public class MyTest {
    public static void main(String[] args) {
        Zi zi = new Zi();
        zi.show(10);
    }
}

class Fu {
    int num = 200;
}

class Zi extends Fu {
    int num = 100;

    public void show(int num) {
        System.out.println(num);//10
        System.out.println(this.num);//100
        System.out.println(super.num);//200
    }
}
4.3 方法重写

当子类出现了和父类一模一样的方法时(方法名,方法参数,返回值类型一样)这个时候会出现方法覆盖现象,子类的方法会覆盖父类的方法

为什么要有方法重写的机制:有的时候子类对父类的方法实现不是很满意,他需要扩展或者覆盖父类的方法

ctrl+o快速重写父类的方法 @Override - 注解 用来检测这个方法是不是重写父类的,如果不是就会报错

也可以在父类的基础上进行扩展 沿袭父类的功能super.call();

注意事项:

a.父类私有的方法不能重写,私有方法子类都不能继承何来重写;

b.构造方法不参与重写;

c.重写时,子类在重写父类方法时,方法的权限修饰符,不能比父类的方法低;

d.父类中的 静态方法不参与重写

e.final 修饰的方法 子类不能重写

f.子类重写父类方法的时候,最好声明一模一样。

public class MyTest {
    public static void main(String[] args) {
        Cat cat = new Cat();
        cat.sleep();
        cat.eat();
        System.out.println("======================");
        Dog dog = new Dog();
        dog.eat();
        dog.sleep();
    }
}

public class Animal {
    public void sleep(){
        System.out.println("睡觉");
    }
    public void eat(){
        System.out.println("吃饭");
    }
}

public class Dog extends Animal{
    public void eat(){
        System.out.println("狗吃骨头");
    }

    @Override
    public void sleep() {
        System.out.println("狗喜欢趴着睡觉");
    }
}

public class Cat extends Animal{
    @Override
    public void eat(){
        System.out.println("猫吃鱼");
    }
    
    //Ctrl+O 重写父类的方法
    @Override //@Override 注解 作用:用来检测这个方法,是不是重写父类的。
    public void sleep() {
        System.out.println("猫白天睡觉");
    }

    //@Override 不是重写的方法会报错
    public void show(){

    }
}

4.4 关键字:final–最终的

由于继承中有一个方法重写的现象,而有时候我们不想让子类去重写父类的方法.这对这种情况java就给我们提供了一个关键字: final,可以修饰变量、方法、类。

a. 修饰变量,此变量会变成一个常量–自定义常量,常量名一般大写

public static final int B=1000// 公共的静态常量

修饰基本类型,指的是地址值不能被再次改变

修饰引用类型,则地址值不能被改变

b. 修饰方法,此方法不能被重写 ,可以被继承

c. 修饰类,此类不能被继承

方法重载:允许在一个域中定义多个同名方法,只要他们的参数列表不同

方法重写:要有继承关系,子类出现了和父类一模一样(参数类型 参数个数 返回值类型)的方法

package org.westos.demo94;

public class MyTest {
    //自定义常量
    public final int A=2000;
    //公共的静态常量
    public static final int B = 2000;

    public static void main(String[] args) {
        final int NUM=200; //自定义常量,常量名一般大写
        System.out.println(MyTest.B);// 2000
       
        final Fu fu = new Fu();
        System.out.println(fu); // @1540e19d
        // fu=new Fu();
        // System.out.println(fu);

    }
}

final class Fu{
    public final void show(){
        System.out.println("fu show");
    }
}

/*
class Zi extends Fu{
}
*/
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值