第二章:JAVA-面向对象编程
面向对象与面向过程
- 面向过程,强调的是功能行为。
- 面向对象,将功能封装进对象,强调了具备了功能的对象。
- 面向对象的三大特征:
- 封装(Encapsulation)
- 继承(Inheritance)
- 多态(Polymorphism)
JAVA类及类的对象
- JAVA类的创建
修饰符 class 类名{ // 属性,成员变量,类的成员变量可以先声明,不用初始化,类成员变量有默认值 属性声明; // 行为,方法,也叫函数 方法声明; }
public class Person{ public int age; //声明公有变量age /** * 打印年龄 */ public void showAge(){//声明方法showAge() System.out.println(age); } /** * 返回年龄 * @return */ public int getAge(){ return age; } }
- 类对象的声明
- 使用
new + 构造器
创建一个新的对象 - 使用
对象名.对象成员
的方式访问对象成员(包括属性和方法)//实例化Person类,也就是创建Person对象 Person person = new Person(); person.age=21;//属性赋值 person.showAge();//方法调用 int age = person.getAge();
- 使用
- 类的成员
- 属性
- 语法格式:
修饰符 类型 属性名 = 初始值;
- 含
static
修饰符的为类变量,可以不实例化直接使用;相应的,不含static
修饰符的为实例变量,只有在类实例化成对象之后才能使用 - 实例变量存在于对象所在的堆内存中
- 局部变量存在于栈内存中
- 局部变量没有默认初始化值,每次必须显式初始化
- 语法格式:
- 方法
- 语法格式:
修饰符 返回值类型 方法名(参数列表){ 方法语句; }
- Java里的方法不能独立存在,所有的方法必须定义在类里
- 同一个类中,所有的方法之间可以直接互相调用
- 形式参数:在方法被调用时用于接收外部传入的数据的变量
- 实参:调用方法时实际传给函数形式参数的数据
- 语法格式:
- 类中的方法可以直接访问类中的成员变量,但是有一个例外:static方法无法访问非static的成员变量
- 属性
匿名对象
- 我们可以不定义对象的句柄,而直接调用这个对象的方法。这样的对象叫做匿名对象:
new Person().showAge();
- 使用的情形包括
- 如果对一个对象只需要进行一次方法调用,那么就可以使用匿名对象
- 我们经常将匿名对象作为实参传递给一个方法调用
方法的重载(overload)
- 概念:在同一个类中,允许存在一个以上的同名方法,只要他们的参数个数或者参数类型不同即可
- 特点:与返回值类型无关,只看参数列表,且参数列表必须不同。调用时,根据方法参数列表的不同来区别(参数顺序不同也可以)
可变个数的形参
- 当函数的形参数目不确定时,有两种解决方法:
- 采用数组形参来定义方法:
public static void test(int a,String[] books)
,没有参数时需要定义一个空数组或是null - 以可变个数形参来定义方法:
public static void test(int a,String... books)
,没有参数时可以直接不填
- 采用数组形参来定义方法:
- 当使用可变个数形参来定义方法时,以下两种使用方式均可行:
person.printInfo("张三","男","21");//方法一 person.printInfo("李四","男","21","17700000000"); String[] args = new String[]{"李四","男","21","17700000000"}; person.printInfo(args);//方法二
其中,函数的定义为:
public void prinyInfo(String... args){//这种参数的使用方式与数组相同 for(int i=0;i<args.length;i++){ System.out.println(args[i]); } }
说明:
- 可变参数:方法参数部分指定类型的参数个数是可变多个
- 声明方式:
方法名(参数类型... 参数名)
- 可变参数方法的使用与方法参数部分使用数组时是一样的
- 方法的参数部分具有可变形参时,需要放在形参声明的最后
方法的参数传递
- 方法只有被调用才有意义
- Java里方法的参数传递方式只有一种:值传递,即,将实际参数值的副本(复制品)传入方法内,而参数本身不受影响
- JVM的内存模型如下,其中栈存放基础数据类型和对象的引用;堆存放所有的对象;方法区存放所有的class和static变量。 因此,当传递的参数为引用对象时,传递过去的值为栈内存中对象的地址,该值被复制一遍后,仍为指向堆内存中对象的地址。此时,在函数内进行的更改操作会影响到堆中的对象。
- 可以总结为:基本数据类型都是保存在栈内存中,引用对象在栈内存中保存的是引用对象的地址,那么进行方法的参数传递时,传递的值均为栈内存中存储的值
包(package)和引用(import)
- 包(package):package语句作为Java源文件的第一条语句,知名该文件中定义的类所在的包。其格式为:
package 顶层包名.子层包名
,用.
来知名包(目录)的层级。 - 引用(import)
- 若引入的包为:java.lang,则编译器默认可获取此包下的类,不需要再显示声明
- import语句出现在package语句之后、类定义之前
- 一个源文件中可以包含多个import语句
- 可以使用
import lee.*
来表示导入lee包下的所有类,但是lee包下的sub子包内的类不会被导入 - import语句不是必须的,可以在类中使用其他类的全名以使用,如
com.animal.Dog myDog = new com.animal.Dog();
- JDK 1.5加入了import static语句,使用
import static 包名.类名.*
来导入这个类中的静态成员。
封装和隐藏
Java中通过将数据声明为私有的(private),再提供公共的(public)方法:getXxx
和setXxx
实现对该属性的操作,以实现以下目的:
- 隐藏一个类中不需要对外提供的实现细节
- 使用者只能通过实现定制好的方法来访问数据,可以方便地加入控制逻辑,限制对属性的不合理操作
- 便于修改,增强代码的可维护性
public class Person{
private int age;//先把属性声明为私有地
public int getAge(){//用get方法获取属性
return age;
}
public void setAge(int a){//用set方法设置属性
if(a>=0 && a<=200){
age = a;
}
else{
System.out.println("Wrong Age!");
}
}
}
四种访问权限修饰符
Java权限修饰符public
protected
private
置于类的成员定义前,用来限定对象对该类成员的访问权限
对于class的权限修饰只能使用public和default(缺省)
- public类可以在任何地方被访问
- default类只可以被同一个包内部的类访问
- 在同一个java文件中可以写多个class,但是只能有一个public,其他的class只能缺省
修饰符 | 类内部 | 同一个包 | 子类 | 任何地方 |
---|---|---|---|---|
private | √ | |||
(缺省) | √ | √ | ||
protected | √ | √ | √ | |
public | √ | √ | √ | √ |
类的构造器
- 构造器的特征
- 它具有与类相同的名称
- 它不声明返回值类型(与声明为void不同)\
- 不能被
static
final
synchronized
abstrac
native
修饰,不能有return
语句返回
- 构造器的作用:创建对象、给对象初始化
- 根据参数的不同,构造器可以分为如下两类:
- 隐式无参构造器(系统默认提供)
- 显式定义一个或多个构造器(无参、有参)
- 注意:
- java语言中,每个类都至少有一个构造器
- 默认的构造器的修饰符与所属类的修饰符一致
- 一旦显示定义了构造器,则系统不再提供默认构造器
- 一个类可以创建多个重载的构造器
- 父类的构造器不可被子类继承
this关键字
- 当形参与成员变量重名时,如果在方法内部需要使用成员变量,必须添加
this
来表明该变量是类成员 - 在任意方法内,如果使用当前类的成员变量或成员方法,可以在其前面添加
this
,增强程序的阅读性。 this
可以做为一个类中构造器相互调用的特殊格式注意,当使用
this
作为构造器的特殊调用格式时:- 必须位于构造器的首行
- 使用
this
调用本类中其他的构造器时,必须保证至少有一个构造器是不用this
的
JavaBean
- JavaBean是一种Java语言写成的可重用组件
- 需要符合如下标准
- 类是公共的
- 有一个无参的公共的构造器
- 有属性及对应的get、set方法