OOP-2

二维数组

基本概念

一维数组本质上就是一段连续的内存空间,用于存放多个类型相同的数据。
二维数组本质就是由一维数组组成的数组,也就是说每个元素都是一个一位数组。

声明方式

<1>语法格式
数据类型[][] 变量名 = new 数据类型[m][n];

	m:表示这个二维数组由多个个一位数组
	n:表示每一个一维数组的元素个数
	比如:
		int[][] arr = new int[2][3]; - 表示声明一个具有23列的二维数组
arr代表什么?  arr[0]代表什么?  arr[0][0]代表什么?
		arr代表数组的名称,也就是用于记录该数组内存空间的首地址
		arr[0] 代表二维数组中的第一行,也就是一个一维数组
		arr[0][0] 代表二维数组中下标为00列的元素,也就是第一个一维数组中的第一个元素。
		arr.length 代表二维数组的大小,也就是二维数组的行数。
		arr[0].length代表就是二维数组中第一行的大小,也就是一维数组的大小,也就是列数

<2>二维数组的初始化
数据类型[][] 数组名称 = {{初始值},{初始值2},{初始值3}};

int[][] arr = {{1,3,5,7},{2,4,6},{8,9,10,11,15}}; 

Java的JVM的内存可以分为3个区:堆区、栈区、方法区

堆区

1.存储的全部是对象,每个对象都包含一个与之对应的class信息。(class的目的是得到操作指令)
2.jvm只有一个堆区被所有线程共享,堆中不存放基本数据类型和对象引用,之存放对象本身。

栈区

1.栈中只保存基础数据类型的对象和自定义对象的引用(不是对象),对象都存放在堆区中
2.每个栈区中的数据(原始类型和对象引用)都是私有,其他栈不能访问。
3.栈分为3个部分:基本类型变量区、执行环境上下文、操作指令区

方法区

1.方法区又叫做静态区,和堆一样,被所有线程共享,方法区包含所有的class和static变量。
2.方法区包含的都是在整个过程中永远唯一的元素,如:class,static变量

访问控制修饰符

常见的访问控制

  1. public - 公开的 公开的,任何类
  2. protected - 保护的 本类,派生类,同包类
  3. 默认方式 - 默认的 本类,同包类
  4. private - 私有的 本类

注:1>类的访问修饰符只能是Public或默认的
2>类中成员的访问修饰符以上四种都可以
3>通常情况下,所以的成员变量都用private修饰,所有的成员方法都用public修饰。
4>public修饰的内容表示可以在任意位置进行访问;
5>private修饰的内容只能在本类的内部进行访问。

包的定义

package 包名; - 表示创建单层包
package 包名1.包名2.....包名n - 表示创建多层包,也就是多层目录;
		为了管理文件方便,避免文件同名引起的冲突。

封装

基本概念

通常情况下在测试类中可以给成员变量赋值一些合法但不合理的数值,而程序的执行过程无法检测和提示,和我们的现实有点不太符合。
为了避免上述情况的发生,就需要对成员变量的赋值操作进行合理性的判断和提示,该方式就叫做封装,通俗的来说,封装就是一种保证我们成员变量值合理的机制。

封装的流程

(1)私有化成员变量,使用private关键字修饰;
(2)提供共有的get成员变量和set成员变量的方法,在方法体中进行合理的判断。
(3)在构造方法体中调用set成员变量进行合理值得判断

static 关键字

基本概念

通过情况下成员变量都隶属于对象层级,每个对象都拥有独立的内存空间来记录自己独有的成员变量,当所有的对象的成员变量值都完全一样的时候,若每个对象单独记录则会造成内存空间的浪费,此时应该将该成员变量有对象层级提升到类层级,在内存空间中只保留一份而且被所有的对象所共享,为了实现该效果使用static关键字来进行修饰,表示静态的含义。
static关键字可以修饰成员变量和成员方法表示隶属于类层级,推荐使用类名.的方式访问

使用方式

  1. 对于非静态的成员方法来说,既可以访问非静态的成员同时也可以访问静态的成员;(成员:成员变量+成员方法)
  2. 对于静态的成员方法来说,只能访问静态的成员不能访问非静态的成员;(执行静态方法时候可以还没有创建对象,非静态成员隶属于对象层级)
  3. 只有被所有对象共享的内容才能加static。static不能随便加。

继承

基本概念

当多个类之间有相同的特征和行为的时候,就可以将相同的内容提取出来组成一个新类,让原来的这些继承自新类就可以了,从而实现原来的这些类吸收新类中的成员的效果,此时在原来这些类中只需要编写自己独有的成员即可。

换一句话来说,继承就是一种用于提高代码复用性、可维护性以及可扩展性的机制。
在Java语言中使用extends关键字来代表继承的关系。

比如:
	class Student extends Person{  } --- 表示Student类继承自Person
	其中Person 类叫做超类/父类/基类
	其中Student类叫做  子类/孩子类/派生类

注意事项

  1. 子类可以继承父类中的成员变量,包括私有的成员变量,但不能直接访问;
  2. 子类不可以继承父类中的构造方法以及私有的成员方法。
  3. 构造子类对象时候会自动调用父类中的无参构造方法,用于初始化从父类中继承下来的成员变量信息,相当于在子类构造方法中的第一行增加代码:super();
  4. 在java语言中只支持单继承,也就是一个子类只能有一个父类,但一个父类可以有多个子类;
  5. 只有满足:子类 is a 父类的逻辑关系才能用继承,不能滥用继承;

final关键字

final本意为"最终的",无法更改的。可以修饰类、成员方法以及成员变量
1.final修饰类 表示该类不能被继承
2.final修饰方法 表示该方法不能被重写
3.final修饰变量 表示该变量不能被改变

补充:
	在Java语言中很少单独使用static关键字还有final关键字,通常使用 public static final 共同修饰成员变量来表示常量的概念,常量的命名规则是:所有字母都是大写,不同的单词之间使用下划线连接。

	例如:
		public static final double PI = 3.14;

创建对象的过程

单个对象创建的过程

  1. 将xxx.class文件中相关类信息读取到内存空间的方法区,这个过程叫做类的加载。
  2. 当程序开始运行时找main()方法去执行方法体中的语句,使用new来创建对象。
  3. 若没有执行初始值采用默认初始化,否则采用执行的数值来作为初始化。
  4. 可以通过构造块来更改成员变量的数值。
  5. 执行构造方法体中的语句可以再次修改成员变量的数值。
  6. 此时对象创建完毕,继续执行后续的语句。

子类对象创建的过程

1.先加载父类再去加载子类,先执行父类的静态语句块,在执行子类的静态语句块;
2.执行父类的构造块,在执行父类的构造方法体,此时父类部分构造完毕。
3.执行子类的构造块,在执行子类的构造方法体,此时子类对象构造完毕;

多态

基本概念

多态就是指同一种事物表现出来的多种形态。
C++多态分为两种:编译多态、运行时多态
Java中的多态只有一种,就是运行时多态。是一种运行期间的行为,而不是编译期的行为。

语法格式

父类类型 引用 = new 子类类型();

Person p = new Student();
p.show();

解析:
	在编译阶段p是Person类型,因此调用Person类自己的show()方法,若没有则编译的时候就报错。
	在运行阶段p真正指向的对象是Student类型,因此最终调用的是Student类中自己的show()方法。

当使用多态方式调用方法的时候,首先会检查父类中是否有该方法,如果没有,则编译报错。
如果有,再去调用子类的同名方法。(注意:静态static方法属于特殊情况,静态方法只能继承,不能重写override,如果
子类中定义了同名同形式的静态方法,它对父类方法只能起到隐藏的作用。调用的时候用谁的引用,则调用谁的版本。)

多态存在的三个比较条件

1.要有继承
2.要有重写
3.父类引用指向子类对象

多态的效果

  1. 对于指向子类对象的父类来说,在编译期间只能调用父类的方法,不能直接调用子类的方法。
  2. 对于父子类都有的非静态方法来说,最终调用子类中的重写版本。
  3. 对于父子类中都有的静态方法来说 ,最终调用父类中的版本,与指向的对象类型无关。

引用类型之间的转换

基本概述

1.引用类型之间的转换必须发生在父子类之间,分为自动类型转换(向上转换)和强制类型转换(向下转换)
2.向上转换(子类类型向父类类型的转换)
父类引用指向子类对象: Person p = new Student();
把一个子类对象转换为父类对象,向上转型(自动转型、隐式转型),代码中是父类引用指向子类的对象,父类
引用指向类型实例,可以调用子类重写父类的方法以及父类派生的方法,无法调用子类独有的方法。

注意:
父类中的静态方法无法被子类重写,所以向上转型之后只能调用父类原有的静态方法。

3.向下转换(父类类型向子类类型的转换)
子类引用指向父类实例,必须进行强制类型转换,可以调用子类特有的方法。
instanceof 运算符可以进行判断,左边的对象是否是他右边对象的实例,换句话来说就是左侧对象是否满足右侧对象类型的特征如果是返回true
if(p instanceof Teacher){}
父类中的静态方法(含有static修饰的方法,只能被子类继承使用无法被子类重写)。
4.当没有父子类关系发生强制类型转换则编译报错,当拥有父子类关系发生强制转换是编译通过,若目标类型并不是该引用真正指向的类型时,在运行阶段发生类型转换异常。
5.为了避免上述错误的发生,通常只要进行强制类型转换就需要进行判断,格式如下:
if(引用变量名 instanceof 数据类型){}
- 判断引用指向的对象是否为指定的数据类型,若是则返回true,否则返回false;

多态的实际意义

多态的意义在于:可以屏蔽不同子类的差异性编写通用的代码,从而产生不同的效果。

抽象类

抽象方法

抽象方法就是指不能被具体实现的方法,也就是没有方法体,并且使用abstract关键字修饰;

语法格式:
	访问修饰符   abstract  void  show();

抽象类

  1. 由abstract修饰
  2. 包含抽象方法的类必须是抽象类
  3. 抽象类不能被实例化
  4. 抽象类是需要被继承的,派生类:
    1> 重写抽象类中所有抽象方法,一变不完整为完整
    2>也可以声明为抽象类
抽象类的意义

1.封装派生类所共有的属性和行为
2.为所有的派生类提供统一的类型
3.可以包含抽象方法,为所有派生类提供统一的入口(造型之后通过超类引用能点出来)
派生类的具体实现不同,但入口是一致的(真正调用的还是派生类重写之后的)

抽象总结

抽象关键字  abstract    ,当abstract修饰类,就是抽象类,抽象类不能被实例化,
当 abstract 修饰方法抽象方法没有方法体,继承抽象类,必然要重写抽象方法。

接口

基本概述

接口就是一种比抽象类还抽象的类,该类型不能实例化对象。

是一种引用类型
由interface定义
只能包含常量和抽象方法
接口不能被实例化
接口是需要被实现/继承的,实现类/派生类,必须重写所有抽象方法
一个类可以实现多个接口,用逗号分隔,若又继承又实现,先继承后实现
接口可以继承接口
定义类的关键字是class   而定义接口的关键字是interface
继承类的关键字是extends,而实现接口的关键字是implements

语法格式

修饰符 interface 接口名称 [extends 父接口1,父接口2,…] {
零个到多个常量的定义…
零个到多个抽象方法的定义…
零个到多个默认方法定义…(jdk1.8新特性)
零个到多个静态方法的定义…(jdk1.8新特性)
}

注意事项

	1.接口可以实现多继承,也就是说一个接口可以同时继承多个父接口。
	2.实现接口的类如果不能实现所有接口中待重写的方法,则必须设置为抽象类。
	3.一个类可以继承自一个父类,同时实现多个接口。
	4.接口中的所有成员变量都必须有public static final共同修饰,也就是常量。
	5.接口中所有成员方法必须有public abstract共同修饰,也就是抽象方法。

类和接口之间关系

类和类之间采用继承的关系    	使用extends关键			支持单继承
类与接口之间采用实现的关系		使用implements关键字  	支持多实现
接口与接口之间采用继承的关系	使用extends关键字			通常认为支持单继承

接口中的常量为什么必须使用public static final修饰

public 作用修饰符公开的,也就是说接口的实现类可以使用这个变量。

static 修饰就是表示类的,随着类的加载而存在的
如果不是static的话,就表示属于对象的,只有创建对象才能有它,而接口是不能创建对象的,所以接口的常量定义必须为static。

final 修饰就是保存接口定义的常量不能被实现类去修改,如果没有final的话,由子类随意修改,接口建立常量将没有意义了。

内部类

基本概述

当一个类的定义放在另一个类的实体时,则该类叫做内部类,该类所在的类叫做外部类。
在一个类体中可以出现的内容:成员变量、成员方法、构造方法、构造块、静态语句块、静态变量、方法、内部类。

嵌套类:
内部类(成员内部类、局部内部类、匿名内部类)
静态嵌套类

语法格式

class 外部类类名{
	class 内部类类名{
		内部类的类体;
	}
}

成员内部类

成员内部类定义在另一个类或接口中的内部类

注意事项:
1.必须先创建外部类对象才能创建成员内部类对象
2.不能含有静态变量、静态代码块、静态方法(除了静态常量)
3.外部类可通过成员内部类的对象调用内部类私有成员
4.成员内部类是一个独立的类,编译成独立的.class文件
作用: 成员内部类既可以访问外部类信息,又可以访问父类信息,从而使多继承的解决方案变得完整。

局部内部类

局部内部类是定义在方法或代码块里的内部类

注意事项:
1.不能含有静态变量、静态代码块、静态方法

2.只能在定义该类的方法或代码块中使用,必须在使用前定义

3.防伪码它所有方法的局部变量的时候,局部变量必须是有效的常量。

4.是一个独立的类,编译成独立的.class文件	

5.只能使用abstract、final修饰

6.定义静态块或方法时候,只能访问外部类的静态成员。

匿名内部类

匿名内部类是直接使用接口或父类实例化对象时创建没有名字的内部类。

语法格式:
	接口/父类类型  引用名 = new 接口/父类类型(){
		进行方法的重写;
	};

注意事项:
1.必须且仅能继承一个父类或实现一个接口
2.没有class关键字,没有类名
3.是特殊的局部内部类
4.仅能使用一次
5.不能定义构造方法
6.匿名类不能是抽象类

优点以及作用:
匿名内部类可以使我们的代码更加紧凑,简洁、封装性比较好
匿名内部类可以灵活的创建
匿名内部类使用多继承的解决方案比较完整

静态嵌套类

静态嵌套类定义在另一个类、接口,使用static关键字修饰的嵌套类

注意事项:
1.不需要通过生成外部类对象来生成静态嵌套类对象
2.只能直接访问外部类的静态成员
3.外部类可通过静态嵌套类的对象调用内部类的成员
4.可以定义静态成员变量或静态成员方法。

静态嵌套类和非静态嵌套类的区别

	名称				内部类(非静态嵌套类)			静态嵌套类

	定义位置上		成员位置、方法、代码块			只能在外部类的成员位置
	组成				实例成员、静态常量、构造方法	实例成员、静态成员、静态代码块、方法
	对象创建			必须先有外部类对象			不依赖于外部类实例,可以直接实例化
	访问外部类		可以直接访问外部类所有成员		只能直接访问外部类的静态成员

Object类

Java中常用的包

java.lang包 - 该包是java语言的核心包,该包重的所有内容由Java虚拟机自动导入;

如:java.lang.String 类/System类等.......
java.util包 
- 该包是java语言的工具包,里面提供了大量的工具类和集合等内容。
- 如:java.util.Scanner类/Random类、Arrays类等....
- java.io包	
-该包是java语言的输入输出包,里面提供了大量读写文件的相关类。
-:java.io.PrintStream/InputStream
java.net包
- 该包是java语言的网络包,里面提供了大量网络通信相关的类的内容。
- 如:java.net.ServerSocket类/Socket类等......
java.lang.reflect包
-该包是java语言的反射包,里面提供了一些反射相关的类。

基本概述

java.lang.Object类是所有类层次结构的根类,任何类都是该类的直接/间接子类。

常用的方法

boolean equals(Object obj) - 用于判断调用对象是否与参数对象相同
- 该方法默认比较两个对象的地址,与 == 的效果等效
- 若希望比较对象的内容,则需要进行方法的重写。
- 若该方法重写了,则应该去重写hasCode()方法,为了满足hasCode()常规协定。

int hashCode() - 用于获取调用对象的哈希码值(内存地址和编号)并返回。
			   - 若两个对象调用equals()方法相等,则各自调用该方法得到的哈希码值值必须相同。
			   - 若两个对象调用equals()方法不同等,则各自调用改方法的结果可以相同。
				但是最高不相同

String toString() - 用于返回调用对象的字符串表现形式。
			- 默认返回字符串是: 包名.类型 @ 哈希码的无符号十六进制形式。
			- 若希望返回其他内容,则需要进行方法的重写。
			- 当使用print()/println()打印引用变量的时候,会自动调用toString()方法
			- 当使用字符串和引用变量进行拼接(+)时,会自动调用toString()方法。
			- 可以自动生成toString()方法

包装类

基本概述

在某些场合要求所有的数据内容都必须是类类型的对象,而Java语言中有8中基本数据类型声明的遍历都不是对象,
为了使得这些数据在该场合中能够使用,则需要进行对象化处理,此时就需要借助包装类将变量包装成对象在进行使用。

Integer类型

java.lang.Integer类是Object类的间接子类,用于包装int类型的数据。
该类由final关键字修饰,表示该类不能被继承。

常用方法
	该类重写了Object类的equals()hashCode()以及toString()方法
	Integer(int value) 
	- 根据参数指定的整数值来构造对象
	Integer(String s)  
	- 根据参数指定的字符串来构造对象
	int intValue() 
	- 用于获取调用对象中含有的int类型数据并返回
	- 用于实现将Integer类型拆包为int类型
	static Integer valueOf(int i)  
	- 根据参数指定的整数来得到对象
	- 用于实现将int类型包装成Integer类型 
	static int parseInt(String s) 
	 - 用于将字符串类型的数据转换为int类型的整数

装箱和拆箱

由int类型向Integer类型的转换过程,叫做装箱
由Intger类型向int类型的转换过程,叫做拆箱
从jdk1.5开始,支持自动装箱和自动拆箱的机制。

自动装箱池

为了提高性能在Integer类的内部提供了自动装箱池,也就是把-128 ~ 127之间的整数提前装箱完毕,若程序中需要,该范围内的数据则直接从装箱池中获取无需创建新对象。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值