目录
1.通过this关键字调用成员变量,解决与局部变量名称冲突问题。
面向对象概述
面向对象则是把构成问题的事务按照一定规则划分为多个独立的对象,然后通过调用对象的方法来解决问题。一个应用程序会包含多个对象,通过多个对象的相互配合即可实现应用程序所需的功能,这样当应用程序功能发生变动时,只需要修改个别的对象就可以了,这使得代码更容易得到维护。
1.封装
封装是面向对象的核心思想,将对象的属性和行为封装起来,不需要让外界知道具体实现细节,这就是封装思想。
例如,用户使用电脑,只需要使用手指敲键盘就可以了,无需知道电脑内部是如何工作的,即使用户可能碰巧知道电脑的工作原理,但在使用时,并不完全依赖电脑工作原理这些细节。
2.继承
在Java中,类的继承是指在一个现有类的基础上去构建一个新的类,构建出来的新类被称作子类,现有类被称作父类或基类,子类会自动拥有父类所有可继承的属性和方法。
继承不仅增强了代码的复用性、提高开发效率,还为程序的维护补充提供了便利。
例如,有一个汽车的类,该类中描述了汽车的普通属性和功能,而轿车的类中不仅应该包含汽车的属性和功能,还应该增加轿车特有的属性和功能,这时,可以让轿车类继承汽车类,在轿车类中单独添加轿车特有的属性和功能就可以了。
3.多态
多态指的是在一个类中定义的属性和功能被其他类继承后,当把子类对象直接赋值给父类引用变量时,相同引用类型的变量调用同一个方法所呈现出的多种不同行为特性。
例如,当听到“Cut” 这个单词时,理发师的行为表现是剪发,演员的行为表现是停止表演等。不同的对象,所表现的行为是不一样的。
4.类与对象的关系
让程序中对事物的描述与该事物在现实中的形态保持一致。类是对某一类事物的抽象描述,而对象用于表示现实中该类事物的个体。
5.类的定义
1.类的定义格式
Java中的类是通过class关键字来定义的,其语法格式如下:
[修饰符] class 类名 [extends 父类名] [implements 接口名]{ // 类体,包括类的成员变量和成员方法 }
2.声明(定义)成员变量
类的成员变量也被称作类的属性,它主要用于描述对象的特征。
声明(定义)成员变量的语法格式如下: [修饰符] 数据类型 变量名 [ = 值];
3.声明(定义)成员方法
成员方法也被称为方法,类似于C语言中的函数,它主要用于描述对象的行为。
[修饰符] [返回值类型] 方法名([参数类型 参数名1,参数类型 参数名2,...]){ //方法体 ... return 返回值; //当方法的返回值类型为void时,return及其返回值可以省略 }
● 修饰符:方法的修饰符比较多,有对访问权限进行限定的(如public、protected、private),有静态修饰符static,还有最终修饰符final等,这些修饰符在后面的学习过程中会逐步讲解。
● 返回值类型:用于限定方法返回值的数据类型,如果不需要返回值,可以使用void关键字。
● 参数类型:用于限定调用方法时传入参数的数据类型。
● 参数名:是一个变量,用于接收调用方法时传入的数据。
● return关键字:用于结束方法以及返回方法指定类型的值,当方法的返回值类型为void时,return及其返回值可以省略。
● 返回值:被return语句返回的值,该值会返回给调用者。
6.对象的创建与使用
应用程序想要完成具体的功能,仅有类是远远不够的,还需要根据类创建实例对象。在Java程序中,可以使用new关键字来创建对象,具体语法格式如下:
类名 对象名称 = new 类名();
例如,创建Person类的实例对象代码如下:
Person p = new Person();
上面的代码中,“new Person()”用于创建Person类的一个实例对象,“Person p”则是声明了一个Person类型的变量p,中间的等号用于将Person对象在内存中的地址赋值给变量p,这样变量p便持有了对象的引用。
在创建Person对象时,程序会占用两块内存区域,分别是栈内存和堆内存。其中Person类型的变量p被存放在栈内存中,它是一个引用,会指向真正的对象;通过new Person()创建的对象则放在堆内存中,这才是真正的对象。
在创建Person对象后,可以通过对象的引用来访问对象所有的成员,具体格式如下:
对象引用.对象成员
public class Example02 { public static void main(String[] args) { Person p1 = new Person(); // 创建第一个Person类对象 Person p2 = new Person(); // 创建第二个Person类对象 p1.age = 18; // 为age属性赋值 p1.speak(); // 调用对象的方法 p2.speak(); } }
p1、p2分别引用了Person类的两个实例对象。从图2可以看出,p1和p2对象在调用speak()方法时,打印的age值不同。这是因为p1对象和p2对象是两个完全独立的个体,它们分别拥有各自的age属性,对p1对象的age属性进行赋值并不会影响到p2对象age属性的值。
直接使用创建的对象本身来引用对象成员,具体格式如下:
new 类名().对象成员
这种方式是在通过new关键字创建实例对象的同时就访问了对象的某个成员,并且在创建后只能访问其中某一个成员,而不能像对象引用那样可以访问多个对象成员。同时,由于没有对象引用的存在,在完成某一个对象成员的访问后,该对象就会变成垃圾对象。所以,在实际开发中,创建实例对象时多数会使用对象引用。
成员变量类型 | 初始值 |
---|---|
byte | 0 |
short | 0 |
int | 0 |
long | 0 |
float | 0.0 |
double | 0.0 |
char | 空字符,'\u0000' |
boolean | false |
引用数据类型 | null |
垃圾对象
当没有任何变量引用这个对象时,它将成为垃圾对象,不能再被使用。接下来通过两段程序代码来分析对象是如何成为垃圾的。
第一段程序代码:
{ Person p1 = new Person(); ...... }
上面的代码中,使用变量p1引用了一个Person类型的对象。当这段代码运行完毕时,变量p1就会超出其作用域而被销毁,这时Person类型的对象将因为没有被任何变量所引用而变成垃圾。
第二段程序代码:
{ Person p2 = new Person(); ...... p2 = null; ...... }
上面的代码中,使用变量p2引用了一个Person类型的对象,接着将变量p2的值置为null,则表示该变量不指向任何一个对象,被p2所引用的Person对象就会失去引用,成为垃圾对象,
7.访问控制符
针对类、成员方法和属性提供了四种访问级别,分别是private、default、protected和public。四种控制级别由小到大依次列出
● private(当前类访问级别):如果类的成员被private访问控制符来修饰,则这个成员只能被该类的其他成员访问,其他类无法直接访问。类的良好封装就是通过private关键字来实现的。
● default(包访问级别):如果一个类或者类的成员不使用任何访问控制符修饰,则称它为默认访问控制级别,这个类或者类的成员只能被本包中的其他类访问。
● protected(子类访问级别):如果一个类的成员被protected访问控制符修饰,那么这个成员既能被同一包下的其他类访问,也能被不同包下该类的子类访问。
● public(公共访问级别):这是一个最宽松的访问控制级别,如果一个类或者类的成员被public访问控制符修饰,那么这个类或者类的成员能被所有的类访问,不管访问类与被访问类是否在同一个包中。
访问范围 | private | default | protected | public |
---|---|---|---|---|
同一类中 | √ | √ | √ | √ |
同一包中 | √ | √ | √ | |
子类中 | √ | √ | ||
全局范围 | √ |
8.类的封装
类的封装,是指将对象的状态信息隐藏在对象内部,不允许外部程序直接访问对象的内部信息,而是通过该类所提供的方法来实现对内部信息的操作访问。
定义一个类时,将类中的属性私有化,即使用private关键字来修饰,私有属性只能在它所在类中被访问,如果外界想要访问私有属性,需要提供一些使用public修饰的公有方法,其中包括用于获取属性值的getXxx()方法和设置属性值的setXxx()方法。
9.方法的重载和递归
重载
方法重载指同一个类中定义的多个方法之间的关系,满足下列条件的多个方法相互构成重载:
-
多个方法在同一个类中
-
多个方法具有相同的方法名
-
多个方法的参数不相同,类型不同或者数量不同
2.方法重载特点
-
重载仅对应方法的定义,与方法的调用无关,调用方式参照标准格式
-
重载仅针对同一个类中方法的名称与参数进行识别,与返回值无关,换句话说不能通过返回值来判定两个方法是否相互构成重载
public class MethodDemo { public static void main(String[] args) { //调用方法 //1. int result1=sum(10,20); System.out.println(result1); //2. double result2=sum(10.0,20.0); System.out.println(result2); //3. int result3=sum(10,10,20); System.out.println(result3); } //1.求两个int类型数据和的方法 public static int sum(int a,int b) { //方法体 return a+b; } //2.求两个double类型数据和的方法 public static double sum(double a,double b) { //方法体 return a+b; } //3.求三个int类型数据和的方法 public static int sum(int a,int b,int c) { //方法体 return a+b+c; } }
递归
递归是基于函数调用栈的原理实现的。当一个方法被调用时,会在调用栈中创建一个对应的栈帧,包含方法的参数、局部变量和返回地址等信息。在递归中,方法会在自身的定义中调用自身,这会导致多个相同方法的栈帧依次入栈。当满足终止条件时,递归开始回溯,栈帧依次出栈,方法得以执行完毕。
递归的关键是定义好递归的终止条件和递归调用的条件。如果没有适当的终止条件或递归调用的条件不满足,递归可能会陷入无限循环,导致栈溢出错误。
public class Factorial { public static int factorial(int n) { // 终止条件 if (n == 0) { return 1; } // 递归调用 return n * factorial(n - 1); } public static void main(String[] args) { int n = 5; int result = factorial(n); System.out.println("Factorial of " + n + " is: " + result); } }
优点
-
简化问题:递归能够将复杂问题分解成更小规模的子问题,简化了问题的解决过程。
-
提高代码可读性:递归能够直观地表达问题的解决思路,提高了代码的可读性。
-
实现高效算法:递归在某些算法中能够实现高效的解决方法,如分治法等。
缺点
-
栈溢出风险:递归可能导致方法调用栈过深,造成栈溢出错误。
-
性能损耗:递归调用需要创建多个栈帧,对系统资源有一定的消耗。
-
可能造成代码难以理解:递归的使用需要谨慎,过度使用可能使代码难以理解和调试。
10.构造方法
[修饰符] 方法名 ([参数列表]){ // 方法体 }
① 方法名与类名相同。
② 在方法名的前面没有返回值类型的声明。
③ 在方法中不能使用return语句返回一个值,但是可以单独写return语句来作为方法的结束。
与普通方法一样,构造方法也可以重载,在一个类中可以定义多个构造方法,只要每个构造方法的参数类型或参数个数不同即可。在创建对象时,可以通过调用不同的构造方法来为不同的属性进行赋值。
11.this关键字
1.通过this关键字调用成员变量,解决与局部变量名称冲突问题。
class Person { int age; // 成员变量age public Person(int age) { // 局部变量age this.age = age; // 将局部变量age的值赋给成员变量age } }
2.通过this关键字调用成员方法
class Person { public void openMouth() { ... } public void speak() { this.openMouth(); } }
3.通过this关键字调用构造方法。
class Person { public Person() { System.out.println("无参的构造方法被调用了..."); } public Person(int age) { this(); // 调用无参的构造方法 System.out.println("有参的构造方法被调用了..."); } } public class Example11 { public static void main(String[] args) { Person p = new Person(18); // 实例化 Person 对象 } }
在使用this调用类的构造方法时,应注意以下几点:
①只能在构造方法中使用this调用其他的构造方法,不能在成员方法中使用。
②在构造方法中,使用this调用构造方法的语句必须是该方法的第一条执行语句,且只能出现一次。
③不能在一个类的两个构造方法中使用this互相调用。
12.static关键字
static关键字只能用于修饰成员变量,不能用于修饰局部变量,否则编译会报错
一、被static修饰的成员变量,叫做静态变量
特点: 1.被该类所有对象共享 2.不属于对象,属于类 3.随着类的加载而加载,优先于对象存在
调用方法: a.类名调用(推荐) b.对象名调用
如果一个类的成员变量被static
修饰了,那么所有该类的对象都共享这个变量。无论这个类实例化多少对象,它的静态变量只有一份拷贝。
public class StaticDemo { public static void main(String[] args) { Person p1 = new Person(); p1.name="李四"; Person.name="王二"; Person p2 = new Person(); Person p3 = new Person(); System.out.println(p1.name); System.out.println(p2.name); System.out.println(p3.name); } } class Person{ static String name="John"; int age; }
二、被static修饰的成员方法,叫做静态方法
特点:
1.多用于测试类和工具类中 2.javabean类中很少会用 3.不需要创建对象就可以直接使用
调用方法: a.类名调用(推荐) b.对象名调用