JAVA初学习(三)(数组和面向对象)

六、数组

问题:如何存储一个班所有的同学名字?可以用变量存储吗?不行,怎么办?使用数组存储

6.1 数组

6.1.1 概念

​ — 是同类元素的集合,在内存上是一系列连续的区间(画图说明)

6.1.2 数组两种定义方式

  • 动态初始化

    • 类型[] 数组名 = new 类型[length]; 如 String[] arr = new String[3];
      • 注意:new --内存分配操作符,在堆内存中给数组分配空间
      • 动态初始化时,根据类型默认元素的值为 0、0.0、false、null(引用数据类型)
  • 静态初始化

    • 类型[] 数组名 = {值1,值2,…} 如 int[] arr ={1,2,3,4};
    • 类型[] 数组名 = new 类型[] {元素1,元素2,…} ,如arr =new int[]{2,4,6};
  • 注意:

    • length --数组的长度
    • index --数组下标
    • arr[index] --取某一个数组元素
    • 数组元素类型必须一致,可以存放引用类型和基本数据类型
    • 数组下标越界 --原因:当数组初始化以后,数组长度固定,当访问的下标在数组中不存在

6.1.3 数组遍历

  • for循环遍历 for(int i =0;i<arr.length;i++){}
  • foreach遍历 for(元素类型 当前元素:数组名){}
作业:
  1. 定义一个数组,求出最大值和最小值
  2. 判断一个数是否是回文数,如12321

6.1.4 二维数组的定义

  1. 定义:实际是数组里存放数组

  2. 动态初始化: 数组类型 [ ] [ ]数组名称 = new 数组类型[长度] [ (列数)]

    • 如 int[] [] a1 = new int[3] [ ];

    • int[ ] [ ] a1 = new int[3] [4];

    • int[] [] a1 = new int[ ] [4];//错误 ,必须声明长度

  3. 静态初始化:

    • 数组类型[ ] [ ] 数组名称 = new 数组类型[ ] [ ]{{1,2},{3,4,5},{6}}
    • 数组类型[ ] [ ] 数组名称 = {{1,2},{3,4,5},{6}}
  4. 遍历:嵌套循环

         for (int i = 0; i < arr.length; i++) { // 遍历二维数组个数
    			for (int j = 0; j < arr[i].length; j++) { // 遍历元素(数组)个数
    				System.out.println(arr[i][j]);// 打印数据
    			}
    		}
    

6.1.5 冒泡排序

冒泡排序原理:每一轮结束后,最大的元素放最后,且下一轮都会减少一个元素参与比较

           ....
		   int[] arr ={200,4,11,23,1,12};
		   int temp;
		   for (int i = 0; i < arr.length-1; i++) {//轮数
			for (int j = 0; j < arr.length-i-1; j++) {
				if (arr[j] >arr[j+1]) {
					temp =arr[j];
					arr[j] = arr[j+1];
					arr[j+1] = temp;
				}
			}
			再重新遍历数组arr即可  升序排序

6.1.6 工具类使用

  • Arrays.sort(数组名) --底层冒泡,只能升序,如 Arrays.sort(str);

  • Arrays.toString(数组名) --转为字符串

  • Arrays.fill(数组名,值) --填充数组 如 Arrays.fill(arr, 10);

  • Arrays.equals() --比较两个数组内容是否相同 注意:== 对于基本数据类型,比较是值本身,引用类型比较是地址编号 如 Arrays.equals(c1, c2);

  • 数组拷贝

    • Arrays.copyof(原数组,个数) – 方法内部已创建数组,如int[] a = Arrays.copyOf(src, 2);
    • System.arraycopy(数组A,起始位置,数组B,起始位置,个数) --复制内存效率更高,如 System.arraycopy(src, 2, dest, 0, 4);

七、面向对象

7.1 理解面向过程和面向对象思想

7.1.1 面向过程设计思想

  • 提问:从家到公司怎么过来的?
  • 面向过程设计思想含义: 重心是过程,做一件事情,有多个步骤(过程),每个步骤之间是有既定的顺序,最后按照顺序完成即可
  • 优点:代码结构比较清晰,容易理解,不足:对于类似淘宝、王者荣耀等业务非常复杂,代码量很庞大,不能一个人完成,如果使用面向过程的思想来设计,有N步骤,需要M个人来完成,不方便团队协作,代码维护难

7.1.2 面向对象设计思想(OOP -Object Oriented Programming)

1.现实中例子:造车

​ 问:同一类的车,如何制造出来的呢? --图纸

图纸 -----------------------------------------------> 具体的车

抽象的(类) 具体的 看的见摸得着(对象,多个相类似的车在一起,归一类)

类和对象关系

类 -----------------------------------------------------> 对象

​ 创建过程(按照图纸生产)

对象 ----------------------------------------------------> 类

​ 抽象过程(研究别国的汽车,抽象出国产汽车的图纸)

问:制造一辆具体的BMW mini车

mini车图纸 ----------->造车(需要很多零部件如发动机、轮胎、座椅等)

造发动机 ---->图纸

造轮胎 ---->图纸

​ 轮胎内部又需要橡胶 -->橡胶图纸

造车窗 ---->图纸

最终发现:制造一辆车,首先需要图纸,图纸中反映出很多零部件,每个零部件生产也需要图纸(类),只要有了图纸就能产出具体的产品,当发动机、轮胎、座椅等零部件制造好以后,最终造成就变成了零部件(对象)的组装,如果哪天轮胎坏了,只要换轮胎就可以了,车的维护就很简单。

现实生活中,造车就是一种面向对象(零部件)的设计思想,程序来源于生活,在程序中如何实现面向对象呢?

2.程序中例子 : 淘宝网站

商城网站 淘宝购物网站

​ 图纸 具体的一个产物

网站中细分功能:

产品类别 ----图纸

商品 —图纸

购物车 –

买家中心

评论区 …

采用这种面向对象的设计思想,每个组件由一个小团队完成(便于分工),彼此不冲突,相互协作,出现问题,找到对应的组件即可。

7.2 类

7.2.1 类

  1. 含义:在java中,类是程序的最小组织单元,是抽象的,是一种引用数据类型,也是一种数据封装机制和类型定义机制

  2. 类的三要素:

    • ​ 类名 --英文单词,首字母大写 如汽车类Car 学生类Student
    • ​ 静态特征 --属性 如:狗类 名字 年龄 体重等
    • ​ 动态特征 --行为或方法 如跑 、吃等
  3. 类的几个说明:

  • 类名、属性、方法的命名规范
  • 类中属性和方法成员:关注业务相关
  • 类的设计原则:单一原则(高内聚低耦合)
  • package:用来管理类
    • 包的定义规范:全部英文且小写 如当前包 package day5.modifier;
    • 公司域名倒着写 +项目名称+功能模块名称,如 org.w3c.dom
    • 导包:import java.util.*; import java.util.Scanner;
    • import static java.util.Arrays.*; --直接导入类Arrays中的方法,在程序中使用时,不用写类名,直接使用其中的方法
    • 当多个包下有同名类时,避免冲突,使用时直接包名+类名 如 java.sql.Date
  1. Dog测试类的内存分析图

    public class Dog {    //Dog类
         //静态特征:属性  成员属性  
    	String  name;
    	int age;
    	double weight;
    	//动态特征:方法  行为
    	public void eat(){
    		//内部实现细节
    		System.out.println("吃骨头..");
    	}
    
    public class TestDog {   //测试类
    	    public static void main(String[] args) {
    	    	    int i = 10;
    			   //创建一个对象
    	    	   // 类型  对象名 = new 类型();
    	    	   Dog dog = new Dog();
    	    	   //访问一个对象中属性   .点位符 优先级高于括号
    	    	   System.out.println(dog.name); //null
    	    	   //给狗起名字  对象给属性赋值   对象名.属性名 = 值
    	    	   dog.name = "旺旺";
    	    	   System.out.println(dog.name);
    	    	   //访问方法
    	    	   dog.eat();
    		}
    }
    

    内存分析图:

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-qJ2XIkRY-1611664282556)(C:\Users\njwb\Desktop\img\java\对象内存分析.png)]

  2. 类和对象的关系

    • 类是抽象的,对象是具体的,是类的一个实例
    • 类中的属性也叫对象属性或实例属性、成员属性
    • 类中的方法也叫对象方法或实例方法、成员方法
    • 通过对象可以抽象出类

7.3 引用类型

相对基本数据类型而言,在栈内存中,引用数据类型存储的是地址编号,而基本数据类型存储是具体的数值

7.4 方法

例: 设计一个类:榨汁机,有一个功能是榨汁功能。
  1. 语法:

    ​ 修饰符 返回值类型 方法名(参数列表) 异常类型 {// 方法体 实现某一功能的代码块;}

    • 访问修饰符:public protected 默认 private

    • 返回值类型:

      • void --该方法无返回值
      • 基本数据类型 --返回具体的值
      • 引用数据类型 --返回引用地址
    • 方法名称 --动词 驼峰命名法

    • 参数列表

      • 如果无参数,即方法名()
      • 若有参数 如方法名(参数1,参数2,…,参数n)

    案例:

    • 用面向对象思想来重构人机猜拳游戏

      1. 分析需求,找到程序中的要研究的对象

        游戏

        人的玩家 ----程序中的组件

        计算机玩家

      2. 根据对象抽象出类

        游戏对象 —游戏类

        人的玩家 --人玩家类

        计算机玩家 --计算机类

      3. 分别完成类中的属性和方法(和业务相关)

        人的玩家 PersonaPlay{

        属性:姓名 分数

        方法:出拳

        }

        测试PersonPlayTest类

        计算机玩家 ComputerPlay{

        属性:姓名 分数

        方法:出拳

        }

        测试ComputerPlayTest类

        游戏类Games{

        属性: (体现数据)

        ​ 对战次数

        ​ 计算机玩家

        ​ 真人玩家

        方法:

        (体现功能)

        输出游戏的启动界面

        游戏初始化

        开始游戏

        统计单局游戏的胜负情况

        统计游戏的数据

        统计整个游戏的胜负情况

        }

      ​ 粗粒度:宏观角度,大致将程序分为几块

      ​ 细粒度:微观角度,每个小块中有没有独立的功能,如果有则可以进一步抽取

    • 设计一个计算器,支持多个整数相加(至少两个参数) --数组 可变参数

      	 //可变参数   类型 ... 变量名
      	   public int add(int ... numbers){
      		    int cale =0;
      		    for (int i = 0; i < numbers.length; i++) {
      				cale +=numbers[i];
      			}
      		    return cale;
      	   }
      
    • 设计一个计算阶乘的方法(递归算法)

      //递归算法
      	 public int cale(int n){
      		 if (n== 0) {
      			 System.out.println("输入参数有误!");
      			return 0;
      		}else if (n == 1) {
      			return 1;
      		}else {
      			return n*cale(n-1);
      		}
      	 }
      

7.5 构造方法

需求:假设开一家宠物店,里面有狗、企鹅等 ,需要把狗的信息录入系统中,狗

​ 属性: 名字、品种、性别、健康程度

​ 方法: 自我介绍

1 含义:

也叫构造器、构造函数,专门用于创建对象,并给对象中的属性赋值,任何类中默认有个无参构造方法。

2 语法: 权限修饰符 方法名(参数列表) {…}
注意:
  • 是一种特殊方法,无返回值类型
  • 方法名和类名必须一致
  • 系统默认提供无参构造方法(隐式),如果想定义有参构造方法,则系统不会再提供无参构造方法

7.6 方法重载

  1. 含义: overload,一个类中定义多个同名的方法,但参数列表不同

  2. 满足三个条件

    1. 方法名必须相同

    2. 参数列表必须不同(个数、类型、位置顺序)

    3. 和权限修饰符、返回值类型无关

  3. 使用场景 --类中有多个功能一样,参数略微不同 jdk中有很多

    //无参构造器
    	public Dog(){
    		System.out.println("我是无参构造器");
    	}
    	//有参构造器
    	public Dog(String name, String strain, String sex, int health) {
    		super();
    		this.name = name;
    		...
    	}
    

    练习:设计一个自己的数学类,支持两个整数相加或三个整数的相加

7.7 this关键字

  1. 出现原因:为了解决这种参数名和属性名一样而造成的混淆不清,提供了this这个关键字

  2. this --指的是当前对象

  3. this. 属性或方法名() – 调用当前对象的属性或方法

  4. this() 或this(参数列表) – 调用无参构造或有参构造

    • 注意:在构造方法调用其他构造方法,this()必须放在第一行
    • 使用快捷键自动生成 alt +shift + s或右键 属性 构造方法(无、有)普通方法

7.8 面向对象的三大特征–封装性

1.1 原因

客户端调用一个对象,如果直接通过对象.属性去操作对象中的数据,可能会注入一个非法数据

,造成系统不安全,应该要屏蔽这种方式调用,提供另外一种方式来访问对象中的属性。

1.2 步骤
  1. 设置属性私有化 private

    1. 提供公共的访问方法和修改方法

      • get命名规则:返回值类型跟属性一致,名字getXxx,没有参数 ,对于boolean型属性,其名字一般为isXxx

      • set命名规则: 无返回值,名字为setXxx ,参数为属性的类型

    2. 在set方法中加入访问控制语句

1.3 作用

​ 1. 提高数据的安全性

​ 2. 提高代码复用性,使代码设计更加细粒度化。

7.9 常量

设计企鹅类(Penguin): 姓名 性别 区域 健康度 自述功能

注意:性别这块用常量表示

1 .1 含义:

​ 就是固定的,不能改变的量。只能用,不能修改, 如final String gender =“Male”;

注意:

  1. final修饰的基本数据类型,值不能改变,修饰引用数据类型,不能重新new对象

  2. final和static关键字连用,叫静态常量,属性命名必须是大写 ,下划线分隔,如 static final String FEMALE_SEX= “Female”;

  3. static 修饰类中属性,叫静态属性或类属性、类成员,类名.属性名(推荐)或对象名.属性名

    public static void main(String[] args) {
    Constant cons = new Constant();
    System.out.println(cons.FEMALE_SEX); //对象名.属性
    System.out.println(Constant.FEMALE_SEX);//类名.属性 推荐使用
    }

7.10 面向对象三大特征 – 继承

宠物店生意越来越好,做了一个调查问卷,客户说想增加猫、猪、老鼠、兔子等…

看之前的程序设计方式,有什么不妥的地方?

  1. 单一原则(高内聚低耦合)

  2. 开闭原则

    • 开:对扩展开放, 系统在扩展功能时,需要写更少代码即可,提高系统的扩展性

    • 闭:对修改封闭,在程序设计中,如果功能发生变化了,忌讳修改大量代码,只修改局部,不影响大局即可

对比狗和企鹅的代码有重复的代码

解决重复代码可以用继承解决

现实生活中,继承包含几个角色: 父亲 子女 孙子辈 像族谱

程序中 , 父类 子类 子类的子类

​ 代码编写:Pet类 和Pig类

1 继承***

​ 含义:以已经存在的类作为基础建立新类的一种技术,

​ 注意: 1.是一种单继承关系

​ 2.如果没有指明具体的父类,默认继承Object类 (超基类)

​ 语法 :public class 子类 extend 父类{},如public class Dog extend Pet {}

2 继承范围***

–子类可以继承父类的属性和方法等除以下,反之,父类不能访问子类自己定义的属性和方法

  1. 父类的私有属性和方法不能被访问
  2. 父类的构造方法不能被继承,如Dog dog = new Pet(); //错的
  3. 父类使用的默认修饰符,其他包中的子类不能被继承
3 四大访问修饰符***
private: 作用于本类内部 权限最小
默认权限: 同包中,本类、其他类(子类)
protected: 同包中,本类、其他类(子类),不同包中,子类
public :权限最大
4 子类对象初始化过程***

创建对象时,会给属性赋值(对象初始化)

创建子类对象时,会发生什么呢?

前提:给父类和子类无参构造器中设置打印一段信息,测试子类

***结论: 创建子类对象时,默认先调用父类的构造方法,先创建父类的对象,虽然没有直接调用父类构造器,但是子类中有个隐式的调用

public Dog(){
    //显示调用
    super();
    System.out.println("dog子类无参构造方法");
}

子类对象调用整个初始化过程

子类 对象名 = new 子类();

  1. 父类的属性赋值
  2. 父类构造方法
  3. 子类属性赋值
  4. 子类构造方法

注意:

  1. 在继承中,如果父类只设置有参构造,没有设置无参构造,子类构造通过super()显示,提示调用父类哪种参构造方法,否则会编译报错:Implicit super constructor Pet() is undefined. Must explicitly invoke another constructor
  2. 如果父类不设置有参构造方法,则隐式调用父类中无参构造。
  3. 父类设置有参构造,必须设置无参(系统不提供),子类中有参调用有参,无参调用无参
5 super用法

super --指父类对象 this --指当前对象

super() --子类调用父类的无参构造

super(参数) --子类调用父类的有参构造 且只能放第一行

super.属性名或方法 --调用父类的成员属性或方法

    System.out.println(getName());//子类继承
	System.out.println(this.getName());//子类继承即本类中的方法
    System.out.println(super.getName());//调用父类的方法

注意:

  1. 如果子类中,有一个方法,是从父类中继承过来,三种都可以使用,super.getName() 可读性高
  2. 使用场景:如果父类和子类中有同样的方法,但是这两个方法的实现不一样(方法重写),需要区分是父类还是子类
	//在子类中定义一个方法add 
	public void  add(){
			super.show(); //调用父类 
			this.show(); //调用子类
		}
6 方法重写(override)***

方法重载(overload)是什么?

6.1 重写满足条件:
  1. 继承关系 如Pet和Dog、Penguin
  2. 父类的方法不满足子类的需求,需要将父类的方法重新实现,如show()方法
6.2 概念

​ 也叫覆盖,override, 在子类中重新定义父类已经存在的方法如show()

6.3 特点
  1. 方法名、参数列表(个数、类型、顺序)和返回值类型,必须和父类一样
  2. 重写方法的权限大于等于父类方法的权限
  3. 子类方法中所抛出的异常是父类的一个子集
7 抽象类和抽象方法

问:给宠物系统扩展吃的功能

只要在父类中添加吃的方法

那么具体的子类,如狗啃骨头, 猪吃粗食 猫吃老鼠…必然要重写父类方法

父类宠物吃啥?不确定,pet中eat方法不好实现 ,也没有意义

–》可以把父类的eat方法声明成抽象方法(abstract修饰,无方法体 )

–》那么此类中有抽象方法,则必须是抽象类(abstract修饰,无构造方法)

–》子类继承抽象类,必须重写抽象方法,除非子类也是一个抽象类

1.1 什么是抽象类?

​ 被abstract修饰的类

1.2 什么是抽象方法?

​ 被abstract修饰方法,且没有方法体,注意:抽象方法不能被static、final、private、native和synchronize关键字修饰

1.3 特征
  1. 可以有抽象方法,也可以没有
  2. 可以有具体方法
  3. 可以有构造方法
  4. 不可以new对象
  5. 有抽象方法的类,肯定是抽象类
1.4 使用场景
  1. 当一个类中有一个方法无法实现时,可以使用抽象方法表示,这个类必须是抽象类,要求子类来实现
  2. 当一个类中没有抽象方法,声明了抽象类,不能被实例化,要求子类实现
8 final用法
1.1 修饰属性:

​ 当做常量,基本数据类型,值不能被修改,引用数据类型:不能被重新实例化,但对象中的数据域可以改变

1.2 修饰类:

​ 终结类,不能被继承 如jdk中 String类 Integer类

1.3 修饰方法:

​ 不能被重写

9 static用法***
1.1 修饰属性

叫静态属性、静态变量、类变量,直接通过类名.属性调用

和final 修饰属性,叫静态常量 如final static String FEMALE_SEX = “Female”;

1.2 修饰方法

叫静态方法、类方法,直接通过类名.方法名调用

注意:

  1. 静态方法或静态属性不能调用非静态方法或属性(产生时机早),反之则可以
  2. 使用场景:把工具类的方法设计成静态方法***
1.3 修饰代码块 static{ 代码块}

含义:

叫静态代码块,在类加载到方法区中,当类对象产生时,会优先执行且只加载一次,初始化作用

在静态代码块中,属于类级别的,不能引入非静态成员属性或方法(产生时机最早)

区别:

  1. 初始化块,在类内部,用于初始化对象相关内容,在产生对象后会自动执行,在构造方法之前。如{初始化块}
  2. 局部代码块,在方法内部,用于提前释放不使用的栈内存 {int a =1;}
1.4 修饰类(静态内部类,不做了解)
补充:对象产生的过程
  1. 读取class文件产生类对象,这一过程叫类加载
  2. 给静态变量赋初值
  3. 执行静态代码块
  4. 产生对象,给成员变量赋初始值
  5. 执行初始化块
  6. 执行构造方法
10 变量作用域
1.1 局部变量

​ 作用域在方法或代码块里,必须要先赋值后使用

1.2 全局变量

​ 作用于类中,属性不需要赋值可以使用(默认值)

​ 细分为对象属性(堆中)和类属性(方法区),对象属性共享类属性值

11 继承总结
1.1 作用:解决代码冗余度
1.2 使用场景:
  1. 多个类中有共同的属性和方法
  2. 满足 is a 关系 如 dog is a Pet ,penguin is a Pet

7.11 面向对象三大特征 -多态***

生活中的多态(多个状态):同一个事物,在不同条件下,对外界展示的形态也不一样

如水 100度 :气体 0 度下:固体 常温:液体

同学 教室: 学生 家里:子女 街上:潮男潮女

1 含义

引用类型变量指向其子类的对象(即向上转型)为前提,该变量在访问方法时,访问是该变量所指向的实际类型对象中的方法,多态也叫动态绑定,或运行时绑定,原理:当虚拟机调用一个实例方法时,它会基于对象实际类型(只能是运行时获取实际类型)来选择所调用的方法。

注意:

  1. 属性没有多态性
  2. 多态的实例不能访问子类特有的方法和属性
2 前提
  1. 继承
  2. 重写方法
  3. 父类引用指向子类对象(向上转型)
package day6.polym;

public class Test {
    public static void main(String[] args) {
     	Person p = new Person();
     	p.say();
	//父类引用指向子类对象
	 Person p = new Student();
	 p.say();	//编译器认为 p是Person类型对象 ,运行时才会找具体的实例对象
	 System.out.println(p.age); //age没有继承性  22
	 //p.show(); //不能访问子类私有方法 
	}
}
3 作用
  1. 提高代码的扩展性
  2. 代码的可插拔性
  3. 降低代码的冗余
4 类型转型和instanceof
  1. 自动转换

    • 基本类型 double d = 6;
    • 引用类型 父类 对象 = 子类对象 --向上转型
  2. 强制转换

    ​ 基本类型:int a = (double)3.14;

    ​ 引用类型:子类 对象 =(强制类型转换)父类对象 --向下转型(前提向上转型否则报类型转换错误)

  3. instanceof用法:

​ 对象 instanceof 类: 判断一个对象是否是一个类(其子类)的实例

   public static void main(String[] args) {
    	 double d =20.0;
    	 int b = (int) d;
    	 System.out.println(b);
    	 //向上转型
    	 Person p = new Student();
		//向下转型的前提是先向上转型  否则报运行时异常  java.lang.ClassCastException
    	 Student stu  = (Student)  p;  
        stu.eat();
        
    	 if (p instanceof Student) {
			Student student  =(Student) p;
			student.eat();   //把p转为student对象就可以访问私有方法了
		}
	}  

7.12 接口***

原因:面向对象的三大特征继承和多态都是和继承有关系,而java中只支持单继承,一个类继承某个类就不能继承其它类,而java中没有多继承,使用接口来代替

接口和类是同一级概念(程序最小组织单元)

生活中:USB接口 (厂家标准:规定USB接口2.0或3.0 长 宽 额定电压等) 是一种标准 实际上不工作

​ U盘、键盘、鼠标厂家按照USB接口的标准,去生产

​ 电脑上有USB接口,U盘可以插入拷贝数据 鼠标插入可以用

USB只是对外提供一种服务,具体做什么不清楚,取决于外设什么,最终是外设在工作,对于USB本身来说,不工作,方法不好写,用抽象方法。

java中的接口就类似于USB,能有抽象方法 也有具体的方法 ,也是一种多态的应用

1 概念

​ 是一种规范和标准,用来描述不同类事物的共同特征的方式

​ 实际上,接口就是多态的应用,接口中的implements 等价于extends

2 特征
  1. 接口中的属性默认是public static final型(静态常量)
  2. 接口中的方法通常是public abstract型抽象方法
  3. 接口中可以有具体方法,但要添加default关键字(jdk 1.8以后支持)
  4. 接口中可以有静态方法(jdk1.8以后)
  5. 接口中支持多继承
  6. 接口中没有构造方法,不能产生对象
  7. 类在继承同时,可以实现多个接口
    • 类与类之间:单继承
    • 类和接口之间:实现 多个接口
    • 接口与接口之间:多继承
3 接口和抽象类的区别
  1. 接口之间是多继承,抽象类是单继承
  2. 接口中属性是静态常量,而抽象类不需要
  3. 接口中没有构造方法,而抽象类有(但不能创建对象)
  4. 接口中的可以是抽象方法或default修饰的具体方法(jdk1.8新增),而抽象类中可以有任意类型的方法
4 面向接口编程

招聘一个程序员,会写代码、唱歌、打麻将等,只是关心这种能力,而不关心具体是哪个人

在java中,设计标准、能力,先定义接口而不关心具体的实现,这就是面向接口编程,是软件实现中一种设计风格,使得程序更具有兼容性。

软件公司,对于架构师而言,要架构一个系统,首先要确定功能、标准,而具体的实现由程序员完成,某种程度上体现了团队合作性。

5 jdk中的接口类型
  1. able型接口(以able结尾的),如Runnable Comparable
  2. 标准型接口(作为一种标准),如字符序列接口CharSequence
  3. 常量型接口(也常用具体的类表示,所有成员都是静态常量),如Constants类
  4. 标识型接口 (什么都没有) ,如 Cloneable、Serializable
6 接口应用

对数组的排序方法: 如Arrays.sort(数组名) 冒泡排序法 , 默认是升序

学生对象(姓名、年龄)数组排序步骤

  1. 定义一个学生类,实现Comparable接口

    public class Student  implements Comparable<Student>{
        @Override
    	public int compareTo(Student other) {
    		// this当前对象和数组中其他对象比较
    		 if (this.age>other.age) {
    			return 1; //升序
    		}else if (this.age == other.age) {
    			return 0;  
    		}else {
    			return -1;//降序
    		}
         }   
    
  2. 定义一个比较器类,实现Comparator接口

    public class StudentComparator implements Comparator<Student>{
       	    @Override
       	    public int compare(Student o1, Student o2) {
       	         if (o1.getAge() >o2.getAge()) {
       	            return 1;
       	        }else if (o1.getAge() == o2.getAge()) {
       	            return 0;
       	        }else {
       	            return -1;
       	        }
       	    }
       	}
    
  3. 测试类

    public static void main(String[] args) {
        	StudentComparator sc = new StudentComparator();
        	Student[] s ={new Student("Tom",20),new Student("Marry",22),new Student("Jerry",18)};
        	//Arrays.sort(s); //出现类转换异常
        	Arrays.sort(s, sc);
        	System.out.println(Arrays.toString(s));
    }
    

7.13 内部类

1.普通内部类
public class Outer{
     int a = 10;
    // 1.普通内部类
     class Inner{
         int a1 =100;
         void show(){
         System.out.println("***普通内部类***");
         System.out.println(this.a1);
         System.out.println(Outer.this.a);
         }
     }
}
2.静态内部类
	static class InStatic {
		// 静态变量
		static int s1 = 111;
		int s2 = 222;
		void m1() {
			System.out.println("****静态内部类****");
			System.out.println(s1);
		}
	}
3.局部内部类
void m(){
    class Local{
     int a = 100;
    System.out.println("***局部内部类***");
    System.out.println(a);
    }
    new Local();
}
4.匿名内部类***
 public static void main(String[] args) {
        	     final int a = 1000;
        	     /**
        	      * 1.定义一个类,该类没有名字
        	      * 2.产生一个对象
        	      */
			     Person  person  =new Person() {
			    	 int num;
					@Override
					public void eat() {
						num =100;
						System.out.println(num);
						System.out.println(a);
						System.out.println("匿名内部类");
					}
				};
				person.eat();
		}
  1. 内部接口
Interface Inner{
    void show();
}

7.14 枚举类

  1. 只能产生固定的对象,在定义时已经确定好了,作为属性存在

  2. 枚举的属性全是public static final型属性,类型和枚举的类型一致

//定义一个枚举类型
public enum Course {
      Java,
      MySql;
}

// 
package day6.enumeration;
class Student{
	  String name;
	  Course c;
	  void show(){
		  System.out.println("姓名:"+name+",课程:"+c);
	  }
}
public class Test {
        public static void main(String[] args) {
			    Student stu = new Student();
			    stu.name = "张三";
			    stu.c =Course.Java;
			    stu.show();
			    switch (stu.c) {
				case Java:
					System.out.println("上java课程!");
					break;          
				case MySql:
					System.out.println("上mysql课程!");
					break;
				}
		}
}

7.15克隆对象

步骤:

  1. 重写Object对象中clone()方法

  2. 实现Cloneable标识型接口

public class Monkey extends Object implements Cloneable{
	String name;
	int age;
	
	public Monkey() {
		System.out.println("无参构造");
	}
	public Monkey(String name, int age) {
		super();
		this.name = name;
		this.age = age;
		System.out.println("有参构造");
	}
	@Override
	public String toString() {
		return "Monkey [name=" + name + ", age=" + age + "]";
	}
	//克隆方法
	@Override
	protected Object clone() throws CloneNotSupportedException {
		return super.clone();
	}
	public static void main(String[] args) throws CloneNotSupportedException {
		//创建对象
    	Monkey m1 = new Monkey("金丝猴", 2);
    	Monkey m2 = (Monkey) m1.clone();
    	System.out.println(m1);
    	System.out.println(m2);
	}
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

佛系小樂

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值