Java基础知识——类与对象

类与对象

一、基本概念

1. 面向对象简介

Java 是完全面向对象的的编程语言。面向对象编程的组织方式围绕“对象”展开,而不是围绕“行为(方法)”。面向对象所采用的观点是“万物皆对象”。
面向过程:最小的程序设计单元是函数,通过定义各个函数组成。
面向对象:最小的程序设计单元是类,通过定义各个类组成,这些类可生成多个对象,对象对应着具体的某些事物。

2. 类与对象
  • 将具有相同属性和行为(方法)的一组对象的集合称之为类。
  • 而一个类的实现实例称作一个对象。
  • 一个类可以有多个实现对象,即类是一个抽象的概念,对象则是类的具体示例。例如,“人”是一个类,“张三”则是一个实例对象。
    在这里插入图片描述
3. 面向对象特征
  • 封装
    封装就是将对象的属性和方法结合并隐藏在对象内部,尽可能隐蔽对象的内部细节,对外形成一个边界,只保留有限的对外接口(特定方法)使之与外界发生联系。

    好处:使得外界无法随意存取对象内部属性,有效避免外部错误产生的影响,提高系统安全性,使软件错误局部化,减少查错和排错难度。

  • 继承
    继承通过吸收现有类的数据和方法,并增加新功能或修改现有功能来构建新类。子类拥有父类的全部属性和方法。

    好处:继承可节省程序开发时间,提高代码正确性。
    Java 中只能实现单继承,若想模仿多继承需要借助接口 interface,一个类可以 implements (实现) 多个接口。

  • 多态
    多态是指子类继承父类以后,对父类的属性或方法可以具有不同的表现行为。

    好处:降低了类和程序模块间耦合性,提高了类模块的封闭性。
    Java 中可以通过子类对父类方法的重写,或者子类中定义同名不同参数列表方法重载来实现多态。

  • 抽象
    忽略一个主题中与当前目标无关的方面,并不打算了解全部细节,而只是选择其中一部分。万物皆对象,世间几乎所有的事物我们都可抽象为一个类,用对象表达实体的属性和操作。
4. 多态介绍
  • 编译与运行
    编译:是一种动作,指的是将源代码翻译成目标代码 。将 Java 源文件翻译成字节码文件。
    编译时:是一种状态,一个时间段内。
    运行:代码要想跑(运行)起来,需要代码加载进内存中。
    运行时:将代码加载进内存,使其运行起来,也是一种状态,一个时间段内。

  • 分类
    编译时多态:编译时就已经确定状态了。也叫静态动态。例如,方法重载,本类对象的创建。
    运行时多态:我们常说的多态指的是运行时的多态。核心:编译时不能确定,运行时才能确定状态。一定是有继承关系存在时才产生。

  • 实现条件
    必须满足下面三个条件:
    要有继承关系,有子类和父类
    父类引用指向子类对象
    子类要重写父类的方法

  • 状态
    一个引用变量到底指向的是什么类型?
    Animal、Dog、Pig。 Dog 和 Pig 继承自 Animal
    Animal animal1 = new Pig(); 编译阶段,计算机无法识别 animal1 指向的是 Animal 类型还是 Pig 类型,必须等到运行时才能确定
    Dog dog = new Dog(); 计算机在编译阶段就能确定 dog 指向的具体类型为 Dog

二、 类的声明与对象的创建

1. 定义类

通过关键字 class 来定义一个类。类名首字母必须大写。
Java中使用驼峰命名法,类名每个单词的首字母要大写,例如,AddAge。
方法名每个单词的首字母小写,例如,addAge。

类定义格式如下:

访问符 修饰符 class 类名 {
	[ 属性 ]
	[ 方法 ]
}
public class Animal{
	private char name;
	private double weigh;
	
	public double setName(char name){
		this.name = name;
	}
	public double setWeigh(double weigh){
		this.weigh = weigh;
	}
	public void call( ){
		System.out.println("call"); 
	}
}
2. 类的实例化:创建对象
  • 声明该类类型的一个变量,即定义一个该类的对象的引用
  • 创建该对象的实际物理赋值,即在内存中为该对象分配地址空间
Animal a; 						// 声明对象名
a = new Animal();  				// 创建对象,分配内存空间
Animal b = new Animal();		// 一步到位

null 用来标识一个不确定的对象或者给已经创建过的对象释放内存

注意:null 仅可以赋值给引用类型变量,不可赋值给基本类型变量。基本数据类型:整形(byte、short、int、long)、浮点型(float、double)、字符型(char)、布尔型(boolean)。引用数据类型:类(class)、接口(interface)、数组、枚举(enum)、注解(Annotation)。

Animal a = null 				// 释放空间
3. 初始化对象的过程

Animal a = new Animal(168,98);

  • 首先,执行 Animal a; 时,系统为引用类型变量 a 分配堆内存空间,以便后来存储对象实际空间的地址值(即对象引用)。
  • 然后,执行 a = new Animal(); 时,会创建一个 Animal 对象,为新对象在 栈内存中开辟内存空间来存储对象所有属性并对其默认初始化。(即对象)
  • 然后,执行构造函数对其继续初始化。
  • 最后,执行表达式中的 = ,将所创建对象的内存空间的首地址赋给变量 a ,完成引用的指向操作。

在这里插入图片描述

对象引用存放在栈内存中,对象存放在堆内存中。
对象引用存的就是一个地址,指向的是一个内存空间,内存空间存放的是对象的内存地址,根据这个内存地址就可以找到这个对象。
而对象存储的是实际内容

三、 变量与方法

1. 类中变量
  • 【类的成员变量】类的属性成员,即在方法成员外部定义的变量
    实例变量:没有被 static 修饰,由于没有被 static 修饰,属于类的一个实例对象,只有对象被创建后才有,随着这个实例对象的产生而产生,消亡而消亡。
    static 变量:被 static 修饰后属于静态变量,它属于整个类,随着这个类的产生而产生,随着这个类的消亡而消亡,通过 类名. 的方式访问,会随着类的加载而进行初始化,如果没有初始化就默认初始化。
  • 【方法内的局部变量】
    成员变量:仅在方法内部起作用的局部变量
2. this 、 static 与 final 关键字
  • this 关键字
    代表当前所在类的对象,即本类对象。this非静态内容中都可以出现,用于获取当前对象的引用。
    当方法的参数或者方法中的局部变量与类的属性同名时,类的属性会屏蔽,此时访问类的属性就需要使用 this.属性名,当然,没有同名情况下可以直接使用属性的名字,不需要 this。

  • static 关键字
    修饰静态对象或方法,静态对象或方法从属于类,在内存中只有一份,只能通过类名调用,为该类的所有对象所共有。this 代表本类对象,因此不能用 this 访问静态变量。

  • final 关键字
    修饰变量:表示此变量不可修改,即常量。 final double PI = 3.14159; final Teacher t = new Teacher();
    修饰方法:表示此方法不可被重写。public final void func(){}
    修饰类:表示此类不可被继承。public final class Base{}

3. 构造方法
  • 构造方法在对象实例化的时候做初始化赋值
    构造方法名要与类名相同,权限修饰符为 public。没有返回值类型。

    // 以上述 Animal 类为例
    public class Animal{
    	private char name;
    	private double weigh;
    	
    	// 构造函数
    	public Animal(char name, double weigh){
    		this.name = name;
    		this.weigh = weigh;
    	}
    	
    	public void setWeigh(double weigh){
    		this.weigh = weigh;
    	}
    	public double getWeigh(){
    		return this.weigh;
    	}
    
    	public void call( ){
    		System.out.println("call"); 
    	}
    }
    
    
  • 若类中没有构造方法,编译器会自动加一个不带参数的缺省构造方法,可以执行:

    Animal a = new Animal();
    

    一旦自己定义了,缺省的构造方法将不存在,上面的无参初始化将无法执行,想能执行的化可以写在类中。

    // 构造函数 1 无参
    public Animal(){
    }
    // 构造函数 2 有参
    public Animal(char name, double weigh){
    	this.name = name;
    	this.weigh = weigh;
    }
    
4. 类的一般方法
  • 语法格式如下

    [ 访问符 ] [ 修饰符 ] < 返回类型 >  方法名 [ 参数列表 ] {
             // 方法体
    }
    
    public void setWeigh(double weigh){
    	this.weigh = weigh;
    }
    public double getWeigh(){
    	return this.weigh;
    }
    public void call( ){
    	System.out.println("call"); 
    } 
    
5. 方法的调用

通过对象引用来调用:如果一个方法没有被 static 修饰那么这个方法是属于类的实例,通过 对象名.方法名 来调用。
特别的,静态方法(static修饰),属于类,通过类名.方法名调用。

public class Animal{
    private char name;
    private double weigh;
    // 非静态方法
    public void call( ){
        System.out.println("call");
    }
	// 静态方法
    public static void call2( ){
        System.out.println("static");
    }

    public static void main(String[] args) throws Exception{
        Animal a = new Animal();
        a.call();              // 对象名.方法名
        Animal.call2();		   // 类名.方法名
    }
}

四、 方法的重载与重写

1. 方法重载
  • 在同一个类中,多个方法的方法名相同,参数列表(参数个数、类型、顺序)不同,称为为方法的重载。即方法名相同、参数列表不同

    注意:返回值不作为方法签名。

    public class Summation{
    	public int add(int a, int b){
            return a + b;
        }
    
        public float add(float a, float b){
            return a + b;
        }
    
        public double add(double a, double b){
            return a + b;
        }
    
        public static void main(String[] args) {
            Summation a = new Summation();
            System.out.println(a.add(1,2));
            System.out.println(a.add(1.0F,2.0F));
            System.out.println(a.add(1.0, 2.0));
        }
    }
    
2. 方法重写

方法的重写发生在继承关系中,子类继承父类后,对父类的方法重写使之具有不同的表现行为。重写的方法的签名及返回值类型都与父类中的相同,方法体不同。

注意:

  • 方法签名(方法名和参数列表)必须完全相同。

  • 返回值类型以及声明的异常可以与父类相同。

  • 父类的私有方法不可被重写。否则只会是在子类中定义了新方法。

  • 子类的可访问性只能大于等于其父类。(相同或是更公开)

  • 静态方法不可重写。

public class Animal{
    public void call( ){
        System.out.println("call");
    }
}

public class Dog extends Animal{
    public void call( ){
        System.out.println("wang wang !");
    }
}

public class Cat extends Animal{
    public void call( ){
        System.out.println("miao miao~");
    }
}

五、访问修饰符权限

访问控制private 成员缺省成员protected成员public 成员
同类
同包×
不同包子类××
不同包非子类×××

private 、protected、public 均是关键字,而 friendly 不是关键字,只是一种缺省访问修饰符的称谓。

六、类之间的关系

1. 继承
  • 子类继承父类的属性与方法,并且增加 / 重写属性或方法来满足子类需求。使用 extends 关键字来体现继承关系。继承关系示例图如下:
    在这里插入图片描述
    Java 中一个类可以有多个子类,但是一个类不能继承多个父类。只能一对多,不能多对一。即无法实现多继承。Java 中可以通过接口Interface 模仿多继承的实现。

    public class Person{
    	private String name;
    	private int age;
    	private Srting gender;
    	// 省略方法
    }
    
    public class Teacher extends Person{
    	private float salary; 			// 薪酬
    	private String department;		// 部门
    	// 省略方法
    }
    
    public class Student extends Person{
    	private int[] score; 			// 成绩
    	private String grade;			// 年级
    	// 省略方法
    }
    
  • 继承的重写体现了多态:指子类继承父类以后,对父类的属性或方法改写,可以具有不同的表现行为。

    方法重写时需注意:

    方法签名(方法名和参数列表)必须完全相同。
    返回值类型以及声明的异常可以与父类相同。
    父类的私有方法不可被重写。否则只会是在子类中定义了新方法。
    子类的可访问性只能大于等于其父类。(相同或是更公开)
    静态方法不可重写。

    public class Animal{
        public void call( ){
            System.out.println("call");
        }
    }
    
    public class Dog extends Animal{
        public void call( ){
            System.out.println("wang wang !");
        }
    }
    
    public class Cat extends Animal{
        public void call( ){
            System.out.println("miao miao~");
        }
    }
    
  • super 关键字
    代表父类对象,作用有:调用父类的构造方法,访问父类的属性和方法

    调用父类的构造方法:

    public class Person{
    	private String name;
    	private int age;
    
    	// 2. 因此若想有参无参构造方法都用,需要自行添加
    	public Person(){
    	}
    	// 1. 有参构造方法将会覆盖默认的缺省的无参构造方法
    	public Person(String name, int age){
    		this.name = name;
    		this.age = age;
    	}
    }
    
    public class Teacher extends Person{
    	private float salary; 			
    	private String department;		
    	
    	public Teacher(){
    	}
    	
    	public Teacher(String name, int age, float salary, String department){
    		super(name, age);  // 调用父类构造方法
    		this.salary = salary;
    		this.department = department;
    	}		
    }
    

    若子类构造方法中没有明确调用父类的构造方法,系统会自动调用父类的无参构造方法。若此时系统没有无参构造方法会报错。

    访问父类的属性和方法 :

    public class Person{
    	private String name;
    	private int age;
    		
    	// 省略构造函数
    	
    	public void printInfo(){
    		System.out.println(name,age);      // 父类方法
    	}
    }
    
    public class Teacher extends Person{
    	private float salary; 			
    	private String department;		
    	
    	// 省略构造函数
    	
    	public void printInfo(){
    		super.printInfo();					// 调用父类方法
    		System.out.println(salary);
    	}
    }
    
    • Object 类
      Object 类是所有类的顶级父类,在 Java 体系中,所有类都直接或间接的继承了 Object 类,此类下常用的方法有:

      方法名功能说明
      public boolean equals(Object obj)比较两个对象是否相等【可重写】
      public final Class getClass()判断当前对象所属类,返回 class 对象
      public String toString ()将当前对象转换为字符串【可重写】
      protected Object clone()生成当前对象的一个备份,并返回副本
      public int hashCode()返回当前对象的散列码

      equals() 方法:
      使用 == 可以比较两个基本类型变量值是否相等。
      但是比较两个引用类型的变量是否相等有两种方式:==表示两个变量是否引用同一个对象,即是否存的是同样的地址值。而 equals()方法比较的是两个指向的对象的内容是否相同。可以重写。

      toString() 方法:
      可以在类内对其进行重写,用来输出对象本身的属性。
      public String toString(){ return getClass().getName() + ‘’[name:“+name+”, age:“+age+”]"};
      输出 Person [ name: Tom, age: 18 ];

2. 实现

类似继承,Java 中可以通过一个类实现多个接口 Interface, 模仿多继承的实现。详细内容见下一章。

3. 依赖

一个类的方法中操作另一个类的对象,称其依赖于第二个类
在这里插入图片描述

public class Person{
	void travel(Car car){		// 方法中操作
		car.run("北京");
	}
}
class Car{
	void run(String city){
		System.out.println("汽车开到"+city)}
}
4. 关联

一个类中使用另一个类的对象作为属性
在这里插入图片描述

public class Person{
	Car car;						// 作为属性
	void travel(){
		car.run("北京");
	}
}
class Car{
	void run(String city){
		System.out.println("汽车开到"+city)}
}
5. 聚合

聚合是关联关系的一种特例,体现的是整体与部分的关系。整体由部分组成,比如说一个部门由多个员工组成。

public class Department{
	Employee[] employees;
	public static void main(String[] args){
		Employee e1 = new Empleyee();
		Employee e2 = new Empleyee();
		Employee e3 = new Empleyee();
		
		Department dept1 = new Department();
		dept1.employees = new Employee[] {e1,e2,e3}	

		Department dept2 = new Department();
		dept2.employees = new Employee[] {e1,e2}	
	}
}
class Empleyee{
}

部门由员工组成,同一个员工也可属于多个部门,并且部门解散后员工依旧存在,不会随之消亡。

6. 组合

组合关系是比聚合关系要求更高的一种关联关系,也是整体与部分,但是整体与部分不可分离,整体消亡部分消亡。例如汽车与其零件。
在这里插入图片描述

public class Car{
	Engine engine = new Engine();
	Chassis chassis = new Chassis();
	Bodywork bodywork = new Bodywork();
	Circuitry circuitry = new Circuitry();
}

class Engine{
}
class Chassis{
}
class Bodywork{
}
class Circuitry{
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值