面向对象知识点的总结(全)

面向对象编程(OOP)

Object Oriented Programming
对象 : Object

C 面向过程
C++ 半面向过程半面向对象
Java 面向对象: 把大象装进冰箱.

介绍

什么是类

具有相同特点(属性)和行为(动作)的集合的总称.
人类
植物类

属性和行为

什么是对象
是某一类的具体体现 实例
将类的抽象概念具体化.
人类的对象: 张三,特朗普,…
植物类的对象 : 路边的梧桐,杨树
手机类的对象 : 正在使用的手机
什么是属性
是一类事物的特点/特征.
人类的属性/特征 : 肤色,年龄,身高,体重…
植物类的属性 : 树干,树叶,树根,花,果实
手机的属性 : 价格,重量,颜色,形状
什么是方法
一类事物都可以进行的动作/行为.
人类的动作 : 吃饭睡觉打豆豆
植物的动作 : 开花,结果,光合作用
手机的动作 : 打电话,发短信

方法

什么是方法?

方法:在程序中要去实现的某一个功能,需要包含多条语句,这些语句包含循环语句结构,选择语句结构等共同来处理一件事情.

定义方法的格式详解

public static void main(String[] args){
    
    
		//执行语句
		System.out.println();
}
	 * [访问修饰符] 返回值类型 方法名([参数1],[参数2],...){
    
    
	 *     方法内的执行语句;
	 *     ...
	 * }
	 * 访问修饰符 : 控制访问权限
	 * 返回值类型 : 该方法执行后返回的结果的数据类型
	 * 		基本数据类型/引用数据类型	
	 * 		void :,方法执行后不返回任何数据
	 * 		---
	 * 		如果方法需要返回数据,
	 * 		1) 那就需要在返回值类型处写上返回数据的数据类型
	 * 		2) 在方法体的最后使用 return;的格式将值明确显示返回.
	 * 		3)只要不是void,必须在方法后加:  return;
	 *		4)return 后只能有一值;
	 *		5)如果需要返回多个值需要将多个值放进数组或方法,将数组或方法返回
	 *	eg.public static void main(String[] args){
    
    
	 *			int[] arr = returnMoreValue(1,2);
	 *			System.out.println(arr[0]);
	 *			System.out.println(arr[1]);
	 *	   }
	 *		//方法执行返回多个值:2个值为例
	 *		//需要将多个值放入数组,将数组返回
	 *	   public static int[]  returnMoreValue(int a,int b){
    
    
	 *	   		int[] arr = new int[2];
	 *			arr[0] = a;
	 *			arr[1] = b;
	 *			return arr;
	 *	   }
	 * 方法名 : 见名知意,驼峰原则
	 * () 参数列表 : 
	 * 		1 形式参数 : 该方法执行可能用到的数据
	 * 		2 形式参数的写法: 数据类型 变量名;
	 * 		3 列表内可以写多个参数,多个参数之间用逗号隔开,或者可以不写
	 *		4 当方法参数列表有参数时,在调用时(让方法执行时)
	 *		   就必须给方法的参数赋值	
	 * 参数类型:进入方法当中的数据是一个什么样的类型
	 * 参数名称:进入方法当中的数据对应的变量名称
	 * {
    
    }  方法体	
	 * 备注:方法不允许嵌套
	 * 执行语句 : 该方法真正的功能体现		

Java中方法的分类

JAVA中方法的分类

构造方法

  • 构造方法:类或者抽象类中(接口没有),与类名同名,无返回值,不能用static修饰。
  • 格式:权限修饰符 类名(参数){方法体}
  • 作用:初始化实例对象。
  • 调用:创建类的实例对象时,自动调用。
  • 继承性:无参构造其子类会自动调用父类的无斜体样式参构造supper()。含参构造不会被继承。

注意:构造方法分为含参构造和无参构造。JAVA会在编译时自动生成无参构造,但若书写了含参构造,则必须自己写无参构造,否则只能调用含参构造。

静态方法

  • 定义:类/接口中,用static修饰的方法。
  • 格式: 权限修饰符 static 返回值类型 方法名(参数){} (static可与final,private共存)
  • 特点:
  1. 静态方法属于整个类,不单独属于类的某一个对象。
  2. 静态方法类加载便存在,比对象先存在,随类而消亡。

实例/默认方法

抽象方法

私有方法

数组作为方法参数和返回值

数组作为方法参数

  数组作为应用类型能够当成方法的参数进行传递呢?当然可以

  • 数组作为方法参数传递,传递的参数是数组内存的地址
	public static void main(String[] args){
    
    
        int[] arr = {
    
    1,2,3,4,5};
        //调用方法,传递数组
        println(arr);
	}
   public static void println(int[] arr){
    
    
        for (int i = 0; i < arr.length - 1; i++) {
    
    
            System.out.println(arr[i]);
        }
    }

对象的创建及使用

		 * 通过类 创建对象 <==> 实例化
		 * 类名 对象名 = new 类名();
		 * -----------------------
		 * 数据类型 变量名 =;
		 * -----------------------
		 * 对象属性取值:
		 * 	数据类型 变量名 = 对象名.属性名;
		 * 
		 * 对象属性赋值:
		 * 	对象名.属性名 =;
		 * 
		 * 调用对象的方法[重点]
		 * 三种调用格式:
		 * 1.单独调用:对象名.方法名(参数具体值);
		 * 2.打印调用:System.out.println(对象名.方法名(参数具体值));
		 * 3.赋值调用:数据类型 变量名 = 对象名.方法名(参数具体值);
		 * 备注:当返回值类型为void的时候,这种方法只能单独调用,不能进行打印调用或者赋值调用
		 * 返回值类型一般可以理解为数据类型(基本数据类型和引用数据类型),此外还包含一种类型void类型,当方法执行完毕不需要给程序调用者返回人和的数据结果时,可以指定该方法的返回值类型为void,此时只能[单独调用]
		 * 1) 方法有参数,调用时必须传入实参
		 * 		实参与形参的个数,顺序,数据类型要保持
		 * 2) 方法没有参数,不能给参数
		 * 3) 方法无返回值,一定不能接收返回值
		 * 4) 方法有返回值,可以接收,也可以不接收
		 * 	 A : 无返回值
		 * 	 		A1 无返回值无参
		 * 				对象名.方法名();
		 * 			A2 无返回值有参数
		 * 				对象名.方法名(1,2,..);
		 * 	 B : 有返回值
		 * 			B1 有返回值无参
		 * 				[数据类型 变量名 = ]对象名.方法名();
		 * 			B2 有返回值有参数
		 * 				[数据类型 变量名 = ]对象名.方法名(1,2,..);
		public static void main(String[] args){
    
    
				// 创建对象
		Student stu1 = new Student();
		System.out.println(stu1);
		// 获得属性值 
		String name = stu1.name;
		int age = stu1.age;
		String stuNo = stu1.stuNo;
		String schoolName = stu1.schoolName;
		System.out.println("name = "+name);
		System.out.println("age = "+age);
		System.out.println("stuNo = "+stuNo);
		System.out.println("schoolName = "+schoolName);
		// 属性赋值
		stu1.name = "张三";
		stu1.age = 18;
		stu1.schoolName = "北京大学";
		stu1.stuNo = "100001";
		System.out.println("name = "+stu1.name);
		System.out.println("age = "+stu1.age);
		System.out.println("stuNo = "+stu1.stuNo);
		System.out.println("schoolName = "+stu1.schoolName);
		System.out.println("----------分割线---------");
		// A1 无返回值无参
		stu1.eat();
		// A2 无返回值有参数
		stu1.sleep("地");
		// B1 有返回值无参
		String result1 = stu1.playGame();
		System.out.println("结果 : "+result1);
		// B2 有返回值有参数
		String result2 = stu1.study("<java从入门到精通>", "黑笔");
		System.out.println("谁在学习 ? : " + result2);
		}
		public class Student{
    
    
			/*	
	 	     * 属性的写法:
	         * [访问修饰符] 数据类型 变量名;
	         * []内的代码,可写可不写
	         */
			public String name;
			public int age;
			public String stuNo;
			String schoolName;
			public String study(String book,String pen) {
    
    
			System.out.println("在学习"+book);
			String name = "张三";
		//	return "李四";
			return name;
			}
	
			void eat() {
    
    
				System.out.println("吃");
			}
	
			void sleep () {
    
    
				System.out.println("睡觉");
			}
		}

方法的重载和方法的重写

重载(Overload)

1.在同类中,方法名一样,参数列表不一样的方法之间叫做重载.
2.方法重载与那些因素有关:

  • 参数的个数不同
  • 参数的类型不同
  • 参数的多类型顺序不同

3.方法重载与那些因素无关:

  • 与参数的名称无关
  • 与方法的返回值类型无关
  • 与方法的修饰符无关


    好处:只需要记住唯一一个方法名称即可,就可以实现类似的多个功能.

重写(Override)

定义:重写是子类对父类的允许访问的方法的实现过程进行重新编写,返回值和形参都不能改变.
重写的规则:

  • 参数列表必须完全与被重写方法相同
  • 返回值必须完全相同
  • 访问权限不能比父类中被重写的方法的访问权限更低
  • 父类私有(private)方法不能被重写
  • 声明为final的方法不能被重写
  • 声明为static的方法不能被重写,但能被再次声明
  • 如果子类不是抽象类,子类必须重写父类中的abstract的方法
  • 如果子类和父类在同一个包下,子类可以被重写除private和final之外的所有方法
  • 如果子类和父类不在同一个包下,子类能重写父类中被public修饰和protected修饰的方法
  • 重写方法能够抛出任何非强制异常,无论被重写的方法是否抛出异常.但是,重写的方法不能抛出新的强制性异常
    注:所谓强制性异常,就是在编写程序的过程中,必须在抛出异常的部分try-catch或者向上throw异常

三大基本特征

继承 封装 多态

继承

1.场景:
  如果多个类存在相同的属性和行为时,将这些内容抽取到单独一个类中,
那么多个类无需再定义这些属性和行为,只要继承那一个类即可。
其中,多个类可以称为子类,单独的那个类称为父类、超类、基类
继承描述的是事物之间的所属关系,这种关系是:is-a的关系。
父类更通用,子类更具体。我们主要是通过继承,可以使事物之间形成一种关系体系。

2.定义:
  就是子类继承父类的属性和行为,使得子类对象具有与父类相同的属性、相同的行为。
  子类可以直接访问父类中的非私有的属性和行为。
3.好处:
1)提高代码的复用性
2)使得类与类之间产生了关系,是多态的前提。

4.继承格式:
  通过关键字extends,可以声明一个子类继承另一个父类
class SuperClass{

}
class Subclass extends SuperClass{

}

  1. 继承后的特点—成员变量
    1.成员变量不重名
    如果子类父类中出现不重名的成员变量,这时访问时没有影响的。
    如果重名,这时访问是受影响的。
    子父类中出现了同名的成员变量时,在子类中需要访问父类中非私有成员变量,就需要使用super关键字,
    修饰父类成员变量,类似于关键字this
    2.使用格式:
    super.父类成员变量名;
    备注:父类中的成员变量是非私有的,子类才可以直接访问。若父类中的成员变量私有了,子类不能直接访问的。
    通常编码时,我们一般遵循封装的原则,可以在父类中提供公共的setXxx()和getXxx()方法。

  2. 继承后的特点—成员方法
    1.成员方法不重名
    如果子类父类中出现不重名的成员方法时,这时的调用没有任何的影响。
    对象调用方法时,会先在子类中查找有没有对应的方法,若子类存在就会执行子类中的成员方法,
    若不存在就会执行父类中相应的方法。
    2.成员方法重名—重写(Override)
    方法重写:子类出现于父类一模一样的方法时(返回值类型,方法名和参数列表都相同),会出现覆盖效应
    也称为重写或者复写。声明不变,重新实现。
    3.重写的应用
    子类可以根据需要,定义特定于自己的行为,即沿袭了父类的功能名称,又能根据子类的需要重新实现父类
    的方法,从而进行扩展增强。比如:新的手机来电显示功能。
    备注:
    1.子类方法重写覆盖父类方法时,必须保证权限大于等于父类的权限。
    2.子类方法重写父类方法时,返回值类型,方法名和参数列表必须一模一样。
    在没有使用@Override时,子类定义父类方法时,方法名和参数列表可变,返回值类型不可变。

    1. 继承的特点:
      1.java只支持单继承,不支持多继承。
      2.java支持多层继承(继承体系)
      3.子类和父类是一种相对概念。
      备注:顶层父类是Object类,所有的类默认都继承Object类。

封装

1.封装:就是隐藏对象的属性和实现细节,仅对外提供公共访问方式,封装使用get,set方法。
2.封装的好处:

	  1、良好的封装能够减少耦合。
		 
      2、类内部的结构可以自由修改。

      3、可以对成员进行更精确的控制。

      4、隐藏信息,实现细节。

3.封装时的权限控制符区别如下:
在这里插入图片描述

假如:有一个学生类Student

public class Student{
    
    
	public int age;
	public string name;
	public Date date;
}

外部使用Student时,

public static void main(String[] args){
    
    
		Student stu = new Student();
		stu.age=16;
		stu.name="john";
		stu.date=2017;
}

但是,现实中如果很多外部代码都使用了Student这个类;某一天,如果这个类的age需要换成String类型,那么,外部使用它的任何地方都需要需改xxx.age=“xxx”,这将是非常繁琐的一个过程。


但是如果使用封装属性,开放访问接口的方法:

    public class Student{
    
    
    private String age; //修改int to String
    private string name;
     
    public void setAge(String age){
    
    
      this.age = String.valueOf(age); //修改
    }
    public String getAge(){
    
    
      return this.age;
    }
    }

这样外部使用它的地方都不用修改,只用修改对象内部就可以了,更加方便快捷。到了这里我们确实可以看出,封装确实可以使我们容易地修改类的内部实现,而无需修改使用了该类的客户代码。

多态(polymorphic)

Java中:同一个方法,传入相同类型的参数,但是运行结果不一样.
Java多态:让程序在运行时自行决定执行哪些方法

多态的三种表现形式

1.普通类多态定义的格式

父类 变量名 = new 子类();

2.抽象类多态定义格式
3.接口多态定义格式

多态的前提

1.子父类关系
2.子类必须重写父类方法
3.父类引用指向子类对象
  父类型 变量 = 子类对象;==>向上转型


属性没有多态性,方法有多态性
编译看父类,运行看子类

多态有什么好处?

有两个好处:
A:提高了代码的维护性(继承保证)
B:提高了代码的扩展性(由多态保证)

猫狗案例代码

    class Animal {
    
    
        public void eat(){
    
    
            System.out.println("eat");
        }
        
        public void sleep(){
    
    
            System.out.println("sleep");
        }
    }
     
    class Dog extends Animal {
    
    
        public void eat(){
    
    
            System.out.println("狗吃肉");
        }
        
        public void sleep(){
    
    
            System.out.println("狗站着睡觉");
        }
    }
     
    class Cat extends Animal {
    
    
        public void eat() {
    
    
            System.out.println("猫吃鱼");
        }
        
        public void sleep() {
    
    
            System.out.println("猫趴着睡觉");
        }
    }
     
    class Pig extends Animal {
    
    
        public void eat() {
    
    
            System.out.println("猪吃白菜");
        }
        
        public void sleep() {
    
    
            System.out.println("猪侧着睡");
        }
    }
     
    //针对动物操作的工具类
    class AnimalTool {
    
    
        private AnimalTool(){
    
    }
     
        /*
        //调用猫的功能
        public static void useCat(Cat c) {
            c.eat();
            c.sleep();
        }
        
        //调用狗的功能
        public static void useDog(Dog d) {
            d.eat();
            d.sleep();
        }
        
        //调用猪的功能
        public static void usePig(Pig p) {
            p.eat();
            p.sleep();
        }
        */
        public static void useAnimal(Animal a) {
    
    
            a.eat();
            a.sleep();
        }
        //把所有的可能都归为动物类
    }
     
    class DuoTaiDemo2 {
    
    
        public static void main(String[] args) {
    
    
            //我喜欢猫,就养了一只
            Cat c = new Cat();
            c.eat();
            c.sleep();
            
            //我很喜欢猫,所以,又养了一只
            Cat c2 = new Cat();
            c2.eat();
            c2.sleep();
            
            //我特别喜欢猫,又养了一只
            Cat c3 = new Cat();
            c3.eat();
            c3.sleep();
            //...
            System.out.println("--------------");
            //问题来了,我养了很多只猫,每次创建对象是可以接受的
            //但是呢?调用方法,你不觉得很相似吗?仅仅是对象名不一样。
            //我们准备用方法改进
            //调用方式改进版本
            //useCat(c);
            //useCat(c2);
            //useCat(c3);
            
            //AnimalTool.useCat(c);
            //AnimalTool.useCat(c2);
            //AnimalTool.useCat(c3);
            
            AnimalTool.useAnimal(c);
            AnimalTool.useAnimal(c2);
            AnimalTool.useAnimal(c3);
            System.out.println("--------------");
            
            //我喜欢狗
            Dog d = new Dog();
            Dog d2 = new Dog();
            Dog d3 = new Dog();
            //AnimalTool.useDog(d);
            //AnimalTool.useDog(d2);
            //AnimalTool.useDog(d3);
            AnimalTool.useAnimal(d);
            AnimalTool.useAnimal(d2);
            AnimalTool.useAnimal(d3);
            System.out.println("--------------");
            
            //我喜欢宠物猪
            //定义一个猪类,它要继承自动物,提供两个方法,并且还得在工具类中添加该类方法调用
            Pig p = new Pig();
            Pig p2 = new Pig();
            Pig p3 = new Pig();
            //AnimalTool.usePig(p);
            //AnimalTool.usePig(p2);
            //AnimalTool.usePig(p3);
            AnimalTool.useAnimal(p);
            AnimalTool.useAnimal(p2);
            AnimalTool.useAnimal(p3);
            System.out.println("--------------");
            
            //我喜欢宠物狼,老虎,豹子...
            //定义对应的类,继承自动物,提供对应的方法重写,并在工具类添加方法调用
            //前面几个必须写,我是没有意见的
            //但是,工具类每次都改,麻烦不
            //我就想,你能不能不改了
            //太简单:把所有的动物都写上。问题是名字是什么呢?到底哪些需要被加入呢?
            //改用另一种解决方案。
            
        }
        
        /*
        //调用猫的功能
        public static void useCat(Cat c) {
            c.eat();
            c.sleep();
        }
        
        //调用狗的功能
        public static void useDog(Dog d) {
            d.eat();
            d.sleep();
        }
        */
    }

多态的弊端:

不能使用子类的特有功能。

怎么才能使用子类特有的功能?

A:创建子类对象调用方法即可。(可以,但是很多时候不合理。而且,太占内存了)
B:把父类的引用强制转换为子类的引用。(向下转型)

注:向下转型中有可能的异常:
ClassCastException:类型转换异常一般在多态的向下转型中容易出现

猜你喜欢

转载自blog.csdn.net/weixin_44536951/article/details/109391410