06 Java语言核心知识 -11

本文深入探讨面向对象编程(OOP)的核心概念,包括封装、继承和多态性,讲解了如何通过封装保护类的属性和方法,实现信息隐藏,以及构造方法的作用和使用。此外,还介绍了设计模式、单例模式、方法重载和包的作用。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

面向对象


封装概念

OOP的三大特性:封装(encapsulation)、继承(inheritance)、多态(polymorphism)。

  • 将东西装在一起,然后以新的完整形式呈现出来。
    • 将方法和字段一起包装到一个单元中,单元以类的形式实现
  • 信息隐藏,隐藏对象的实现细节,不让外部直接访问到
  • 将数据和方法包装进类中,加上具体实现的隐藏(访问修饰符),共同被称作封装,其结果是一个同时带有特征和行为的数据类型

定义类,定义其属性、方法的过程称为封装类。

  • 信息隐藏是OOP最重要的功能之一,也是访问修饰符的原因
  • 信息隐藏的原因包括:
    • 对模块的任何实现细节所作的更改不会影响使用该模块的代码
    • 防止用户意外修改数据
    • 使模块易于使用和维护

访问修饰符:
在这里插入图片描述

  • 属性封装的实现:
    • 修改属性的可见性来限制对属性的访问
    • 为每个属性创建一对赋值(setter)方法和取值(getter)方法,用于公开这些属性的访问接口
    • 在setter和getter方法中,根据需要加入对属性操作的限制
	public class Teacher{
		private String name;		//教员姓名
		private int age;			//年龄
		
		public int getAge(){
			return age;
		}

		public void setAge(int myAge){
			if(myAge < 22){
				System.out.println("错误!最小年龄应为22岁!");
				age = 22;		//如果不符合年龄要求,则赋予默认值
			} else {
				age = MyAge;
			}
		}
	}

除非必须公开底层实现细节,否则应该将所有属性指定为private加以封装
使用属性封装,通过增加数据访问限制,增强了类的可维护性。

  • 封装方法的目的:
    • 隐藏方法实现细节(方法体),向外部提供公开接口(方法头),以供安全调用
    • 简化调用,方便修改维护
    • 根据需要,可以私有化方法以供内部使用——帮助方法helper
public class Teacher{
	private int year;		//出生年份
	//判断出生年份是否是闰年
	private boolean isLeapYear(){
		if(( year%4 == 0 && year %100 != 0 )|| year%400 == 0) {
			return true;
		} else {
			return false;
		}
	}
}

使用方法封装,隐藏了细节,实现了简化调用,有利于修改维护。

public class TeacherDemo{
	public static void main(String[] args){
		Teacher t = new Teacher();
		t.setName = "张三";
		System.out.println(t.getName());
		t.setAge(10);
		System.out.println(t.getAge());
	}
}

class Teacher{
	private String name;
	private int age;
	public void setName(Strinig tname){
		name = tname;
	}
	public String getName(){
		return name;
	}
	public void setAge(int tage){
		age = tage;
	}
	public String getAge(){
		return age;
	}
	public void setAge(int age){
		if(tage<25){
			System.out.println("年龄太小了");
			age = 25;
		} else {
			age = tage;
		}
	}
}

UML类图

Unified modeling Language 图形化语言
建模工具
在这里插入图片描述


构造方法

类的构造方法的概念和作用

  • 构造方法负责对象初始化工作,为对象的属性赋合适的初始值。
  • 创建对象时,其类的构造方法确保在用户操作对象之前,系统保证初始化的进行

构造方法的语法规则

  • 构造方法与类名相同
  • 没有返回值类型
  • 方法实现主要为字段赋初值

构造方法的调用
构造方法的调用很特别:new操作符(返回新建实例的引用)

强调:Java系统保证每个类都有构造方法。

public class ConstructorDemo{
	public static void main(String[] args){
		Person p = new Person();
		Person p = new Person("王五",25,"上海");
		p.setName("张三");
		p.setAge(10);
		Person p1 = new Person("张三",23,"上海");
		//1.在堆中开辟空间,给属性分配默认的初始值
		//2.假设属性一开始就赋值了,就进行赋值工作
		//3.调用构造方法,来对属性进行初始化
		System.out.println(p.toString());
		//名字:张三,今年:10岁,家住null
	}
}

//当一个类没有显式声明一个构造方法的时候,系统会有一个默认的无参构造方法
class Person{
	private String name = "李四";
	private int age = 0;
	private String city = null;
	
	//无参的构造方法
	public Person(){
		
	}
	
	//带参数的构造方法
	public Person(String tname,int tage,String tcity){
		name = tname;
		age = tage;
		city = tcity;
	}

	public void setCity(String tcity){
		city = tcity;
	}

	public String getCity(){
		return city;
	}

	public void setName(String tname){
		name = tname;
	}

	public int getAge(){
		return age;
	}

	public void setAge(int tage){
		age = tage;
	}

	public String toString(){
		return "名字:" + name + ",今年:" + age + "岁,家住" + city;
	}
}

this关键字

this关键字的特点

  • 在类的方法中使用的this关键字代表的是调用此方法的对象的引用。
    p.a() //p代表指向对象的引用变量 this和当前方法的调用是同一个人
  • this可以看作是一个变量,它的值是当前对象的引用。
  • 使用this可以处理方法中的成员变量和形参同名的问题。
  • 当在方法内需要用到调用该方法的对象时,就可以用this。
  • 在类的构造方法中可以调用this(【参数列表】)来调用该类的指定构造方法。
public class IotekTeacher{
	private String name;
	private int age;
	public IotekTeacher(String name,int age){
		this.name = name;
		this.age = age;
	}
}		//this指向当前对象所指的引用空间
public class ConstructorDemo{
	public static void main(String[] args){
		Person p = new Person();
		Person p = new Person("王五",25,"上海");
		p.setName("张三");
		p.setAge(10);
		Person p1 = new Person("张三",23,"上海");
		//1.在堆中开辟空间,给属性分配默认的初始值
		//2.假设属性一开始就赋值了,就进行赋值工作
		//3.调用构造方法,来对属性进行初始化
		System.out.println(p.toString());
		//名字:张三,今年:10岁,家住null
	}
}

//当一个类没有显式声明一个构造方法的时候,系统会有一个默认的无参构造方法
class Person{
	private String name = "李四";
	private int age = 0;
	private String city = null;
	
	//无参的构造方法
	public Person(){
		
	}
	
	//带参数的构造方法
	public Person(String name,int age,String city){
		this();		//调用构造方法,必须放在构造方法中的首条语句
		this.name = name;
		this.age = age;
		this.city = city;
	}

	public void setCity(String city){
		this.city = city;
	}

	public String getCity(){
		return city;
	}

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

	public int getAge(){
		return age;
	}

	public void setAge(int age){
		this.age = age;
	}

	public String toString(){
		return "名字:" + this.name + ",今年:" + this.age + "岁,家住" + this.city;
	}
}

static关键字

  • static关键字的特点

    • 用来修饰类的成员(属性、方法)——修饰成员变量的称之为类变量(静态变量),修饰成员方法的称之为类方法(静态方法)。
    • 当类被加载的时候就会被加载,优先于对象的存在。
    • 用来修饰语句块——称之为静态代码块。先于构造方法之前执行,只会执行一次,用来对静态成员做初始化。
    • 静态修饰的成员被所有对象共享。
    • 调用的时候可以直接通过类名、成员来进行访问。
  • static关键字注意事项

    • 静态方法中只能访问外部的静态成员
    • 静态方法中不能出现this关键字。(this表示当前对象,但是static静态属性、静态方法是先于对象产生的)
package Study1;

public class Test {

	public static void main(String[] args) {
		// TODO Auto-generated method stub

		//Account.number1++;// 为什么这里非要写个++,才不报错?
		//System.out.println(Account.number1);
		// System.out.println(Account.number2);
		// 报错:Cannot make a static reference to the non-static field Account.number2
		
		Account acc1 = new Account();
		Account acc2 = new Account();
	}

}

class Account {
	public static int number1 = 1;
	public int number2 = 2;
	
	public Account() {
		System.out.println("2 构造方法");
	}
	
	//static 语句块
	//在类被加载的时候就会执行,只会执行一次,用来对静态的变量赋值
	//优先于构造方法的执行
	static {
		number1=100;//静态方法中只能访问静态方法不能访问非静态方法
		System.out.println("1 static静态方法");
	}

	public static void showNumber1() {
		// 静态方法中不能访问非静态的变量
		// 静态方法中不能使用this.
		System.out.println(number1);
		//System.out.println(this.number2);
		// 报错:Cannot make a static reference to
		// the non-static field Account.number2
	}

	public void showNumber2() {
		//非静态的方法可以访问
		//静态的内容和非静态的属性和方法
		System.out.println(number1);
		System.out.println(number2);
	}
}

//总结:
静态方法中只能访问静态方法不能访问非静态方法;
非静态方法可以访问非静态方法和静态方法.

静态的方法是先于类的产生,为堆内存中一个共享的区域,无法从静态方法中引用非静态的方法

  • 设计模式(Design pattern)是一套被反复使用、多数人知晓的、经过分类编目的、代码设计经验的总结。使用设计模式是为了可重用代码、让代码更容易被他人理解、保证代码可靠性。
  • 1994年,由Erich Gamma, Richard Helm, Ralph Johnson和John Vlissides编写的经典书籍《Design Patterns: Elements of Reusable Object-Oriented Software》面世。在此书中,它们总结了多年来软件开发人员的实践经验和研究成果,收编了23个最常用的设计模式。时至今日,书中所列的23个模式仍然是最基本、最经典的设计模式,而这四个人被称为 “ Gang of Four (四人帮) ” ,简称 “ GoF ” 。
  • 设计模式描述了在一个特定上下文里,如何定制这些互相通信的对象和类来解决一个常见设计问题。GoF给出的定义更加侧重于OOP。

单例模式

定义:单例模式只有一个实例,单例模式确保某一个类只有一个实例,而且自行实例化并向整个系统提供这个实例,这个类称为单例类。

要点

  • 某个类只能有一个实例;
  • 他必须自行创建这个实例;
  • 他必须自行像整个系统提供这个实例。
public class SingleTonDemo {
	public static void main(String[] args) {
		// SingleTon ton1 = new SingleTon();
		// SingleTon ton2 = new SingleTon();
		SingleTon.getInstance();
	}
}

class SingleTon {

	//private static SingleTon singleTon = new SingleTon();
	//饿汉式

	private static SingleTon singleTon = null;
	private SingleTon() {
		System.out.println("SingleTon");
	}

	public static SingleTon getInstance() {
		if(singleTon == null) {
			singleTon = new SingleTon();
		}
		return singleTon;
	}//懒汉式:只有调用了getInstance()这个方法,才创建对象
}

方法重载

  • 多数程序设计语言要求为每个方法(函数)提供一个独一无二的方法名,不存在方法重载的概念。
  • 在Java中,规定方法签名(方法名+参数列表)是解析方法的规则而不是方法名,为方法重载开创了条件。
  • 方法重载使得在一个类中,方法名相同而参数列表不同的方法可同时存在,代表相似的行为或功能。

重载overload概念:同一类中,同名不同参的方法称为重载方法
注意:仅有返回类型不同的方法不能称为重载,即方法重载必须方法签名不同。

  • 方法重载并不陌生
  • java.io.PrintStream类的println方法能够打印数据,根据数据类型的不同,有不同的实现方式。
    在这里插入图片描述

方法重载是由方法签名决定的:
① 参数类型不同
② 参数个数不同
③ 与返回类型无关

  • 构造方法的重载是方法重载的典型示例

通过调用不同的构造方法来表达对象不同的初始化方式

public class Teacher{
	private String name;//教员姓名
	private String school = "上海徐汇中心";//所在中心

	public Teacher(String name) {
		this.name = name;//教员姓名赋值
	}
//方法重载
	public Teacher(String name, String school) {
		this.name = name;//教员姓名赋值
		this.school = school;
	}

	public String introduction(){
		return "大家好!我是"+school+"的"+name;
	}
}

包(package)

  • 打包的意义

    • 标准的Java库是由一系列包组成,包括java.lang, java.util, java.net等等。标准Java包就是层次型包结构,就如同硬盘上嵌套的子目录一样,我们可以使用嵌套层次结构来组织包。
    • Java的包是为了更好地规划代码,防止命名冲突和混乱。所以Java出现了打包机制
    • 当把类组织起来放进一个包内之时,也就给包中的成员赋予了相互访问的权限,您就 “ 拥有 ” 了该包内的程序代码。
    • 包访问权限为把类聚集在一个包中,这一做法提供了意义和理由。
  • package——声明包
    在这里插入图片描述

  • 包名由小写单词组成

  • Java程序员都可以编写属于自己的Java包,为了保障每个Java包命名的唯一性,编程规范要求程序员在自己定义包的名称之前加上唯一的前缀

  • 由于互联网上的域名是不会重复的,所以一般推荐采用公司在互联网上的域名的导致作为包的唯一前缀

  • 一个类可以使用同一包中所有类以及其他包中的所有类

  • 我们可以通过两种方式访问其他包中的公开类

    • 简单在每个类前面加上完整包名,例如:

    java.util Date today = new java.util.Date();

    • 更简洁更通用的方式是:使用import语句来导包。

    import语句提供了引用其他包中的快捷方式,可以免去使用完整包名的累赘
    import java.util.Date;
    ··· ···
    Date today = new Date();

  • 可以使用import 特定类,也可以导入整个包。通过在源代码文件的顶部(在打包语句后)使用import导入语句来实现。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值