面向对象
-
何为对象
- 在Java语言范畴中,我们都将功能、结构等封装到类中,通过类的实例化,来调用具体的功能结构
- Scanner,String等
- 文件:File
- 网络资源:URL
- 涉及到
Java
语言与前端html
、后端的数据库交互时,前后端的结构在Java
层面交互时,都体现为类、对象。
- 在Java语言范畴中,我们都将功能、结构等封装到类中,通过类的实例化,来调用具体的功能结构
-
面向对象学习的三条主线
- Java类及类的成员:属性、方法、构造器:代码块、内部类
- 面向对象的大特征:封装性、继承性、多态性、(抽象性)
- 其它关键字:
this
、super
、static
、final
、abstract
、interface
、package
、import
等
类的属性
-
类的属性和变量的区别
- 权限修饰符的不同属性:可以在声明属性时,指明其权限,使用权限修饰符。常用的权限修饰符:
private
、public
、缺省(default)
、protected
—>封装性
- 权限修饰符的不同属性:可以在声明属性时,指明其权限,使用权限修饰符。常用的权限修饰符:
-
默认初始化值的情况:类的属性,根据其类型,都有默认初始化值。
- 整型(
byte
、short
、int
、long
:0) -
浮点型(`float`、`double`:0.0)
- 字符型(
char
:0 (或'\u0000'
)) - 布尔型(
boolean
:false
) - 引用数据类型(类、数组、接口:
nul
l)
注意:局部变量没默认初始化值,意味着,我们在调用局部变量之前,一定要显式赋值。特别地:形参在调用时,我们赋值即可。
- 整型(
类的方法
类的方法:描述类应该具的功能。
-
方法的声明:权限修饰符 返回值类型 方法名(形参列表){
方法体
} -
return关键字
- 使用范围:使用在方法体中
- 作用:
- 结束方法
- 针对于返回值类型的方法,使用
return 数据
方法返回所要的数据。
- 注意点:return关键字后面不可以声明执行语句
-
方法的重载
-
定义:在同一个类中,允许存在一个以上的同名方法,只要它们的参数个数或者参数类型不同即可。
-
总结:“两同一不同”:同一个类、相同方法名参数列表不同:参数个数不同,参数类型不同.
-
代码举例
举例二: //如下的4个方法构成了重载 public void getSum(int i,int j){ System.out.println("1"); } public void getSum(double d1,double d2){ System.out.println("2"); } public void getSum(String s ,int i){ System.out.println("3"); } public void getSum(int i,String s){ System.out.println("4"); } 不构成重载的举例: //如下的3个方法不能与上述4个方法构成重载 // public int getSum(int i,int j){ // return 0; // } // public void getSum(int m,int n){ // // } // private void getSum(int i,int j){ // // }
注意:方法的重载跟方法的权限修饰符、返回值类型、形参变量名、方法体都没关系
-
可变个数的参数方法设置方法
-
可变个数形参的格式:数据类型 … 变量名
-
当调用可变个数形参的方法时,传入的参数个数可以是:0个,1个,2个,多个.
-
可变个数形参的方法与本类中方法名相同,形参不同的方法之间构成重载
-
可变个数形参的方法与本类中方法名相同,形参类型也相同的数组之间不构成重载。换句话说,二者不能共存。
-
可变个数形参在方法的形参中,必须声明在末尾
-
可变个数形参在方法的形参中,最多只能声明一个可变形参。
-
代码举例
public void show(int i){ } public void show(String s){ System.out.println("show(String)"); } public void show(String ... strs){ System.out.println("show(String ... strs)"); for(int i = 0;i < strs.length;i++){ System.out.println(strs[i]); } } //不能与上一个方法同时存在 public void show(String[] strs){ } //调用时: test.show("hello"); test.show("hello","world"); test.show(); test.show(new String[]{"AA","BB","CC"});
-
-
-
方法的重写
-
子类继承父类以后,可以对父类中同名同参数的方法,进行覆盖操作
-
重写以后,当创建子类对象以后,通过子类对象调用子父类中的同名同参数的方法时,实际执行的是子类重写父类的方法。
-
重写的规则:
-
方法的声明: 权限修饰符 返回值类型 方法名(形参列表) throws 异常的类型{
//方法体
}
-
子类重写的方法的方法名和形参列表与父类被重写的方法的方法名和形参列表相同
-
子类重写的方法的权限修饰符不小于父类被重写的方法的权限修饰符
-
子类不能重写父类中声明为private权限的方法
-
返回值类型:
- 父类被重写的方法的返回值类型是void,则子类重写的方法的返回值类型只能是void
- 父类被重写的方法的返回值类型是A类型,则子类重写的方法的返回值类型可以是A类或A类的子类
- 父类被重写的方法的返回值类型是基本数据类型(比如:double),则子类重写的方法的返回值类型必须是相同的基本数据类型(必须也是double)
- 子类重写的方法抛出的异常类型不大于父类被重写的方法抛出的异常类型
-
-
代码举例
class Circle{ public double findArea(){}//求面积 } class Cylinder extends Circle{ public double findArea(){}//求表面积 } // *************** class Account{ public boolean withdraw(double amt){} } class CheckAccount extends Account{ public boolean withdraw(double amt){} }
-
-
重载和重写的区别
重载,是指允许存在多个同名方法,而这些方法的参数不同。
编译器根据方法不同的参数表,对同名方法的名称做修饰。
对于编译器而言,这些同名方法就成了不同的方法。
它们的调用地址在编译期就绑定了。
Java的重载是可以包括父类和子类的,即子类可以重载父类的同名不同参数的方法。
所以:对于重载而言,在方法调用之前,编译器就已经确定了所要调用的方法,这称为**“早绑定”或“静态绑定”;**而对于多态,只等到方法调用的那一刻,解释运行器才会确定所要调用的具体方法,这称为“晚绑定”或“动态绑定”。
-
java的值传递机制
-
规则:
- 如果变量是基本数据类型,此时赋值的是变量所保存的数据值。
- 如果变量是引用数据类型,此时赋值的是变量所保存的数据的地址值。
-
形参:方法定义时,声明的小括号内的参数
-
实参:方法定义时,声明的小括号内的参数
-
-
递归方法:一个方法体内调用它自身
-
方法递归包含了一种隐式的循环,它会重复执行某段代码,但这种重复执行无须循环控制。
-
递归一定要向已知方向递归,否则这种递归就变成了无穷递归,类似于死循环。
-
代码举例
// 例1:计算1-n之间所自然数的和 public int getSum(int n) {// 3 if (n == 1) { return 1; } else { return n + getSum(n - 1); } } // 例2:计算1-n之间所自然数的乘积:n! public int getSum1(int n) { if (n == 1) { return 1; } else { return n * getSum1(n - 1); } } //例3:已知一个数列:f(0) = 1,f(1) = 4,f(n+2)=2*f(n+1) + f(n), //其中n是大于0的整数,求f(10)的值。 public int f(int n){ if(n == 0){ return 1; }else if(n == 1){ return 4; }else{ // return f(n + 2) - 2 * f(n + 1); return 2*f(n - 1) + f(n - 2); } }
-
类的封装性
-
类的封装性—权限具体修饰范围
4种权限都可以用来修饰类的内部结构:属性、方法、构造器、内部类
修饰类的话,只能使用:缺省、public -
封装性的体现:
- 将类的属性xxx私化(private),同时,提供公共的(public)方法来获取(getXxx)和设置(setXxx)此属性的值
- 不对外暴露的私有的方法
- 单例模式(将构造器私有化)
- 如果不希望类在包外被调用,可以将类设置为缺省的。
类的继承性
- java中继承的说明:
- 一个类可以被多个子类继承。
- Java中类的单继承性:一个类只能有一个父类
- 子父类是相对的概念。
- 子类直接继承的父类,称为:直接父类。间接继承的父类称为:间接父类
- 子类继承父类以后,就获取了直接父类以及所间接父类中声明的属性和方法
- 如图:
java.lang.Object
类的理解- 如果我们没显式的声明一个类的父类的话,则此类继承于
java.lang.Object
类 - 所有的java类(除
java.lang.Object
类之外都直接或间接的继承于java.lang.Object
类 - 即,所的java类具有
java.lang.Object
类声明的功能。
- 如果我们没显式的声明一个类的父类的话,则此类继承于
类的构造器(或构造方法):Constructor
-
构造器的作用
- 创建对象
- 初始化对象的信息
-
使用说明:
- 如果没显式的定义类的构造器的话,则系统默认提供一个空参的构造器
- 定义构造器的格式:权限修饰符 类名(形参列表){}
- 一个类中定义的多个构造器,彼此构成重载
- 一旦我们显式的定义了类的构造器之后,系统就不再提供默认的空参构造器
- 一个类中,至少会有一个构造器。
-
代码举例
//构造器 public Person(){ System.out.println("Person()....."); } public Person(String n){ name = n; } public Person(String n,int a){ name = n; age = a; }
部分关键字的说明 this/package/import
- this
- this理解为:当前对象 或 当前正在创建的对象
- this调用属性和方法
- 在类的方法中,我们可以使用"this.属性"或"this.方法"的方式,调用当前对象属性或方法。但是,通常情况下,我们都择省略"this."。特殊情况下,如果方法的形参和类的属性同名时,我们必须显式的使用"this.变量"的方式,表明此变量是属性,而非形参。
- 在类的构造器中,我们可以使用"this.属性"或"this.方法"的方式,调用当前正在创建的对象属性或方法。但是,通常情况下,我们都择省略"this."。特殊情况下,如果构造器的形参和类的属性同名时,我们必须显式的使用"this.变量"的方式,表明此变量是属性,而非形参。
- this调用构造器
- 我们在类的构造器中,可以显式的使用"this(形参列表)"方式,调用本类中指定的其他构造器
- 构造器中不能通过"this(形参列表)"方式调用自己
- 如果一个类中有n个构造器,则最多有 n - 1构造器中使用了"this(形参列表)"
- 规定:"this(形参列表)"必须声明在当前构造器的首行
- 构造器内部,最多只能声明一个"this(形参列表)",用来调用其他的构造器
- package
- 使用说明
- 为了更好的实现项目中类的管理,提供包的概念
- 使用package声明类或接口所属的包,声明在源文件的首行
- 包,属于标识符,遵循标识符的命名规则、规范(xxxyyyzzz)、“见名知意”
- 每"."一次,就代表一层文件目录。
- 举例:MVC设计模式
- JDK中主要的包[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-xiBkonM6-1598227998494)(C:\Users\Night\AppData\Roaming\Typora\typora-user-images\image-20200824002510567.png)]
- 使用说明
- import
- 在源文件中显式的使用import结构导入指定包下的类、接口
- 声明在包的声明和类的声明之间
- 如果需要导入多个结构,则并列写出即可
- 可以使用"xxx.*"的方式,表示可以导入xxx包下的所结构
- 如果使用的类或接口是java.lang包下定义的,则可以省略import结构
- 如果使用的类或接口是本包下定义的,则可以省略import结构
- 如果在源文件中,使用了不同包下的同名的类,则必须至少一个类需要以全类名的方式显示。
- 使用"xxx.*"方式表明可以调用xxx包下的所结构。但是如果使用的是xxx子包下的结构,则仍需要显式导入
- **import static:**导入指定类或接口中的静态结构:属性或方法。
- super
- 关键字可以理解为:父类的
- 可以用来调用的结构:属性、方法、构造器
- 和
this
关键字类比即可
对象的创建和内存解析
如果创建了一个类的多个对象,则每个对象都独立的拥有一套类的属性。(非static的)
意味着:如果我们修改一个对象的属性a,则不影响另外一个对象属性a的值。
Person p1 = new Person();
Person p2 = new Person();
Person p3 = p1;//没有新创建一个对象,共用一个堆空间中的对象实体。
匿名对象
匿名对象:我们创建的对象,没显式的赋给一个变量名。即为匿名对象
特点:匿名对象只能调用一次。(好像没什么特别的作用,就是减少代码量)
代码举例
new Phone().sendEmail();
new Phone().playGame();
new Phone().price = 1999;
new Phone().showPrice();//0.0
// 应用场景:
PhoneMall mall = new PhoneMall();
//匿名对象的使用
mall.show(new Phone());
//其中
class PhoneMall{
public void show(Phone phone){
phone.sendEmail();
phone.playGame();
}
}
一个变量名。即为匿名对象
特点:匿名对象只能调用一次。(好像没什么特别的作用,就是减少代码量)
代码举例
new Phone().sendEmail();
new Phone().playGame();
new Phone().price = 1999;
new Phone().showPrice();//0.0
// 应用场景:
PhoneMall mall = new PhoneMall();
//匿名对象的使用
mall.show(new Phone());
//其中
class PhoneMall{
public void show(Phone phone){
phone.sendEmail();
phone.playGame();
}
}