目录
Day06---面向对象... 1
1 构造方法... 1
1.1 概念... 1
1.2 形式... 1
1.3 练习1:构造方法创建对象... 1
1.4 练习2:构造方法赋值... 1
2 this. 1
2.1 概念... 1
2.2 形式... 1
2.3 练习1:当变量名相同时... 1
2.4 练习2:构造方法间的调用... 1
3 构造代码块和局部代码块... 1
3.1 构造代码块... 1
3.2 局部代码块... 1
3.3 练习1:代码块加载顺序... 1
4 继承... 1
4.1 概念... 1
4.2 特点... 1
4.3 入门案例... 1
5 super关键字... 1
6 方法重写Override. 1
7 继承中的用法... 1
7.1 成员变量的使用... 1
7.2 成员方法的使用... 1
7.3 [预习]构造方法的使用... 1
8 拓展... 1
8.1 this和super的区别... 1
8.2 Overload/重载和Override/重写的区别... 1
8.3 创建对象的流程... 1
8.4 匿名对象... 1
Day06---面向对象
1 构造方法
1.1 概念
构造方法是一种特殊的方法,它是一个与类同名的方法。
对象的创建就是通过构造方法来完成.
其功能主要是完成对象的创建或者对象的初始化。
当类实例化new一个对象时会自动调用构造方法。
构造方法和其他方法一样也可以重载(方法名相同+参数列表不同)。
1.2 形式
可以无参也可以有参
修饰符 类名([参数列表]){
代码……
}
1.3 练习1:构造方法创建对象
创建day06工程
创建cn.tedu.constructor包
创建Test1_Constructor.java
package cn.tedu.constructor;
//测试构造方法创建对象
//一个.java文件中个,可以有多个类
//但是,只能有一个类被public修饰,而且这个类名就是.java的文件名
//总结:
//1、构造方法什么时候被触发?在创建对象时触发
//2、创建对象时会触发哪个构造方法怎么决定?要看你创建对象时的参数列表,自动匹配要调用的构造方法
public class Test1_Constructor {
public static void main(String[] args) {
//创建Person对象
//1、new Person()创建对象时,会自动调用 无参 构造方法
Person p = new Person();
//自动调用含参 的构造
Person p2 = new Person("jack");
//自动调用含参 的构造
Person p3 = new Person("jack",10);
}
}
//创建Person类
class Person{
//构造方法:修饰符 类名(){}
//2、无参构造,默认就会存在,前提是没有含参构造
public Person() {
System.out.println("构造方法");
}
//3、重载的构造方法:方法名可以相同+参数列表必须不同
public Person(String n) {
System.out.println("构造方法"+n);
}
public Person(String n,int age) {
System.out.println("构造方法"+n+age);
}
}
1.4 练习2:构造方法赋值
package cn.tedu.constructor;
//测试构造方法赋值
public class Test2_Constructor2 {
public static void main(String[] args) {
//TODO 创建Teacher对象测试
Teacher t = new Teacher();
//1、触发重载构造方法
Teacher t2 = new Teacher("王一博",18,100000);
//TODO 测试属性都有值了吗?有了,因为创建对象时已经给成员变量赋值了
// System.out.println(t2.name);
// System.out.println(t2.age);
// System.out.println(t2.salary);
// Teacher [name=王一博, age=18, salary=100000.0]
System.out.println(t2);//因为Teacher类中提供了toString()
}
}
//创建Teacher类
class Teacher{
String name;
int age;
double salary;
//无参构造,默认就存在,提供构造方法
public Teacher() {
System.out.println("构造方法");
}
//2、构造方法给成员变量赋值:在创建对象时需要把实参传递给形参n a s
//形参n a s拿到值后给成员变量一一赋值
public Teacher(String n,int a,double s) {
name = n;
age = a;
salary = s;
}
//toString() --查看属性的值
@Override
public String toString() {
return "Teacher [name=" + name + ", age=" + age + ", salary=" + salary + "]";
}
}
2 this
2.1 概念
this代表本类对象的一个引用对象。
2.2 形式
this.name=name;
2.3 练习1:当变量名相同时
package cn.tedu.thisdemo;
//this的用法
//总结:1、前提是,成员变量和局部变量同名时,this用来区分成员变量和局部变量,this能调用出来的一定是成员变量
public class Test3_This {
public static void main(String[] args) {
//TODO 创建Student对象测试
Student s = new Student();
Student s2 = new Student("rose");
System.out.println(s2.name);//rose
}
}
//创建Student类
class Student{
String name;
//TODO 提供构造方法
public Student() {
System.out.println("构造方法");
}
public Student(String name) {
//1、变量使用有就近原则
// name = name;//等号的左右两边使用的都是局部变量name,并没有给成员变量赋值
//2、这时我们想要把等号左边的name表示成员变量
//this代表的是本类,this能调用的是本类的成员,成员变量和成员方法
//this à Student this = new Student();
this.name=name;
}
}
2.4 练习2:构造方法间的调用
package cn.tedu.thisdemo;
//测试this调用构造方法
//总结:1、this可以在 构造方法 间互相调用 2、必须是第一条语句
public class Test4_This2 {
public static void main(String[] args) {
//TODO 创建对象测试
Zoo z = new Zoo();
Zoo z2 = new Zoo("猴子");
}
}
//创建Zoo类
class Zoo{
//TODO 构造方法
public Zoo() {
//1、this在无参构造中 调用 含参构造
//3、this关键字在构造方法中使用时,必须是第一条语句
// this("大老虎");
System.out.println("无参构造");
}
public Zoo(String n) {
//2、this在含参构造中 调用 无参构造
//3、this关键字在构造方法中使用时,必须是第一条语句
this();
System.out.println("含参构造"+n);
}
}
3 构造代码块和局部代码块
{
…
}
3.1 构造代码块
1、 在类的内部,方法外部,的代码块。
2、 通常用于抽取构造方法中的共性代码。
3、 每次调用构造方法前都会调用构造代码块new new new
4、 优先于构造方法加载
5、 测试
package cn.tedu.block;
//测试代码块
public class Test5_Block {
public static void main(String[] args) {
//TODO 创建对象测试
//1、如果有构造代码块,创建对象时发生两件事:先执行构造代码块再执行构造方法
Block b = new Block();
Block b2 = new Block("jack");
}
}
//创建Block类
class Block{
//2、构造代码块:位置是在类里方法外
String country ;
{
//3、构造代码块中可以提供所有构造方法的共性功能
country="中国人";
System.out.println("构造代码块");
}
//TODO 构造方法
public Block() {
System.out.println("无参构造"+);
}
public Block(String n) {
System.out.println("含参构造"+country);
}
}
3.2 局部代码块
1、 在方法里面的代码块
2、 通常用于控制变量的作用范围,出了括号就失效
3、 变量的范围越小越好,成员变量会有线程安全问题
4、 测试
package cn.tedu.block;
//测试代码块
public class Test5_Block {
public static void main(String[] args) {
//TODO 创建对象测试
//1、如果有构造代码块,创建对象时发生两件事:先执行构造代码块再执行构造方法
Block b = new Block();b.eat();//方法调用时,才触发局部代码块
Block b2 = new Block("jack");
}
}
//创建Block类
class Block{
//2、构造代码块:位置是在类里方法外
String country ;
{
//3、构造代码块中可以提供所有构造方法的共性功能
country="中国人";
System.out.println("构造代码块");
}
//TODO 构造方法
public Block() {
System.out.println("无参构造"+country);
}
public Block(String n) {
System.out.println("含参构造"+country);
}
//TODO 提供普通方法
public void eat() {
//局部代码块:位置是在方法里 + 主要用来控制变量的作用范围
{
int i = 10;
System.out.println("局部代码块"+i);
}
}
}
3.3 练习1:代码块加载顺序
1、创建类
2、提供构造代码块,构造方法,局部代码块
3、创建对象,测试执行顺序
总结:构造代码块->构造方法->局部代码块
构造代码块:每次创建对象都会执行构造方法,在执行构造方法前会执行构造代码块
局部代码块:存在方法里,只有调用方法才执行
4 继承 -- OCP原则
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) {
//TODO 创建子类Dog对象测试
Dog d = new Dog();
d.eat();//2.1、可以使用父类的所有功能
//TODO 创建DaHuang类对象测试
DaHuang huang = new DaHuang();
huang.eat();//4.1、继承可以传递
//5、父类的私有成员,子类无法继承
// System.out.println(huang.sum);
}
}
//创建父类
class Animal{
public void eat() {
System.out.println("吃啥都行");
}
}
//创建子类
//1、extends关键字用来表示继承关系
//3、java中只支持单继承 , 是 is a 的关系 , 子类要强制继承父类,才能用父类的功能
class Dog extends Animal{ //耦合性强--两者的关系就是强制依赖
//2、子类继承父类就能无偿使用,因为相当于把父类的功能复制了一份
private int sum = 10;
}
//创建孙子类
class DaHuang extends Dog{
//4、继承可以传递,Animal的功能也能用
}
5 super关键字
1、 通过super关键字可以使用父类的内容。
2、 super代表父类的一个引用对象。
3、 如果在构造方法中使用,必须是第一条语句。
6 !!方法重写Override
1、 继承后,子类就拥有了父类的功能。
2、 在子类中,可以添加子类特有的功能也可以修改父类的原有功能。
3、 子类中方法的声明与父类完全一样时,会发生覆盖/复写/重写操作。
4、 方法的声明:包括方法的返回值,方法名和参数列表,完全一致。。
注意:
1、父类中的私有方法不能被重写。
2、子类重写父类方法时,修饰符要>=父类修饰符。
3、父类中的构造方法不能被子类继承。
7 继承中的用法
7.1 成员变量的使用
package cn.tedu.extendsdemo;
//测试继承的使用
//总结:1、继承中,如果要使用父类的成员变量 -- 通过super.调用父类成员变量
public class Test7_UseExtends {
public static void main(String[] args) {
//TODO 创建父类对象测试
Baba b = new Baba();
b.eat();
}
}
//创建爷爷类
class Yeye{
int count = 30;
int sum = 50;
}
//创建父类
class Baba extends Yeye{
int sum = 20;
public void eat() {
int sum = 10;
System.out.println(sum);//10
System.out.println(this.sum);//20,this调用成员变量
System.out.println(count);
System.out.println(super.sum);//50,通过super关键字使用父类的资源
}
}
7.2 成员方法的使用
继承方法,特有方法,重写方法
package cn.tedu.extendsdemo;
//继承中成员方法的使用
//总结:1、如果只是继承,子类用的就是父类的功能
//2、如果继承后,发生了重写,子类用的是重写后的功能
//3、重写的意义:是在不修改源码的前提下,进行功能的拓展。就算是发生了重写后,父类本身功能并没改。
public class Test8_UseExtends2 {
public static void main(String[] args) {
//TODO 创建父类对象测试
Father f = new Father();
f.eat();//爸爸在吃肉
f.study();//爸爸在赚钱
//TODO 创建子类对象测试
Son s = new Son();
//4、如果没有发生重写现象,使用的就是继承过来的父类的功能。
//但是,如果发生了重写现象,从此使用的都是重写后的效果。
s.eat();//5、从爸爸在吃肉变成了儿子在喝汤
s.study();//爸爸在赚钱? -- 儿子在学Java
s.play();//正在吃鸡
}
}
//创建父类
class Father{
public void eat() {
System.out.println("爸爸在吃肉");
}
public void study() {
System.out.println("爸爸在赚钱");
}
}
//创建子类
class Son extends Father{
//子类特有功能
public void play() {
System.out.println("正在吃鸡");
}
//1、如果子类想要修改父类的功能 -- 方法的重写Override
//2、重写:子类的方法声明和父类一模一样(返回值 方法名 参数列表)
//3、重写中,父类原本的功能并没有影响,改的是子类自己的功能--super.eat()
public void eat() {
System.out.println("儿子在喝汤");
}
//TODO 重写父类的study()
public void study() {
System.out.println("儿子在学Java");
}
}
7.3 [预习]构造方法的使用
1、 子类创建对象时,默认会去访问父类的无参构造方法
2、 在子类构造方法的第一行,都有一条默认的语句:super();this()
3、 父类没有无参构造时,可以用super调用父类的其他构造
package cn.tedu.extendsdemo;
//继承中构造方法的使用
public class Test9_UseExtends3 {
public static void main(String[] args) {
//TODO 创建子类对象测试
Zi z= new Zi();
}
}
//创建父类
class Fu{
/*当父类没有无参构造时
* public Fu() { System.out.println("父类构造方法"); }
*/
public Fu(String n) {
System.out.println("父类构造"+n);
}
}
//创建子类
class Zi extends Fu{
public Zi() {
//1、第一行隐藏着super(),会自动调用了父类的无参构造
// super();
//2、当父类没有无参构造时,子类通过super调用父类的含参构造
super("rose");
System.out.println("子类构造方法");
}
}
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 Overload/重载和Override/重写的区别
8.3 创建对象的流程
Person p = new Person();//短短这行代码发生了很多事情
- 把Person.class文件加载进内存
- 在栈内存中,开辟空间,存放变量p
- 在堆内存中,开辟空间,存放Person对象
- 对成员变量进行默认的初始化
- 对成员变量进行显示初始化
- 执行构造方法(如果有构造代码块,就先执行构造代码块再执行构造方法)
- 堆内存完成
- 把堆内存的地址值赋值给变量p ,p就是一个引用变量,引用了Person对象的地址值
8.4 匿名对象
没有名字的对象,是对象的简化表示形式。
使用场景:
1、 当被调用的对象只调用一次时(多次会创建多个对象浪费内存)
Demo d = new Demo();
d.sleep();
d.game();
//这个d就是对象的名字。
也可以写成:
new Demo().show();//创建了一个对象调方法
new Demo().game();//又创建了一个对象调方法