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 构造代码块
-
在类的内部,方法外部,的代码块
-
通常用于抽取构造方法中的共性代码
-
每次调用构造方法前new都会调用构造代码块
-
优先于构造方法加载
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 局部代码块
-
在方法里面的代码块
-
通常用于控制变量的作用范围,出了括号就失效
-
变量的范围越小越好,成员变量会有线程安全问题
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 特点
-
使用extends关键字
-
相当于子类把父类的功能复制了一份
-
java只支持单继承
-
继承可以传递(爷爷,儿子,孙子的关系)
-
不能继承父类的私有成员
-
继承多用于功能的修改,子类可以拥有父类的功能的同时,进行功能拓展
-
像是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关键字
-
通过super关键字可以使用父类的内容。
-
super代表父类的一个引用对象。
-
如果在构造方法中使用,必须是第一条语句。
6 方法重写Override
-
继承后,子类就拥有了父类的功能。
-
那么在子类中,可以添加子类特有的功能也可以修改父类的原有功能。
-
子类中方法的声明与父类完全一样时,会发生重写/覆盖/复写操作。
-
方法的声明:包括方法的返回值,方法名和参数列表,完全一致。。
注意:
-
父类中的私有方法不能被重写。
-
子类重写父类方法时,修饰符要 >= 父类修饰符的权限。
-
父类中的构造方法不能被子类继承。
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();//短短这行代码发生了很多事情
-
把Person.class文件加载进内存
-
在栈内存中,开辟空间,存放变量p
-
在堆内存中,开辟空间,存放Person对象
-
对成员变量进行默认的初始化
-
对成员变量进行显示初始化
-
执行构造方法(如果有构造代码块,就先执行构造代码块再执行构造方法)
-
堆内存完成
-
把堆内存的地址值赋值给变量p ,p就是一个引用变量,引用了Person对象的地址值
8.3 匿名对象
没有名字的对象,是对象的简化表示形式。
使用场景:
1、 当被调用的对象只调用一次时(多次会创建多个对象浪费内存)
Demo d = new Demo();
d.sleep();
d.game();
//这个d就是对象的名字。
也可以写成:
new Demo().show();//创建了一个对象调方法
new Demo().game();//又创建了一个对象调方法