五、面向对象
1.面向对象与面向过程:
面向过程,强调的是功能行为;面向对象,将功能封装进对象,强调具备了功能的对象。
2.面向对象的三大特性:封装、继承、多态
3.java类及类的成员:
Java代码世界是由诸多个不同功能的类构成的,一个类class一般包含:
①属性-成员变量
②行为-(成员)方法、函数
4.理解:
类 = 汽车设计图;
对象 = 实实在在的汽车
面向对象程序设计的重点是类的设计
定义类其实是定义类中的成员(成员变量和成员方法)
5.类的语法格式:
修饰符 class 类名 {
属性声明;
方法声明;
}
//方法中不能再定义方法
举例:
public class Person {
//属性,成员变量,类的成员变量可以先声明,不用初始化,类成员变量是有默认值
public String name; //姓名,String的默认值是null
private int age; //年龄,int的默认值是0
public static String sex = "男"; //类变量-后面详解
//行为,方法,也叫函数
public void showName(){ //方法的名称如果是多个单词,首个的单词的首字母小写,其他的单词首字母大写,这样就像一个驼峰一样,所有叫驼峰命名法
System.out.println("姓名:" + name);
getAge(); //同一个类中,所有的方法可以直接互相调用,不用new去实例化对象
}
//有返回值的函数
public int getAge(){
return age;
}
}
6.类的实例化:对象的创建和使用
①使用new +构造器创建一个新的对象;
②使用“对象名.对象成员”的方式访问对象成员(包括属性和方法;
以上面创建的Person类为例:
public class People {
public static void main(String[] args){
//实例化Person类,也就是创建Person对象
Person person = new Person();
//声明一个Person类型的变量,变量名person,实例化Person类并且给person赋值,赋值的值就是当前的实例
person.name = "张三"; //给person对象的name属性赋值
person.showName(); //对象的方法的调用
int i = person.getAge();
System.out.println(i);
person.age = 11; //给person对象的age属性赋值
int a = person.getAge();
System.out.println(a);
}
}
注:如果创建了一个类的多个对象,对于类中定义的属性,每个对象都拥有各自的一套副本,且互不干扰.
7.类的成员之一:属性
(1)语法格式:
修饰符 类型 属性名 =初值 ;
说明:修饰符private:该属性只能由该类的方法访问,不能通过 对象.属性 的方式调用。
修饰符public:该属性可以被该类以外的方法访问。
类型:任何基本类型,如int、boolean或任何类。
(2)变量的分类:
①成员变量:
a.实例变量(不以static修饰):
就是在类实例化成对象之后才能被使用的变量,如Person中的name(成员变量有默认的init值).
实例变量存在于对象所在的堆内存中。
b.类变量(以static修饰):
这样的变量是静态的,类不需要实例化成对象就可以通过 类名.属性 调用.如Person中的sex.
②局部变量:
a.形参(方法签名中定义的变量)
b.方法局部变量(在方法内定义的变量)
c.代码块局部变量(在代码块中定义的变量)
③ 注 释 :
a.局部变量存在于栈内存中,作用的范围结束,变量空间会自动释放.
b.局部变量没有默认初始化值,每次必须显式初始化.
c.局部变量声明时不指定权限修饰符
8.类的成员之二:方法
(1)语法格式:
修饰符 返回值类型 方法名(参数类型 形参1,参数类型 形参2,...){
程序代码
return 返回值;
}
说明: 修饰符:public, private, protected等。
返回类型为void,则不用return.关于形参,实参,返回值等不再记录,和C++完全一致
(2) 方 法:
01.方法是类或对象行为特征的抽象,也称为函数.
02.Java里的方法不能独立存在,所有的方法必须定义在类里.
03.方法只有被调用才会被执行.
04.方法中只能调用方法,不可以在方法内部定义方法.
并且在同一个类中,方法之间可以直接互相调用,所以在方法中调用另一个方法时不需要new
9.关于对象:
01.匿名对象:不定义对象的句柄,而直接调用这个对象的方法,这样的对象叫做匿名对象。
使用情况:如果对一个对象只需要进行一次方法调用,那么就可以使用匿名对象。
经常将匿名对象作为实参传递给一个方法调用。
如: new Person().shout();
02.在一个类中的访问机制:
类中的方法可以直接访问类中的成员变量。
(例外:static方法访问非static的成员变量,编译不通过.)
03.在不同类中的访问机制:
先创建要访问类的对象,再用对象访问类中定义的成员。
10.方法的重载
01.概念:
在同一个类中,允许存在一个以上的同名方法,只要它们的参数个数或者参数类型不同即可,与形参名无关。
02.代码示例:
public int add(int x, int y){
return x + y;
}
public double add(int x, double y){
return x + y;
}
public int add(int x, int y, int z){
return x + y + z;
}
//在主类Text中定义重载函数,在main()中,进行对象实例化,以及方法的调用
Text examp = new Text();
examp.add(1, 2);
examp.add(1, 0.5);
examp.add(1,2,3);
03.特点:
与返回值类型无关,只看参数列表,且参数列表必须不同。
参数个数或参数类型,参数相同只是顺序不同也可以构成重载
调用时,根据方法参数列表的不同来区别。
在主类Text中定义重载函数,在main()中,
Text examp = new Text();
examp.add(1, 2);
examp.add(1, 0.5);
examp.add(1,2,3);
11.方法--可变个数的形参
定义方法:
a.使用数组作为形参
(传参使用时需要在main函数中new一个数组作为实参传入,数组长度可变0~+无穷)
public void printInfo(String[] args){
//这里的String可以根据需要使用基本数据类型
for(int i = 0; i < args.length; i++){
System.out.println(args[i]);
}
}
b.使用Java自带的可变形参表示法(使用方法与使用数组的形式相同)
//方法的参数部分有可变形参,需要放在形参声明的最后
public void printInfo1(int d, String... args){
for(int i = 0; i < args.length; i++){
System.out.println(args[i]);
}
}
//使用:(在此之前要在main中实例化一个方法所在的类,命名为p3)
p3.printInfo1(2,"lisi", "23", "男");
//或者像使用数组一样
String[] ss2 = new String[]{"北京市xxx","13133334444","152109874523666541"};
p3.printInfo1(ss2);
//不同的是,当参数为空时,使用数组的方法要传入null或空数组,用b方法形参可以空着
12.JVM的内存模型
13.方法--参数传递
01.Java里方法的参数传递方式只有一种:值传递。
即将实际参数值的副本(复制品)传入方法内,而参数本身不受影响。
02.参数传递的两种情况
a.如果方法的形参是基本数据类型,那么实参(实际的数据)向形参传递参数时,就是直接传递值,把实参的值复制给形参。
b.如果方法的形参是对象,那么实参(实际的对象),向形参传递参数的时,也是把值给形参,这个值是实参在栈内存中的值,也就是引用对象在堆内存中的地址。
基本数据类型都是保存在栈内存中,引用对象在栈内存中保存的是引用对象的地址,那么方法的参数传递是传递值(是变量在栈内存的当中的值)
03.参数传递的内存示意图
14.源文件布局:
[<包声明>]
[<引用声明>]
<类声明>
15.关键字-package
01.package语句作为Java源文件的第一条语句,指明该文件中定义的类所在的包。若缺省该语句,则指定为无名包.
02.包对应于文件系统的目录,package语句中,用 “.” 来指明包(目录)的层次.
03.包通常用小写单词,类名首字母通常大写.
16.关键字-import
01.作用:为使用定义在不同包中的Java类,需用import语句来引入指定包层次下所需要的类或全部类(.*),但是包内的子包中的类不会被引用。
02.语法格式:import 包名[.子包名…]. <类名 |*>
03.代码示例:
import p1.Test; //import p1.*;表示引入p1包中的所有类
public class TestPackage{
public static void main(String args[]){
Test t = new Test(); //Test类在p1包中定义
t.display();
}
}
04.import语句出现在package语句之后、类定义之前,一个源文件中可包含多个import语句。
17.面向对象特征之一:封装和隐藏
使用者对类内部定义的属性(对象的成员变量)的直接操作会导致数据的错误、混乱或安全性问题
01.Java中通过将数据声明为私有的(private),再提供公共的(public)方法:
getXxx()和setXxx()实现对该属性的操作,以实现下述目的:
a.隐藏一个类中不需要对外提供的实现细节;
b.使用者只能通过事先定制好的方法来访问数据,可以方便地加入控制逻辑,限制对属性的不合理操作;
c.便于修改,增强代码的可维护性;
02.四种访问权限修饰符
03. 注意:
a.对于class的权限修饰只可以用public和default(缺省)。
b.public类可以在任意地方被访问。
c.default类只可以被同一个包内部的类访问。
d.在同一个Java文件中可以写多个class,但是只有一个可以定义为public,其他修饰符空着(default)。
18.类的成员之三:构造器(构造函数)
01.构造器的特征
a.它具有与类相同的名称
b.它不声明返回值类型。(与声明为void不同)
c.不能被static、final、synchronized、abstract、native修饰,不能有return语句返回值
02.构造器的作用:创建对象;给对象进行初始化
a.如:Order o = new Order(); Person p = new Person(Peter,15);
b.New对象实际就是调用类的构造方法(构造函数-C++后遗症)
03.语法格式:
修饰符 类名 (参数列表) { //修饰符与类的修饰符一致
初始化语句; //可以使用初始化语句和参数列表将类的属性默认初始化或显式初始化
}
04.根据参数不同,构造器可以分为如下两类:
a.隐式无参构造器(系统默认提供)
b.显式定义一个或多个构造器(无参、有参)
05.注 意:
a.Java语言中,每个类都至少有一个构造器
b.默认构造器的修饰符与所属类的修饰符一致
c.一旦显式定义了构造器,则系统不再提供默认构造器
d.一个类可以创建多个重载的构造器
e.父类的构造器不可被子类继承
19.构造器重载(构造函数重载)
01.构造器重载使得对象的创建更加灵活,方便创建各种不同的对象。
02.构造器重载举例:
public class Person{
public Person(String name, int age, Date d) {this(name,age);…}
public Person(String name, int age) {…}
public Person(String name, Date d) {…}
public Person(){…}
}
03.构造器重载,参数列表必须不同
20.关键字—this
01.它在方法内部使用,即表示这个方法所属对象的引用;
02.它在构造器内部使用,表示该构造器正在初始化的对象。
03. this表示当前对象,可以调用类的属性、方法和构造器。
04.使用时机:当在方法内需要用到调用该方法的对象时,就用this。
05.使用this,调用属性、方法。代码示例:
class Person{ // 定义Person类
private String name ;
private int age ;
public Person(String name,int age){
this.name = name ; //这里必须用this指针表明name为类的属性,而非形参
this.age = age ; }
public void getInfo(){
System.out.println("姓名:" + name) ;
this.speak();
}
public void speak(){
System.out.println(“年龄:” + this.age);
}
}
/**
* a.当形参与成员变量重名时,如果在方法内部需要使用成员变量,
* 必须添加this来表明该变量时类成员
* b.在任意方法内,如果使用当前类的成员变量或成员方法可以在其前面添加this,
* 增强程序的阅读性
*/
class Person{ // 定义Person类
private String name ;
private int age ;
public Person(){ // 无参构造
System.out.println("新对象实例化") ;
}
public Person(String name){
this(); // 调用本类中的无参构造方法,且放在构造方法的首行
this.name = name ;
}
public Person(String name,int age){
this(name) ; // 调用有一个参数的构造方法,且放在构造方法的首行
this.age = age;
}
public String getInfo(){
return "姓名:" + name + ",年龄:" + age ;
}
}
/**
* c.this可以作为一个类中,构造器相互调用的特殊格式
* d.使用this()必须放在构造器的首行
* e.使用this调用本类中其他的构造器,保证至少有一个构造器是不用this的。
*(实际上就是不能出现构造器自己调用自己)
*/
21.JavaBean
01.JavaBean是一种Java语言写成的可重用组件
02.所谓javaBean,是指符合如下标准的Java类:
a.类是公共的
b.有一个无参的公共的构造器
c.有属性,属性一般是私有的,且有对应的get、set方法
03.用户可以认为JavaBean提供了一种随时随地的复制和粘贴的功能,而不用关心任何改变。
04.对于eclipse,在创建了类和其中的属性后,可以使用 右键 -> Source -> Generate Geeters and Setters,进行设置,直接 生成类中各个属性的setter和getter.