【JavaSE学习】03面向对象&Java语法

JavaSE(B站黑马)学习笔记

01Java入门
02数组、方法
03面向对象&Java语法
04-1Java高级(Stream流、异常处理、日志技术)
04-2Java高级(文件处理-IO流)
04-3Java高级(多线程、网络编程)
04-4Java高级(单元测试、反射、注解、动态代理、XML)
05-1常用API
05-2常用API(集合)


文章目录


前言

JavaSE(B站黑马)学习笔记 03面向对象&Java语法


03面向对象&Java语法

面向对象学习建议

关注语法点的基本作用,短期内不要想能做什么,这些都是螺丝钉,最后通过整合做成火箭

面向对象概述

什么是面向对象:

面向:找、拿
对象:东西
面向对象编程:找或拿东西过来编程

更加符号人类的思维来编程,比如我们想要让屋子干净,可以使用扫地机器人 也可以用扫把,扫地机器人和扫把就是两个不同对象,我们通过对象来解决让屋子干净问题。 再比如我们想要到达某个目的地,可以坐高铁,也可以坐飞机,同样也可以开车,他们就代表三个对象,我们可以使用任意一个对象解决到达目的地的问题。记住这个思想,以后我们编程会new许多个对象,而这些对象就是帮我们解决问题的。

面向对象学习什么
学习自己设计对象并使用——面向对象的语法。

设计对象并使用

设计类、创建对象并使用

类是什么

先有类才有对象

如何设计类



定义类的注意事项

  • 类名首字母建议大写,且有意义,满足“驼峰命名法”
  • 一个Java文件中可以定义多个class类,但只能一个类是public修饰,而且public修饰的类名必须成为代码文件名。实际开发中建议还是一个文件定义一个class类。
  • 成员变量的完整定义格式是:修饰符 数据类型 变量名称 = 初始化值; 一般无需指定初始化值,存在默认值。

对象在内存中的运行机制

构造器

为什么学习构造器?

  • 真正知道对象具体是通过调用什么代码得到的。
  • 能够掌握为对象赋值的其它简便写法
  • 为以后学习面向对象编程的其它内容做支撑。

构造器的注意事项

  • 任何类定义出来,默认就自带了无参数构造器,写不写都有。
  • 一旦定义了有参数构造器,那么无参数构造器就没有了,如果还想用无参数构造器,此时就需要自己手写一个无参数构造器了。

this关键字

this关键字是什么

  • 可以出现在构造器、方法中
  • 代表当前对象的地址

this关键字的作用

  • 可以用于指定访问当前对象的成员变量、成员方法。

举例
如下图:形参名直接写 n、p 无法 ‘见名知意’ 不被推荐使用。而形参名与成员变量名相同又无法正确区分。使用this就能完美解决这个问题,因为this代表当前创建对象的地址,所以this.name就代表当前对象的成员变量。使用this.name = name 就能完美的将传入的值赋给成员变量

下图也是如此

面向对象三大特征:封装

  • 面向对象的三大特征:封装、继承、多态
  • 封装:告诉我们,如何正确设计对象的属性和方法
  • 封装的原则:对象代表什么,就得封装对应的数据,并提供数据对应的行为

举例
人画圆:圆是自己画的,人只是提供了一个半径,然后调用了draw方法,draw方法在根据半径的信息画了一个圆。

人关门:门本来就可以关上,关是门 的一个方法,谁都可以关,人只是施加了一个力让门关上

张三砍死了李四:死是李四死的,死这个方法是李四本来就具有的,张三只是拿刀触发了李四死的方法,造成了李四的死亡

理解封装思想的好处

sun公司知道我们对字符串的操作是很常见的,所以它就给我们提供了一个String对象,里面设定了相应的属性来封装我们要处理的字符串,并提供了对字符串进行处理的各种方法。想做什么找对应的方法就行

sun公司为了简化我们的开发,提供了很多很多的对象给我们使用,每个对象又有很多很多的方法。我们只用提供对应的数据找对象 调方法就行了


JavaBean

Static

static静态关键字

static是什么

  • static是静态的意思,可以用来修饰成员变量、成员方法。
  • static修饰成员变量之后称为静态成员变量(类变量),修饰方法之后称为1静态方法(类方法)。
  • static修饰后的成员变量,可以被类的所有对象共享(访问、修改)

简单来说,用static修饰的成员变量或方法,当它被实例成对象访问的地址都是同一个,被所有人共享。

static修饰成员变量

如下图:分别实例处user1和user2,onLineNumber成员变量使用static修饰,name没有。当user1设置了onLineNumber=163、name=“Tom”。同时打印两个对象的值。onLineNumber成员变量值被所以人共享,而name值没有。(注:访问静态成员变量推荐使用 类名.静态成员变量 下图只是方便演示)。

简单来说,被static修饰则在内存只存在一个地址,每个人都来访问这个地址。没有被修饰则在内存中开辟新的地址存放,每次访问不同地址。

static修饰成员变量的内存原理

静态变量跟类同时加载

static修饰成员方法


static修饰成员方法的内存原理

静态成员方法跟类一起加载,普通方法当类被实例化成对象后才被加载

static访问注意事项

  • 静态方法只能访问静态的成员,不可以直接访问实例成员。
  • 实例方法可以访问静态的成员,也可以访问实例成员。
  • 静态方法中是不可以出现this关键字的。

1.静态方法只能访问静态的成员,不可以直接访问实例成员。

静态方法中是不可以出现this关键字的,因为静态方法可以不用对象调,而this代表当前对象的地址。

static应用知识-工具类

为什么工具类中的方法不用实例方法做?

  • 实例方法需要创建对象调用。
  • 此时用对象只是为了调用方法,这样只会浪费内存。

如果每个人new对象出来只是为了调用方法就太浪费内存了。

工具类定义时的其他要求:

由于工具里面都是静态方法,直接用类名即可访问,因此,工具类无需创建对象,建议将工具类的构造器进行私有。

将构造方法私有化隐藏,这样别人就无法创建对象了。不写也行,写了代码更加严谨

static应用知识-代码块

代码块概述

  • 代码块是类的5大成分之一(成员变量、构造器,方法,代码块,内部类),定义在类方法外,跟方法属于平级关系。
  • 在Java类下,使用 { } 括起来的代码被称为代码块 。

代码块分为

  • 静态代码块:

    • 格式:static { }
    • 特点:需要通过static关键字修饰,随着类的加载而加载,并且自动触发、只执行一次。属于类
    • 使用场景:在类加载的时候做一些静态数据初始化的操作,以便后续使用。
  • 构造代码块(了解,见的少)

    • 格式:{ }
    • 特点:每次创建对象,调用构造器执行时,都会执行该代码块中的代码,并且在构造器执行前执行。属于对象
    • 使用场景:初始化实例资源。

静态代码块,跟类一起加载,所以比main先打印

构造代码块,属于对象,每次构建对象都会执行一次

静态代码块实际案例:09Request&Response 中的代码优化:SqlSessionFactory

static应用知识-单例设计模式

设计模式

面向对象三大特征:继承

继承概述

什么是继承?

  • Java中提供一个关键字extends,用这个关键字,我们可以让一个类和另一个类建立起父子关系。

  • Student称为子类(派生类),People称为父类(基类 或超类)。

  • 作用:当子类继承父类后,就可以直接使用父类公共的属性和方法了。

使用继承的好处

  • 可以提高代码的复用性

继承的设计规范、内存运行原理

内存运行原理

继承的特点

  • 子类可以继承父类的属性和行为,但是子类不能继承父类的构造器。
  • Java是单继承模式:一个类只能继承一个直接父类。(只能有一个爹)
  • Java不支持多继承、但是支持多层继承。(有爷爷跟祖宗)
  • Java中所有的类都是Object类的子类。(Object是祖先)

1.子类是否可以继承父类的构造器?

不可以的,子类有自己的构造器,父类构造器用于初始化父类对象。

2.子类是否可以继承父类的私有成员?

能继承,不能直接访问,内存中看还是含有。(有争议,我感觉能继承)

例如:小头爸爸传给大头儿子一个保险箱,但是没告诉密码。那不就相当于继承但不能直接访问。

保险箱可以用电锯强行锯开,父类私有属性和方法也可以暴力破解(需要用到在深究)。

3.子类是否可以继承父类的静态成员?

有争议的知识点。
子类可以直接使用父类的静态成员(共享形式)
但黑马老师认为:子类不能继承父类的静态成员。(共享并非继承)
静态变量的地址都是同一个,所以子类只是共享了父类的地址,并不是继承

继承后:(super关键字)成员变量、成员方法的访问特点

在子类方法中访问成员(成员变量、成员方法)满足:就近原则

  • 先子类局部范围找
  • 然后子类成员范围找
  • 然后父类成员范围找,如果父类范围还没有找到则报错。

如果子父类中,出现了重名的成员,会优先使用子类的,此时如果一定要在子类中使用父类的怎么办?

  • 可以通过super关键字,指定访问父类的成员。

没有重名还是找父类

继承后:方法重写

什么是方法重写?

  • 在继承体系中,子类出现了和父类中一模一样的方法声明,我们就称子类这个方法是重写的方法。

方法重写的应用场景

  • 当子类需要父类的功能,但父类的该功能不完全满足自己的需求时。
  • 子类可以重写父类中的方法。

重写不加注解的话,子类方法名和父类方法名不一样就不容易知道,这样容易造出新方法。使用@Override注解后会进行重写校验,子类方法名跟父类方法名不一样就提示出错,更安全、也提高代码可读性

继承后:子类构造器的特点

子类继承父类后构造器的特点:

  • 子类中所有的构造器默认都会先访问父类中无参的构造器,再执行自己。

为什么?

  • 子类在初始化的时候,有可能会使用到父类中的数据,如果父类没有完成初始化,子类将无法使用父类的数据。
  • 子类初始化之前,一定要调用父类构造器先完成父类数据空间的初始化。

怎么调用父类构造器的?

子类构造器的第一行语句默认都是:super(),不写也存在。

总结:先有爹后又子

继承后:子类构造器访问父类有参构造器

super调用父类有参数构造器的作用:

  • 初始化继承自父类的数据。

如果父类中没有无参数构造器,只有有参构造器,会出现什么现象呢?

  • 会报错。因为子类默认是调用父类无参构造器的。

如何解决?

  • 子类构造器中可以通过书写 super(…),手动调用父类的有参数构造器

this和super详情

  • this:代表本类对象的使用;super:代表父类存储空间的标识

this()的使用,调用本类的构造器

包、权限修饰符

权限修饰符

什么是权限修饰符?

  • 权限修饰符:是用来控制一个成员能够被访问的范围。
  • 可以修饰成员变量,方法,构造器,内部类,不同权限修饰符修饰的成员能够被访问的范围将受到限制。

同包其它类中

protected不同包下的子类访问:父类方法用protected修饰,子类继承后用子类对象进行访问。注意:仅供子类内用子类对象访问,其它类中用该子类对象也无法访问。就是只能在子类使用。如图:

final关键字

final的作用

目的:final修饰变量可能会用,其它不常用,只要能看懂别人写的代码就行

final修饰变量的注意

  • final修饰的变量是基本类型:那么变量存储的数据值不能发生改变。
  • final修饰的变量是引用类型:那么变量存储的地址值不能发生改变,但是地址指向的对象内容是可以发生变化的。

常量

后面使用响应状态码就会使用

枚举

枚举和常量都是为了做信息的标志和信息的分类,但常量进行判断时代表一个值,随便输入值都可以判断其它人不按规则输入就没用了,而枚举是一种类型,是一组常量的集合。进行判断时只能填入枚举类型。如图:

枚举和常量都可以做信息的标志和信息的分类,但项目中还是大量使用常量,因为常量简单

反编译后观察枚举的特征

反编译枚举类后会自动加上public static final

反编译就是先将Java文件编译成class文件,再把class文件里的源代码弄出来

详解参考网址:Java枚举详解

抽象类

抽象类概述

  • 在Java中abstract是抽象的意思,可以修饰类、成员方法。
  • abstract修饰类,这个类就是抽象类;修饰方法,这个方法就是抽象方法。

注意事项

  • 抽象方法只有方法签名,不能声明方法体。
  • 一个类中如果定义了抽象方法,这个类必须声明成抽象类,否则报错
  • 一个类如果继承了抽象类,那么这个类必须重写完抽象类的全部抽象方法,否则这个类也必须定义成抽象类。

声明一个为Animal的类作为父类,让其它动物去继承。每个动物都要跑,定义一个跑的行为(方法),但每个动物跑的都不一样,所以把这个方法不完全写出来,声明成抽象的,让子类再去实现(子类继承后必须重写)

作用:派生子类,约束子类一定完成这个行为,具体完成由子类决定

抽象的使用场景

  • 抽象类可以理解成不完整的设计图,一般作为父类,让子类来继承。
  • 当父类知道子类一定要完成某些行为,但是每个子类该行为的实现又不同,于是该父类就把该行为定义成抽象方法的形式,具体实现交给子类去完成。此时这个类就可以声明成抽象类。

抽象类案例

特征和注意事项

  • 类有的成员(成员变量、方法、构造器)抽象类都具备
  • 抽象类中不一定有抽象方法,有抽象方法的类一定是抽象类
  • 一个类继承了抽象类必须重写完抽象类的全部抽象方法,否则这个类也必须定义成抽象类。
  • 不能用abstract修饰变量、代码块、构造器。
  • 最重要的特征:得到了抽象方法,失去了创建对象的能力(有得有失) 为什么:反证法:假如抽象类可以创建对象,那使用它的方法连方法体都没有怎么使用。

final和abstract是什么关系?

  • 互斥关系
  • abstract定义的抽象类作为模板让子类继承,final定义的类不能被继承。
  • 抽象方法定义通用功能让子类重写,final定义的方法子类不能重写。

抽象类的应用知识:模板方法模式

设计模式

接口

接口的定义与特点

  • 接口的格式如下:

  • JDK8之前接口中只能是抽象方法和常量,没有其他成分了。

  • 接口不能实例化。

  • 接口中的成员都是public修饰的,写不写都是,因为规范的目的是为了公开化。

什么是接口

  • 接口是一种规范
  • 规范使用这个接口的类必须按照规定的方法设定功能
  • 和抽象类很像,不过接口类必须被全部实现,抽象类不用

比如插座和插头有三孔有两孔,它们都必须按照国家标准来设计才能实现通用。而国家标准就是一种接口(规范)

接口的使用:被实现

  • 接口是用来被类实现(implements)的,实现接口的类称为实现类。实现类可以理解成所谓的子类。

  • 从上面可以看出,接口可以被类单实现,也可以被类多实现。

补充知识

接口与接口的多继承

基本小结

  • 类和类的关系:单继承。
  • 类和接口的关系:多实现。
  • 接口和接口的关系:多继承,一个接口可以同时继承多个接口。

接口多继承的作用

  • 规范合并,整合多个接口为同一个接口,便于子类实现。

一个个实现

接口和接口多继承,整合多个接口为同一个接口,便于子类实现。

JDK8开始接口新增的方法

版本1.0上线后想进行版本更新,对接口添加方法,但牵一发而动全身,全部都要实现,这时JDK8版本开始后就允许接口中直接定义带有方法体的方法。

第一种:默认方法

  • 类似之前写的普通实例方法:必须用default修饰
  • 默认会public修饰。需要用接口的实现类的对象来调用

第二种:静态方法

  • 默认会public修饰,必须static修饰。
  • 注意:接口的静态方法必须用本身的接口名来调用。

第三种:私有方法

  • 就是私有的实例方法:,必须使用private修饰,从JDK 1.9才开始有的。
  • 只能在本类中被其他的默认方法或者私有方法访问。

注意:JDK8新增的3种方法我们自己在开发中很少使用,通常是Java源码涉及到的,我们需要理解、识别语法、明白调用关系即可。

接口的注意事项

  1. 接口不能创建对象
  2. 一个类实现多个接口,多个接口的规范不能冲突
  3. 一个类实现多个接口,多个接口中有同样的静态方法不冲突。
  4. 一个类继承了父类,同时又实现了接口,父类中和接口中有同名方法,默认用父类的。
  5. 一个类实现了多个接口,多个接口中存在同名的默认方法,可以不冲突,这个类重写该方法即可。
  6. 一个接口继承多个接口,是没有问题的,如果多个接口中存在规范冲突则不能多继承。

面向对象三大特征:多态

多态的概述

什么是多态?

  • 同类型的对象,执行同一个行为,会表现出不同的行为特征(比如猫类,狗类都属于动物类。但它们执行跑的行为有所不同)

多态的常见形式


这种类型的合理性是狗类和乌龟类都继承于动物类,都属于动物类型,所以可以赋给动物类型。

多态中成员访问特点

  • 方法调用:编译看左边,运行看右边。
  • 变量调用:编译看左边,运行也看左边。(注意:多态侧重行为多态

因为多态侧重的是表现不同的行为特征

多态的前提

  • 继承/实现关系;有父类引用指向子类对象;有方法重写(多态侧重行为多态)

多态的优势

优势

  • 在多态形式下,右边对象可以实现解耦合,便于扩展和维护。

假如业务开始需要狗类,到业务中期却换成乌龟类,就会造成更换对象要改一大堆地方。使用多态则只需跟换一处地方即可。可以实现解耦合 如图:

  • 定义方法的时候,使用父类型作为参数,该方法就可以接收这父类的一切子类对象,体现出多态的扩展性与便利。

多态下会产生的一个问题:

  • 多态下不能使用子类的独有功能

多态下: 类型转换问题

**自动类型转换(从子到父):**子类对象赋值给父类类型的变量指向

强制类型转换(从父到子)

  • 从父到子( 必须进行强制类型转换,否则报错): 子类 对象变量 = (子类)父类类型的变量

  • 作用:可以解决多态下的劣势,可以实现调用子类独有的功能。

  • 注意: 如果转型后的类型和对象真实对象的类型不是同一种类型,那么在运行代码时,就会出现ClassCastException

Java建议强转转换前使用instanceof判断当前对象的真实类型,再进行强制转换

上面看着是不是有点多此一举,明明可以看到a2就是乌龟类型还判断。因为这里只是演示,真实项目中很多情况是看不到真实类型是什么的。

多态综合案例


内部类

内部类概述[了解]

内部类

  • 内部类就是定义在一个类里面的类,里面的类可以理解成(寄生),外部类可以理解成(宿主)。

内部类的使用场景

  • 场景:当一个事物的内部,还有一个部分需要一个完整的结构进行描述时。如汽车类中的发动机类

基本作用

  • 内部类通常可以方便访问外部类的成员,包括私有的成员。
  • 内部类提供了更好的封装性,内部类本身就可以用private ,protectecd等修饰,封装性可以做更多控制。

静态内部类[了解]

  • 有static修饰,属于外部类本身。
  • 它的特点和使用与普通类是完全一样的,类有的成分它都有,只是位置在别人里面而已。

静态内部类创建对象的格式:

静态内部类的访问拓展:

1、静态内部类中是否可以直接访问外部类的静态成员?

  • 可以,外部类的静态成员只有一份可以被共享访问。

2、静态内部类中是否可以直接访问外部类的实例成员?

  • 不可以的,外部类的实例成员必须用外部类对象访问。

总结:

  • 如果一个类中包含了一个完整的成分,如汽车类中的发动机类。
  • 特点、使用与普通类是一样的,类有的成分它都有,只是位置在别人里面而已。
  • 访问总结:可以直接访问外部类的静态成员,不能直接访问外部类的实例成员。
  • 注意:开发中实际上用的还是比较少

成员内部类[了解]

什么是成员内部类?

  • 无static修饰,属于外部类的对象。
  • JDK16之前,成员内部类中不能定义静态成员,JDK 16开始也可以定义静态成员了。

成员内部类创建对象的格式:

成员内部类的访问拓展:

1、成员内部类中是否可以直接访问外部类的静态成员?

  • 可以,外部类的静态成员只有一份可以被共享访问。

2、成员内部类的实例方法中是否可以直接访问外部类的实例成员?

  • 可以的,因为必须先有外部类对象,才能有成员内部类对象,所以可以直接访问外部类对象的实例成员

局部内部类 [鸡肋语法,了解即可]

  • 局部内部类放在方法、代码块、构造器等执行体中。
  • 局部内部类的类文件名为: 外部类$N内部类.class。

    还不如独立写出来

匿名内部类[重点]

概述

  • 本质上是一个没有名字的局部内部类,定义在方法中、代码块中、等。
  • 作用:方便创建子类对象,最终目的是为了简化代码编写。

格式:

特点总结:

  • 匿名内部类是一个没有名字的内部类,同时也代表一个对象。
  • 匿名内部类产生的对象类型,相当于是当前new的那个的类型的子类类型

没使用匿名内部类 如果只是实现一个很简单的功能,(如下图左)Tiger只有一个跑的方法,当我们构建对象的时候就相对麻烦些。而使用匿名内部类可以很方便快速的构建一个对象,代码更加简洁。

匿名内部类常见使用形式

更加简化,既然go()方法接收的是实现类,那就直接把匿名内部类写在里面作为参数传进去

Lambda表达式

Lambda概述

  • Lambda表达式是JDK 8开始后的一种新语法形式。
  • 作用:简化匿名内部类的代码写法。

Lambda表达式的简化格式

什么是函数式接口?

  • 首先必须是接口、其次接口中有且仅有一个抽象方法的形式(就是只能是接口,且只能有一个抽象方法才可以)
  • 通常我们会在接口上加上一个@FunctionalInterface注解,标记该接口必须是满足函数式接口

体验Lambda表达式


Lambda实战-简化常见函数式接口

Lambda表达式简化Comparator接口的匿名形式

Comparator详见->05-1常用API 的Arrays类的排序方法

看到@FunctionalInterface注解就可以开始简化了

Lambda表达式的省略规则

Lambda表达式的省略写法(进一步在Lambda表达式的基础上继续简化)

  • 参数类型可以省略不写。
  • 如果只有一个参数,参数类型可以省略,同时()也可以省略。
  • 如果Lambda表达式的方法体代码只有一行代码。可以省略大括号不写,同时要省略分号!
  • 如果Lambda表达式的方法体代码只有一行代码。可以省略大括号不写。此时,如果这行代码是return语句,必须省略return不写,同时也必须省略";"不写

泛型

泛型的概述和优势

泛型概述

  • 泛型:是JDK5中引入的特性,可以在编译阶段约束操作的数据类型,并进行检查。
  • 泛型的格式:<数据类型>; 注意:泛型只能支持引用数据类型。
  • 集合体系的全部接口和实现类都是支持泛型的使用的。

泛型的好处:

  • 统一数据类型。
  • 把运行时期的问题提前到了编译期间,避免了强制类型转换可能出现的异常,因为编译阶段类型就能确定下来。

泛型可以在很多地方进行定义:

自定义泛型类

泛型类的概述

  • 定义类时同时定义了泛型的类就是泛型类。

  • 泛型类的格式:修饰符 class 类名<泛型变量>{ }

  • 此处泛型变量**T可以随便写为任意标识,常见的如E、T、K、V**等。

  • 作用:编译阶段可以指定数据类型,类似于集合的作用。

案例

  • 模拟ArrayList集合自定义一个集合MyArrayList集合,完成添加和删除功能的泛型设计即可。

泛型类的原理:

  • 把出现泛型变量的地方全部替换成传输的真实数据类型。

自定义泛型方法

泛型方法的概述

  • 定义方法时同时定义了泛型的方法就是泛型方法。

  • 泛型方法的格式:修饰符 <泛型变量> 方法返回值 方法名称(形参列表){}

  • 作用:方法中可以使用泛型接收一切实际类型的参数,方法更具备通用性。

案例

  • 给你任何一个类型的数组,都能返回它的内容。也就是实现Arrays.toString(数组)的功能!

泛型方法的原理:

  • 把出现泛型变量的地方全部替换成传输的真实数据类型。

自定义泛型接口

泛型接口的概述

  • 使用了泛型定义的接口就是泛型接口。

  • 泛型接口的格式:修饰符 interface 接口名称<泛型变量>{}

  • 作用:泛型接口可以让实现类选择当前功能需要操作的数据类型

案例

  • 教务系统,提供一个接口可约束一定要完成数据(学生,老师)的增删改查操作

泛型接口的原理:

  • 实现类可以在实现接口的时候传入自己操作的数据类型,这样重写的方法都将是针对于该类型的操作。

定义泛型接口后实现了要实现该接口就要传入指定的类型,重写内部方法就会按照泛型的约束把出现泛型变量的地方全部替换成传输的真实数据类型,实现类就能够根据真实数据类型执行指定的操作,接口更具有约束性,让代码更具有通用性。

泛型通配符、上下限

通配符:?

  • ? 可以在“使用泛型”的时候代表一切类型。
  • E T K V 是在定义泛型的时候使用的。

定义泛型,是在还没使用的时候,要定义的时候。

使用泛型,是已经用了泛型,要区分泛型使用哪种类型进行操作的时候使用。如图

案例

  • 开发一个极品飞车的游戏,所有的汽车都能一起参与比赛。

注意:

  • 虽然BMW和BENZ都继承了Car但是ArrayList和ArrayList与ArrayList没有关系的!!

使用通配符:?可以代表一切类型,但又出现一个问题,就是谁都可以放进来,如图 狗都可以和车一起跑

泛型的上下限:

  • ? extends Car: ?必须是Car或者其子类 泛型上限
  • ? super Car : ?必须是Car或者其父类 泛型下限(使用少)

使用泛型的上下限:? extends Car 就能规定只有Car或者Car的子类才能传进来


注:

该内容是根据B站黑马程序员学习时所记,相关资料可在B站查询:Java入门基础视频教程,java零基础自学就选黑马程序员Java入门教程(含Java项目和Java真题)

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值