Java代码块与继承
文章目录
1.代码块
- 代码块就是被一堆{}所括起来的代码;
- 根据代码块定义的位置不同;分局部代码块,构造代码块,静态代码块,同步代码块;
- 局部代码块:定义在方法中的代码快
pubilc void codeblock(){
//在方法中出现;限定变量生命周期,及早释放,提高内存利用率
int num = 200;
System.out.println("局部代码块");
System.out.println(num);
}
- 构造代码块
当我们创建对象时,如果构造代码块,再执行代码块,而且构造代码块优先于构造方法执行,构造代码块,可以为该类的所有对象的成员变量赋值
{
System.out.println("构造代码块");
//构造代码块,可以为该类的所有对象的成员变量赋值。
num = 100;
}
- 静态代码块
随着类的加载而加载,优先于构造代码块执行。而且只执行一次,一般在静态代码块里面,做一些提前准备工作,例如:读取配置文件中数据;
在静态代码块里只能访问
static {
System.out.println("静态代码块");
System.out.println("一般在静态代码块里面,做一些提前准备工作。比如我提前读取配置文件中数据。");
System.out.println(num);
}
-
当我们创建对象时,如果构造代码块,那就先执行构造代码块,再执行构造方法,而且构造代码块优先于构造方法执行。
-
练习:以下语句哪条先执行
public class StudentDemo {
static {
System.out.println("StudentDemo的静态代码块"); //()
}
public static void main(String[] args) {
System.out.println("我是main方法"); //()
Student s1 = new Student();
Student s2 = new Student();
}
}
class Student {
static {
System.out.println("Student 静态代码块"); //()
}
{
System.out.println("Student 构造代码块");//()
}
public Student() {
System.out.println("Student 构造方法");//()
}
1 2 3 4 5
2.继承
- Java中的继承,子类可以继承父类的成员,要让类和类之间产生父子关系,采用是extends关键字
class A{
}
class B extends A{
}
2.1继承优势:
提高了代码的复用性,以及维护性
public class Animal {
String name;
int age;
public void eat() {
System.out.println("吃油条");
}
public void sleep() {
System.out.println("睡觉");
}
}
public class Cat extends Animal {
public void catchMouse() {
System.out.println("抓老鼠");
}
}
public class Dog extends Animal {
public void lookDoor() {
System.out.println("看门");
}
}
public class MyTest {
public static void main(String[] args) {
Cat cat = new Cat();
cat.name = "小花";
cat.age = 3;
cat.sleep();
cat.eat();
cat.catchMouse();
System.out.println("=====================================");
Dog dog = new Dog();
dog.name = "旺财";
dog.age = 4;
dog.sleep();
dog.eat();
dog.lookDoor();
}
}
- 继承的弊端
让类和类之间产生了关系,增加了耦合性;
//高内聚:一个事物,独立完成某项功能的能力。耦合:事物和事物之间产生了依赖关系。
2.2继承的注意事项
- Java只支持单继承,一个类,只能由一个父类,可以多层继承
public static void main(String[] args) {
System.out.println(c.a);
System.out.println(c.b);
}
class A {
int a = 20;
}
class B extends A {
int b = 50;
}
class C extends B {
}
- 父类私有的成员,子类无法继承
class A extends Object {
private void show() {
System.out.println("私有方法");
}
}
class B extends A {
int b = 50;
}
class C extends B {
}
-
构造方法不参与继承,创建子类对象时,会调用父类构造方法,因为子类继承了父类数据,还要使用父类数据,父类没有先完成数据的初始化,子类继承父类的数据,甚至要使用父类数据;
所以创建子类对象时,应先完成父类数据的初始化,怎么完成,先调用父类的构造来完成父类数据的初始化。
-
父类构造方法作用:当我们创建子类对象时,要先调用父类的构造方法,完成父类数据的初始化
public class MyTest {
public static void main(String[] args) {
Zi zi = new Zi();
}
}
class Fu {
public Fu() {
System.out.println("Fu 类空参构造执行了");
}
int num = 0;
}
class Zi extends Fu {
int a = 20;
public Zi() {
System.out.println("Zi 类空参构造执行了");
}
public void ziShow() {
System.out.println(num);
}
}
//输出:
//Fu 类空参构造执行了
//Zi 类空参构造执行了
2.3关键字super
- super:是一个父类空间标识,简单理解super就是父类的一个引用;
我们在子类的方法中用super,可以访问父类的数据(成员方法,成员变量,构造方法)
this代表本类的一个引用,用this可以访问本类的数据(成员方法,成员变量,构造方法)
public class MyTest {
public static void main(String[] args) {
B b = new B();
b.show(500);
}
}
class A {
int num = 120;
int a = 100;
}
class B extends A {
int num = 20;
int b = 5000;
public void show(int num) {
System.out.println(num); //500
System.out.println(this.num); //20
System.out.println(super.num); //120
System.out.println(b);
System.out.println(a);
}
}
//就近原则:变量访问遵循就近原则,先本类在局部范围找(形参,方法内部),找到就使用,如果没有找到,就在本类成员范围找(类中方法外)找到就使用。
//如果在本类的成员范围没有找到,就去父类的成员范围找,找到就使用。
访问成员变量 | 访问本类的成员变量 | 访问父类的成员方法 | 访问本类的成员方法 | 访问父类的构造法 | 访问本类构造方法 |
---|---|---|---|---|---|
super.成员变量名 | this.成员变量名 | super.成员方法名() | this.成员方法名() | super( ) | this( ) |
public class MyTest {
public static void main(String[] args) {
Zi zi = new Zi();
zi.haha();
}
}
class Fu {
int num = 200;
int a = 20;
public void show() {
System.out.println("fu show");
}
public void test() {
System.out.println("fu test");
}
}
class Zi extends Fu {
int price = 200;
int age = 20;
public void hehe() {
System.out.println(this.num);
System.out.println(super.num);
System.out.println(age);
System.out.println(this.price);
}
public void haha() {
this.show();
super.show();
this.hehe();
}
}
- 构造方法
所以我们在创建子类对象时,应该先完成父类数据的初始化,怎么完成?先调用父类的构造来完成父类数据的初始化。
在每个类的每个构造方法中的第一行,有一条默认语句 super() 去调用父类的空参构造,先来完成父类数据的初始化。
public class MyTest {
public static void main(String[] args) {
Son son = new Son();
new Son(20);
}
}
class Father extends Object {
int num = 200;
public Father() {
System.out.println("父类空参构造调用了");
}
public Father(int num) {
this();
System.out.println("父类有参构造调用了");
}
}
class Son extends Father {
public Son() {
super(20); //调用父类有参构造
System.out.println("子类的空参构造调用了");
}
public Son(int a) {
this(); //调用本类的构造
}
}
//输出
/*父类空参构造调用了
父类有参构造调用了
子类的空参构造调用了
父类空参构造调用了
父类有参构造调用了
子类的空参构造调用了*/
3.代码块与继承的综合练习题
练习1:
class Fu{
public int num = 10;
public Fu(){
System.out.println("fu"); //1
}
}
class Zi extends Fu{
public int num = 20;
public Zi(){
System.out.println("zi"); //2
}
public void show(){
int num = 30;
System.out.println(num); //30
System.out.println(this.num); //20
System.out.println(super.num); //10
}
}
class Test {
public static void main(String[] args) {
Zi z = new Zi();
z.show();
}
}
练习2:
class Fu {
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() {
super();
System.out.println("构造方法Zi"); //6
}
}
class Test{
public static void main(String[] args){
Zi z = new Zi(); //请问执行结果。
}
}