面向对象(2)

六、构造方法

构造方法是一种特殊的方法,也称之为构造函数 或构造器constructor

作用:用于创建和初始化对象

特点:

  • 方法名必须和类名相同
  • 没有返回值,也不能写作void
  • 当创建类的对象时,会自动调用构造方法
  • 一个类中可以有多个构造方法(构造方法重载)
  • 如果没有自定义构造方法,则类中默认会有一个无参的构造方法
  • 如果自定义了构造方法,则默认的无参构造方法就没有了,可以自己写无参的构造方法(建议)
  • 可以使用this(参数)调用当前类中的其他构造方法,但只能出现在构造方法的第一行
public static void main(String[] args) {
		Dog dog = new Dog();
    
		Dog dog2 = new Dog("豆豆", 3, "金毛");
		dog2.run();
		dog2.show();
	}
}
class Dog {
	// 成员属性
	String name;
	int age;
	String breed;

	// 成员方法
	public void run() {
		System.out.println("狗狗正在奔跑....");
	}

	public void show() {
		System.out.println("姓名:" + name + ",狗龄:" + age + ",品种:" + breed);
	}

	// 构造方法
	public Dog() {
		System.out.println("这是一个无参的构造方法");
	}

	// 带参构造方法
	public Dog(String name, int age) {
		this.name = name;
		this.age = age;
		System.out.println("这是一个带两个参数的构造方法");
	}
	public Dog(String name, int age, String breed) {
		this(name, age);// 调用构造方法,必须位于第一行
		this.breed = breed;
		System.out.println("这是一个带三个参数的构造方法");
	}

七、包package

包的作用:

  • 区分同名的类
  • 类比较多时便于管理
  • 便于访问控制

声明包:

  • 用来指定当前类所在包
  • 使用package,写法: package 包名
  • 必须位于第一行(注释除外)

命名规范:

  • 采用组织的反向域名
  • 使用小写字母,不能以点号开头结尾
  • com.baidu.fany

导入包:

  • 当需要使用其他包中的类时必须导入
  • 使用import ,写法:import 包名.类名;import 包名.*;
  • 必须位于包声明的下面

常用的包:

  • java.lang包含java的核心类,如System、String、Math等,该包默认会被自动导入,当使用其中的类,无需import导入
  • java.util 包含实用的工具类,如Scanner、Arrays等
  • java.io 包含输入/输出操作的类
  • java.sql 包含数据库操作的类
  • java.net 包含网络操作的类
  • java.awt 包含图形窗口操作的类

注意:定义类时务必指定包名,严禁将类直接放在src下(default package 默认包,会导致类无法被引用)

八、访问修饰符

用来控制访问范围,可以修饰属性、方法、类等

修饰符同一个类同一个包内的类不同包的子类不同包并且不是子类
public公开的
protected 受保护的
默认
private私有的

总结:

  • public:在哪都能访问
  • protected:只有不同包并且非子类不能访问,其他都能访问
  • 默认:只有本包中可以访问
  • private:只有本类中可以访问

范围从大到小的顺序:public>protected>默认>private

九、对象的初始化顺序

1.类加载

概念:将class文件读取加载到JVM内存中的过程,称为类加载

类加载的时机:

  1. 创建类的对象
  2. 调用类的静态属性或静态方法
  3. 执行main方法时,main方法所在的类会被加载
  4. 通过反射调用类Class.forName("包名.类名")
2.类的成员

类中的成员:

  • 属性(实例属性、静态属性)
  • 方法(实例方法、静态方法)
  • 构造方法
  • 代码块
  • 静态代码块:使用static修饰的代码块

注:static关键字可以修饰变量、方法、代码块、匿名类等

3.初始化顺序

步骤:

  1. 对象所在的类被加载

    执行静态属性和静态代码块(根据定义的顺序,从上往下执行)

    特性:

    • 静态变量在类加载时初始化,且在内存中值分配一块空间

    • 静态代码块在类加载时执行,且只执行一次(类只会被加载一次),主要用于初始化静态属性

    • 静态代码块中不能初始化实例变量,只能初始化静态变量

  2. 对象被创建

    执行实例属性和代码块(根据定义的顺序,从上往下执行)

    执行构造方法

    总结:执行先后顺序:静态代码块>代码块>构造方法

十、面向对象的三大特征

1.封装
1.1Java代码规范
  • 将类的属性封装在类中,不允许在类的外部直接访问,保护数据的安全,使内容可控
  • 只能通过被授权的方法才能对数据进行访问
  • 类的基本原则就是封装
1.2实现方式

步骤:

  1. 将属性私有化

    使用private修饰属性

  2. 提供对外访问的方法,用于赋值、取值

    使用public修饰方法

    方法命名规范:

    • 赋值方法:以set开头,后面属性名,如setXxx,称为setter方法(属性名首字母大写)

    • 取值方法:以get开头,后面属性名,如getXxx

      ​ 如果是boolean类型属性,可以是getXxx,也可以是isXxx

    如果属性只具有getter方法,则表示该属性是只读的,在外部只能读取

    如果属性只具有setter方法,则表示该属性是只写的,在外部只能修改

	public static void main(String[] args) {
		User user = new User();
	
		user.setAge(19);
		user.setName("老王");
		user.setSex("妖");
		user.setMarried(false);

		System.out.println(user.getAge());
		System.out.println(user.getName());
		System.out.println(user.getSex());
		System.out.println(user.isMarried());
		
		user.show();
	}


class User {
	private String name;
	private int age;
	private String sex;
	private boolean married;

	// 赋值
	public void setAge(int age) {
		if (age >= 1 && age <= 100) {
			this.age = age;
		} else {
			System.out.println("age无效,已设置为默认值18");
			this.age = 18;
		}
	}
	// 取值
	public int getAge() {
		return age;
	}

	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}

	public void setSex(String sex) {
		// if(sex=="男"||sex=="女")
		if (sex.equals("男") || sex.equals("女")) {
			this.sex = sex;
		} else {
			System.out.println("性别有误!已设置为女");
			this.sex = "女";
		}
	}
	public String getSex() {
		return sex;
	}
	
	public void setMarried(boolean married) {
		this.married = married;
	}
	public boolean isMarried() {
		return married;
	}

	public void show() {
		System.out.println("编号:" + id + ",姓名:" + name + ",年龄:" + age + ",性别:" + sex);
	}
}
2.继承
2.1概念

可以让一个类继承自另一个类,此时该类会继承另一个类中的属性和方法 继承而得到的类称为子类,被继承的类称为父类(超类/基类)

继承是一种is a的关系比如:cat is a animalstudent is a person

2.2实现方式

语法:

class 子类 extends 父类{
    
}

作用:

  • 代码复用:将多个子类中相同的属性和方法放到父类中
  • 功能扩展:子类可以有自己独特的属性和方法

特性:

  • java只支持单继承,不支持多继承,但支持多层继承,即继承的传递
  • java中所有的类都直接或间接继承了java.long.Object类(后面会详细讲)
2.3继承的范围

子类可以继承父类的哪些成员?

  • 父类的public、protected、默认修饰的属性和方法可以被子类继承(同包的情况下)
  • 父类 的private修饰的属性和方法不能被子类继承
  • 父类中的构造方法不能被子类继承(构造方法名必须与类名相同,而子类名称不可能与父类相同)
2.4构造方法的调用

调用过程:

  • 创建子类对象是默认会自动调用父类无参的构造方法(此时必须保证父类中有无参的构造方法)
  • 从子类开始,逐层往上调用父类的构造方法,直到Object类,然后在层层返回到子类中,执行后续代码
  • 创建子类对象时必须会调用父类的构造方法,而调用父类构造方法也就创建了父类的对象,所以当创建子类对象时,其实也创建了父类对象,只不过这个父类对象并不是独立存在的,而是和子类对象合为一个整体

在这里插入图片描述

super 关键字:

  • 表示父类对象的引用,只能在子类中使用
  • 可以使用super()调用父类的构造方法,必须位于第一行
  • 可以使用super.访问父类的属性和方法,解决父类和子类中同名的问题

this关键字:

  • 表示当前对象的引用,只能在方法中使用
  • 可以使用this()访问当前类中重载的构造方法,必须位于第一行
  • 可以使用this.访问本类中的属性和方法,解决全局变量和局部变量同名的问题

注:调用构造方法时this()和super()都只能放在第一行,所以不能同时使用

 public static void main(String[] args) {
	Pig pig=new Pig("佩奇","女",2,80);
	 pig.show();
}
/*
 * 父父类
 */
class Live{
	public Live() {
		System.out.println("父父类中无参的构造方法-------------");
	}
}
/*
 * 父类
 */
class Animal extends Live{
	String name="李四";
	String sex;

	public Animal() {
		System.out.println("父类中无参的构造方法-------");
	}

	public Animal(String name, String sex) {
		super();
		this.name = name;
		this.sex = sex;
		System.out.println("父类中带参的构造方法---------");
	}

	public void show() {
		System.out.println("父类中的show方法---------------");
	}
}
/*
 * 子类
 */
class Pig extends Animal{
	int age;
	double weight;
	
	String name="张三";
	
	public Pig(){
		System.out.println("子类中无参的构造方法-------------");
	}
	public Pig(int age,double weight) {
		super();//调用父类中无参的构造方法
		this.age=age;
		this.weight=weight;
		System.out.println("子类中带两个参数的构造方法-------");
	}
	public Pig(String name, String sex,int age,double weight) {
		super(name,sex);
		this.age=age;
		this.weight=weight;
		System.out.println("子类中带四个参数的构造方法-------");
	}
	public void show() {
		System.out.println(age);
		System.out.println(this.age);
		System.out.println(name);
	//	System.out.println(this.name);
	    System.out.println(super.name);
		
		super.show();
	}
}
2.5方法重写

子类中的方法,与父类中的方法的名称、参数列表、返回值类型一样,我们就说子类重写了父类的方法,称为方法重写override

  • 在父子类之间
  • 方法名相同
  • 参数列表也相同
  • 返回值类型相同或是子类
  • 访问修饰符不能缩小,即访问权限不能缩小
  • 子类不能抛出比父类更大的异常

作用:用来重新定义子类的行为,解决父类和子类的差异性

public static void main(String[] args) {
	Cat cat=new Cat();
	cat.name="猫咪";
	cat.cry();//调用的是子类重写后的方法
}
/*
 * 父类
 */
class Pet{
	String name;
	String sex;
	int health;
	public void cry() {
		System.out.println("俺是宠物,俺能叫----------");
	}
    public Pet show() {
		System.out.println("我是一只宠物");
		return new Pet();
	}
}
class Cat extends Pet {

	@Override //该注解表示当前方法是一个重写方法,可有可无
	public void cry() {
		System.out.println("俺是猫,喵喵喵");
	}

	@Override
	public int sum(int num1, int num2) {
		return super.sum(num1, num2);
	}
	
	@Override
	public Cat show() {
		System.out.println("我是一只猫");
		return new Cat();
	}
}

面试:方法重载和方法重写的区别?

3.多态
3.1概念

多态是具有表现多种形态的能力的特征,即一种事物,具有多种形态

回顾?基本数据类型之间的转换

  • 自动类型转换
  • 强制类型转换

引用类型之间的转换

3.2引用类型之间的转换

两种:

  • 自动类型转换

    将子类对象转换为父类,如student——>person

    将父类的引用指向子类的对象,称为向上转型,会自动进行类型的转换

    特性:

    通过父类引用变量调用的方法是子类重写后的方法,不是父类的方法

    通过父类引用变量是无法访问子类特有的属性和方法

  • 强制类转换

    将一个指向子类对象的父类引用赋给一个子类的引用,称为向下引用,必须进行强制类型转换

    语法:(子类类型)指向子类对象的父类引用

    特性:

    向下转型后,才可以访问子类特有的属性和方法

    必须转化为父类指向的真实的子类类型,否则会出现类型转换异常ClassCastException

    向下转型是不安全的,可以再转换时使用instanceof操作符判断对象的类型,避免类型转换异常

    	public static void main(String[] args) {
    		/*
    		 * 自动类型转换
    		 */
    		Person person = new Teacher();// 向上转型
    		person.name = "tom";
    		person.show();// 调用子类重写后的方法
    		/*
    		 * 强制类型转换 //
    		 */
    //	Teacher t=(Teacher)person;//向下转型
    //	t.school="九江学院";
    //	t.teach();
    		if (person instanceof Doctor) {// 判断一个对象是否属于某个类或实现了某个接口,结果是true或false
    			Doctor d = (Doctor) person;
    			d.hospital = "九江学院附属医学院";
    			d.operate();
    		}
    	}
    class Person {
    	String name;
    	public void show() {
    		System.out.println("我是一个人");
    	}
    }
    
    class Teacher extends Person {
    	String school;// 所在学校
    	// 重写父类的方法
    	public void show() {
    		System.out.println("我叫" + name + ",我是一个老师");
    	}
    	// 子类特有的方法
    	public void teach() {
    		System.out.println("我正在" + school + "进行教学------");
    	}
    }
    
    class Doctor extends Person {
    	String hospital;// 所在医院
    	// 重写父类的方法
    	public void show() {
    		System.out.println("我叫" + name + ",我是一个医生");
    	}
    	// 子类特有的方法
    	public void operate() {
    		System.out.println("我正在" + hospital + "做手术");
    	}
    }
    
3.3多态的实现

将父类作为方法形参,将子类的对象作为方法实参,从而实现多态

案例:主人与宠物、玩耍、喂养

  • 主人类Master
  • 宠物Pet——>Dog、Cat…
  • 食物Food——>Bone、Fish…
3.4总结

实现多态的条件:

  • 继承的存在(继承是多态的基础,没有继承就没有多态)
  • 子类要重写父类的方法(多态下调用的是子类重写后的方法)
  • 父类的引用变量指向子类对象(向上转型)

多态的有点:

  • 减少代码量

  • 提高可扩展性和可维护性

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值