1 构造方法

1.1 概念

构造方法是一种特殊的方法,它是一个与类同名的方法。

对象的创建就是通过构造方法来完成,

其功能主要是完成对象的创建或者对象的初始化。

当类实例化new一个对象时会自动调用构造方法。

构造方法和其他方法一样也可以重载(方法名相同+参数列表不同)。

1.2 形式

可以无参也可以有参在这里插入代码片

修饰符  类名(参数列表…){

       代码……

}

1.3 练习1:构造方法创建对象

创建day06工程

创建cn.tedu.constructor包

创建Test1_Constructor.java

package cn.tedu.constructor;

 

//这个类用来测试构造方法:

//总结:1、构造方式是在创建对象时会自动调用

//2、如果不想让外界随意创建对象,可以把构造方法private

public class Test1_Constructor {

    public static void main(String[] args) {

       //创建Person对象

       //1、当对象实例化时,会自动调用构造方法

       //2、无参构造会默认存在:前提是不可以提供任何含参构造,否则将被覆盖

       Person p = new Person();

//3、构造方法是一个特殊的方法,但是也可以重载,把实际参数"大黄"传递给重载的形参name

       Person p2 = new Person("大黄");

       Person p3 = new Person("大黄",3);

    }

}

//创建Person类

class Person{

    //构造方法:修饰符 类名( ){ }

public Person() {

       System.out.println("构造方法...");

    }

    //重载构造方法

    public Person(String name) {

       System.out.println("构造方法..."+name);

    }

    //重载构造方法

    public Person(String name,int age) {

       System.out.println("构造方法..."+name+age);

    }

   

}

 

 

1.4 练习2:构造方法赋值

package cn.tedu.constructor;

 

//这个类用来测试构造方法:赋值

//总结:含参创建对象时,把实参传递给形参,并给成员变量赋值

public class Test2_Constructor2 {

    public static void main(String[] args) {

       //创建Animal对象

       Animal a = new Animal();//自动调用无参构造

      

       Animal a2 = new Animal("大黄");//自动调用含参构造

       System.out.println(a2.name);//大黄

    }

}

//创建Animal类

class Animal{

   

    String name;

   

    //2、最好提供,方便外界无参创建对象

    public Animal() { }

   

    //提供含参构造

    //1、含参创建对象时,把实参"大黄"传递给形参n。

    public Animal(String n) {

       name = n;  //n给成员name赋值

    }

   

}

2 this

2.1 概念

this代表本类对象的一个引用对象。

2.2 形式

this.name=name;

2.3 练习1:当变量名相同时

package cn.tedu.thisdemo;

 

import org.junit.Test;

 

//这个类用来测试this的用法

//总结:变量名相同时,想要调用成员变量,通过this才能调用,否则用的都是局部变量

public class Test3_This {

       public static void main(String[] args) {

           Teacher t = new Teacher();

           t.show();

          

           Student s = new Student("jack");

       }

}

//创建学生类

class Student{

    String name;

   

    //提供含参构造

    public Student(String name) {//这个name是局部变量

//1、变量名相同了,想要调用成员变量,通过this才能调用,否则用的都是局部变量

this.name=name;//左面是成员变量,右面是局部变量

       System.out.println("局部变量"+name);

       System.out.println("成员变量"+this.name);//jack?null?

    }

}

 

//创建Teacher类

class Teacher{

    int sum = 20;

   

    public void show() {

       int sum = 10;

       System.out.println(sum);//10,就近原则

//this代表的是本类对象的引用,通过this可以调用本类的成员(成员变量和成员方法)

       //1、当变量名相同时,this用来区分成员变量和局部变量

       System.out.println(this.sum);//20

    }

}

2.4 练习2:构造方法间的调用

package cn.tedu.thisdemo;

 

//这个类用来测试this的用法

//总结:this可以在构造方法间互相调用

public class Test4_This2 {

       public static void main(String[] args) {

           //创建Zoo的无参对象

           Zoo z = new Zoo();//自动调用了无参构造

          

           //创建Zoo的含参对象

           Zoo z2 = new Zoo("大老虎");//自动调用了含参构造

       }

}

 

//创建Zoo类

class Zoo{

    //1、this可以在构造方法间调用

    public Zoo(){

       //在 无参构造中 调用 含参构造

       this("大海豚");

       System.out.println("无参构造");

    }

   

    public Zoo(String name){

       //在 含参构造中 调用 无参构造

// this();//调用了无参构造

       System.out.println("含参构造"+name);

    }

   

}

3 构造代码块和局部代码块

{

}

3.1 构造代码块

  1. 在类的内部,方法外部,的代码块

  2. 通常用于抽取构造方法中的共性代码

  3. 每次调用构造方法前new都会调用构造代码块

  4. 优先于构造方法加载

package cn.tedu.block;

 

//这个类用来测试构造代码块

public class Test5_Block {

    public static void main(String[] args) {

       //创建Car对象

       Car c  = new Car();

       Car c2  = new Car();

       Car c3  = new Car("神车");

    }

}

 

//创建Car类

class Car{

    String pinPai = "五菱宏光" ;

   

    //构造代码块

    //1、位置:类里方法外 2、顺序:先执行构造代码块再执行构造方法 

    //3、new几次会执行几次 4、可以用来抽取构造方法的共性

    {

       System.out.println("构造代码块"+pinPai);//抽取pinPai的共性

    }

    //提供无参构造

    public Car() {

       System.out.println("无参构造");

    }

    //提供含参构造

    public Car(String name) {

       System.out.println("含参构造");

    }

   

}

3.2 局部代码块

  1. 在方法里面的代码块

  2. 通常用于控制变量的作用范围,出了括号就失效

  3. 变量的范围越小越好,成员变量会有线程安全问题

package cn.tedu.block;

 

//这个类用来测试构造代码块

//总结:

//1、构造代码块:在创建对象时,会自动调用构造方法,但是,如果有构造代码块,先执行构造代码块

//2、构造方法:在创建对象时,执行完构造代码块,立刻执行构造方法

//3、局部代码块:当方法被调用时,才触发。方法如果不调用,局部代码块就不会执行

//顺序:构造代码块-->构造方法-->局部代码块

public class Test5_Block {

    public static void main(String[] args) {

       //创建Car对象

       Car c  = new Car();

       Car c2  = new Car();

       Car c3  = new Car("神车");

       c3.start();//局部代码块

    }

}

//创建Car类

class Car{

    String pinPai = "五菱宏光" ;

   

    //构造代码块

    //1、位置:类里方法外 2、顺序:先执行构造代码块再执行构造方法 

    //3、new几次就执行几次 4、可以用来抽取构造方法的共性

    {

       System.out.println("构造代码块"+pinPai);//抽取pinPai的共性

    }

    //提供无参构造

    public Car() {

       System.out.println("无参构造");

    }

    //提供含参构造

    public Car(String name) {

       System.out.println("含参构造");

    }

    public void start() {

       //局部代码块

       //1、位置:在方法里 //2、作用:控制变量的作用范围,只在局部代码块范围内可用

       {

           int a = 10;

           System.out.println("局部代码块"+a);

       }

      

    }

   

}

3.3 练习1:代码块加载顺序

创建类

提供构造代码块,构造方法,局部代码块

创建对象,测试执行顺序

构造代码块->构造方法->局部代码块

构造代码块:每次创建对象都会执行构造方法,在执行构造方法前会执行构造代码块

局部代码块:存在方法里,只有调用方法才执行

4 继承

4.1 概念

继承是面向对象最显著的一个特性。

继承是从已有的类中派生出新的类,新的类能吸收已有类的数据属性和行为,并能扩展新的能力。

Java继承是使用已存在的类的定义作为基类/父类/超类,新类的定义可以增加新的数据或新的功能,也可以用父类的功能。

但不能选择性地继承父类(超类,基类)。

这种技术使得复用以前的代码非常容易,能够大大缩短开发周期,降低开发费用。

4.2 特点

  1. 使用extends关键字

  2. 相当于子类把父类的功能复制了一份

  3. java只支持单继承

  4. 继承可以传递(爷爷,儿子,孙子的关系)

  5. 不能继承父类的私有成员

  6. 继承多用于功能的修改,子类可以拥有父类的功能的同时,进行功能拓展

  7. 像是is a 的关系

4.3 入门案例

package cn.tedu.extendsdemo;

 

//这个类用来测试继承的入门案例

public class Test6_Extends {

       public static void main(String[] args) {

              //创建子类对象测试

              Erzi erzi = new Erzi();

             

              //子类使用父类的功能

              erzi.eat();

              System.out.println(erzi.country);

             

              //子类使用爷爷的功能

              //4、继承是可以传递的,爷爷--爸爸--儿子

              System.out.println(erzi.money);

             

              //5、父类的私有成员,子类继承不过来

// System.out.println(erzi.sifangqian);

       }

}

//创建爷爷类

class Yeye{

       String money;

}

//创建父类

class Baba extends Yeye{

       String country;

       private String sifangqian;

      

       public void eat() {

              System.out.println("爸爸在吃猪肉");

       }

}

//创建子类

//1、通过extends关键字表示继承关系

//3、java只支持单继承

class Erzi extends Baba{ //6、强耦合性is a的关系

       //2、子类复制了父类的所有功能

}

5 super关键字

  1. 通过super关键字可以使用父类的内容。

  2. super代表父类的一个引用对象。

  3. 如果在构造方法中使用,必须是第一条语句。

6 方法重写Override

  1. 继承后,子类就拥有了父类的功能。

  2. 那么在子类中,可以添加子类特有的功能也可以修改父类的原有功能。

  3. 子类中方法的声明与父类完全一样时,会发生重写/覆盖/复写操作。

  4. 方法的声明:包括方法的返回值,方法名和参数列表,完全一致。。

注意:
  1. 父类中的私有方法不能被重写。

  2. 子类重写父类方法时,修饰符要 >= 父类修饰符的权限。

  3. 父类中的构造方法不能被子类继承。

7 继承中的用法

7.1 成员变量的使用

7.2 成员方法的使用

继承方法,特有方法,重写方法

7.3 构造方法的使用

1、 子类创建对象时,默认会去访问父类的无参构造方法

2、 在子类构造方法的第一行,都有一条默认的语句:super();this()

3、 父类没有无参构造时,可以用super调用父类的其他构造

8 拓展

8.1 this和super的区别

1、 this代表本类对象的引用,super代表父类对象的引用。

2、 this用于区分局部变量和成员变量

3、 super用于区分本类变量和父类变量

4、 this.成员变量 this.成员方法() this(【参数】)代表调用本类内容

5、 super.成员变量 super.成员方法() super(【参数】),代表调用父类内容

6、 this和super不可以同时出现在同一个构造方法里,他们两个只要出现都得放在第一行,同时出现的话,到底第一行放谁呢。。

8.2 创建对象的流程

Person p = new Person();//短短这行代码发生了很多事情
  1.  把Person.class文件加载进内存
    
  2.  在栈内存中,开辟空间,存放变量p
    
  3.  在堆内存中,开辟空间,存放Person对象
    
  4.  对成员变量进行默认的初始化
    
  5.  对成员变量进行显示初始化
    
  6.  执行构造方法(如果有构造代码块,就先执行构造代码块再执行构造方法)
    
  7.  堆内存完成
    
  8.  把堆内存的地址值赋值给变量p ,p就是一个引用变量,引用了Person对象的地址值
    

8.3 匿名对象

没有名字的对象,是对象的简化表示形式。

使用场景:

1、 当被调用的对象只调用一次时(多次会创建多个对象浪费内存)

Demo d = new Demo();

d.sleep();

d.game();

//这个d就是对象的名字。

也可以写成:

new Demo().show();//创建了一个对象调方法

new Demo().game();//又创建了一个对象调方法