面向对象(上)
java面向对象学的三条主线:
- Java类以及类的成员:属性、方法、构造器;代码块、内部类
- 面向对象三大特征:封装性,继承性、多态性、(抽象性)
- 其他关键字:this,super,static,final,abstract,package,import等
概述:
比较面向过程与面向对象(人把大象装进冰箱):
- 面向过程:强调的是功能行为,以函数为最小单位,考虑怎么做。
- 把冰箱门打开
- 抬起大象塞进冰箱
- 把冰箱门关闭
- 面向对象:强调具备了功能的对象,以类/对象为最小单位,考虑谁来做.
理解万事万物皆对象:1.在java语言范畴中,我们都将功能结构等封装到类中,通过类的实例化,来调用具体的功能结构 2.涉及到Java语言与前端HTML、后端的数据库交互时,前后端的结构在Java层面交互时,都体现为类、对象
人{
打开(冰箱){
冰箱.开开;
}
抬起(大象){
大象.进入冰箱
}
关闭(冰箱){
冰箱.闭合
}
}
冰箱{
开开(){}
闭合(){}
}
大象{
进入冰箱(){}
}
面向对象的两个要素:
类:对一类事物的描述,是抽象的、概念上的定义
对象:是实际存在的该类事物的每个个体,因而也称为实例(instance)
面向对象程序设计的重点是类的设计
类的设计,其实就是类成员的设计
类
属性 = 成员变量 = field = 域、字段
方法 = 成员方法 = 函数 = method
创建类的对象 = 类的实例化 = 实例化类
示例:
class Person{
//属性
String name;
int age = 1;
boolean isMale;
//方法
public void eat(){
System.out.println("人可以吃饭");
}
public void sleep(){
System.out.println("人可以睡觉");
}
public void talk(String language){
System.out.println("人可以说话,使用的是:"+language);
}
}
类的实例化
//测试类:
public class PersonTest{
public static void main(String[] args){
//创建Person类的对象
Person p1 = new Person();
//调用对象的结构:属性,方法
//调用属性:“对象.属性”
p1.name = "Tom";
p1.isMale = true;
System.out.println(p1.name);
//调用方法:"对象.方法"
p1.eat();
p1.sleep();
p1.talk("Chinese");
//如果创建了一个类的多个对象,这每个对象都独立的拥有一套类的属性。(非static)
Person p2 = new Person();
System.out.println(p2.name);//null
//将p1变量保存的对象地址值赋值给p3,导致p1和p3指向了堆空间中的同一个实体
Person p3 = p1;
System.out.println(p3.name);//Tom
p3.age = 10;
System.out.println(p1.age);//10
}
}
对象的内存解析:
编译完源程序以后,生成一个或多个字节码文件。
我们使用JVM 中的类加载器和解释器对生成的字节码文件进行解释运行。意味着,需要将字节码文件对应的类加载到内存中,涉及到内存解析。
虚拟机栈,即为平时提到的栈结构。我们将局部变量存储在栈结构中
堆,我们将new出来的结构(比如:数组、对象)加载在堆空间中。补充:对象的属性(非static的)加载在堆空间中
方法区:类的加载信息、常量池、静态域
堆 (Heap),此内存区域的唯一目的就是存放对象实例,几乎所有的对象实例都在这里分配内存。这一点在Java虚拟机规范中的描述是:所有的对象实例以及数组都要在堆上分配。
通常所说的栈 (stack) ,是指虚拟机栈。虚拟机栈用于存储局部变量等局部变量表存放了编译期可知长度的各种基本数据类型 (boolean、byte、char 、 short 、 int 、 float 、 longdouble)、对象引用 (reference类型它不等同于对象本身,是对象在堆内存的首地址)。 方法执行完,自动释放。
方法区 (Method Area) ,用于存储已被虚拟机加载的类信息、常量、静态变量、即时编译器编译后的代码等数据
类中属性的使用
属性(成员变量) vs 局部变量
1.相同点:定义变量的格式一样:数据类型 变量名 = 变量值。先声明,后使用;变量都有其作用域
2.不同点:在类中声明的位置不同,属性直接声明在类的一对{}中 局部变量:声明在方法内、方法形参、代码块内、构造器形参,构造器内部的变量;关于权限修饰符的不同,属性可以在声明属性时,指定其权限,使用权限修饰符。常用的权限修饰符有:private、public、缺省、protected ---->封装性,局部变量不能使用权限修饰符;默认初始化值,属性:类的属性,根据其类型,都有其默认初始化值 整型(byte,short,int,long):0,浮点型(float,double):0.0 字符型(char):0,布尔类型(boolean):false引用数据类型:null。局部变量没有初始化值,特别的,形参在调用时赋值即可;在内存中加载位置不同,属性加载在堆空间(非static)局部变量:加载到栈空间
类中方法的使用
方法:描述类应该具有的功能
方法的声明:权限修饰符 返回值类型 方法名(形参列表){方法体}
说明: 权限修饰符同上(public,private,缺省,protect)
返回值类型:有返回值和无返回值。如果方法有返回值,则必须在方法声明时,指定返回值类型。同时,方法中需要使用return关键字来返回指定类型的变量或常量。无返回值,则方法声明时,使用void来表示。通常,不使用return,如果使用return表示方法的结束
方法名:属于标识符,见名知意
形参列表:方法可以定义0,1,多个形参。格式:数据类型1 形参1,数据类型2 形参2,...
return关键字的使用:1.使用范围:使用在方法体中 2.结束方法 3.针对有返回值的方法,使用"return 数据"返回所要的值 4.return关键字后面不能再声明语句
方法的使用:可以调用当前类的属性、方法
匿名对象的使用
理解:我们创建对象,没有显式的赋给一个变量名。即为匿名对象
特征:匿名对象只能调用一次
使用:直接new 对象名().方法名或者new 对象名().属性名 此时new 对象名()就是一个匿名对象
方法的重载(overload)
概念:在同一个类中,允许存在一个以上的同名方法,只要它们的参数个数或者参数
类型不同即可
特点:与返回值类型无关,只看参数列表,且参数列表必须不同。(参数个数或参数类型)。调用时,根据方法参数列表的不同来区别。
可变个数的形参
- jdk5.0新增的内容
- 具体使用:格式:数据类型... 变量名;当调用可变个数形参方法时,传入的参数可以是0,1,多个;可变个数形参方法与本类中方法名相同,形参不同的方法之间构成重载;形参类型也相同的数组之间不构成重载,二者不能共存;若方法中要使用该参数,用数组接收;可变个数形参在方法中必须声明在末尾;可变个数形参只能声明一个形参
public void show(String ...strs){
for(int i =0;i<strs.length;i++){
System.out.println(strs[i]);
}
}
方法参数的值传递机制
关于变量的赋值:如果变量时基本数据类型,此时赋值的是变量所保存的数据值。如果变量是引用数据类型:此时赋值的变量所保存的数据的地址值
形参:方法定义时,声明的小括号里的参数
实参:方法调用时,实际传递给形参的数据
方法的形参的传递机制:
如果参数是基本数据类型,此时实参赋给形参的是实参真实存储的数据值
如果参数是引用数据类型,此时实参赋给形参的是实参真实存储的地址值
递归(recursion)方法
概念:一个方法调用它本身
方法递归包含一种隐式的循环,它会重复执行某段代码,但这种重复执行,无须循环控制。
递归一定要向已知方向递归,否则这种递归就变成了无穷递归,类似于死循环
例:
public int getSum(int n){
if(n==1){
return 1;
}else{
return n+getSum(n-1);
}
}
面向对象特征之一:封装和隐藏
隐藏对象内部的复杂性,只对公开简单的接口,便于外界调用,从而提高系统的可扩展性、可维护行。通俗的说,把该隐藏的隐藏起来,该暴露的暴露出来。这就是封装性的设计思想。
问题的引入:当我们创建一个类的对象以后,我们可以通过"对象.属性"的方式,对对象进行赋值,这时候,赋值操作要受到属性的数据类型和存储范围的制约。除此之外,没有其他制约条件。但是在实际问题中,我们往往需要给属性赋值加入额外的限制条件。这个条件就不能属性声明时体现,我们只通过方法进行限制条件的添加。比如:(set)。同时要避免使用对象.属性的方式对属性进行赋值。我们需要将属性设置为私有,即private-->此时,针对属性就体现了封装性。
封装性的体现:我们将类的属性私有化(private),同时,提供公共的(public)方法来获取(getXxx)和(setXxx)此属性的值
封装性的体现,需要权限修饰符来配合
1、Java规定的4中权限(从小到大排列),private(类内部),缺省(类内部,同一个包),protected(类内部,同一个包,不同包的子类),public(类内部,同一个包,不同包的子类,同一个工程)
2、4种权限可以用来修饰类及类的内部结构:属性、方法、构造器、内部类
3、具体的,4种权限都可以用来修饰类的内部结构:属性、方法、构造器、内部类。修饰类的话只能使用缺省和public
总结:Java提供了四种权限修饰符来修饰类及其类的内部结构,体现了类及类内部结构在被调用时的可见性的大小
构造器(构造方法)constructor
一、构造器的作用:创建对象,初始化对象的属性
二、说明:1.如果没有显式的定义类的构造器的话,这系统默认会提供一个空参的构造器,2.定义构造器的形式:权限修饰符 类名(形参列表){} 3.一个类中定义的多个构造器,彼此构成重载 4.一旦我们显示的定义了类的构造器之后,系统就不再提供默认的空参构造器 5.一个类中,至少会有一个构造器
关于属性赋值的先后顺序:1、默认初始化值 2、显式初始化 3、构造器中赋值 4、通过"对象.方法"赋值。操作的先后顺序:1-2-3-4 取决于后边的值
JavaBean
概念:JavaBean是一种Java语言写成的可重用组件。
所谓javaBean,是符合如下标准的Java类:
- 类是公共的
- 有一个午餐的公共的构造器
- 有属性,且有对应的get和set方法
用户可以使用JavaBean将功能、处理、值、数据库访问和其他任何可以用Java代码创造的对象进行打包,并且其他的开发者可以通过内部的JSP页面、Servlet、其他JavaBean、applet程序或者应用来使用这些对象。用户可以认为JavaBean提供了一种随时随地的复制和粘贴的功能,而不用关心任何改变。
扩展知识:UML类图
- +表示public类型,-表示private类型,#表示protected类型
- 方法的写法:方法的类型(+、-)方法名(参数名:参数类型):返回值类型
关键字:this的使用
在Java中,this关键字比较难理解,它的作用和其词义很接近。
- 它在方法内部使用,即这个方法所属对象的引用;
- 它在构造器内部使用,表示该构造器正在初始化对象
this表示当前对象,可以调用类的属性、方法和构造器
什么时候使用this关键字?当在方法内需要用到调用该方法的对象时,就用this。具体的:我们可以用this来区分局部变量和属性。比如:this.name = name;
this可以修饰:属性、方法、构造器
-
this修饰属性和方法:this理解为当前对象或当前正在创建的对象
在类的方法中,我们可以使用"this.属性"或"this.方法"的方式,调用当前对象属性或方法。但是,通常情况下,我们都省略"this."。特殊情况下,如果方法的形参和类的属性同名时,我们必须显式的使用"this.变量"的方式,表明此变量是属性,而非形参。(构造器同理) -
this调用构造器 this(形参列表);
在类的构造器中,可以显式的使用"this(形参列表)"方式调用其他的构造器,不能调用自己。
如果一个类有n个构造器,则最多有n-1构造器中使用了"this(形参列表)"
规定:"this(形参列表)"必须声明在当前构造器的首行
构造器内部,最多声明一个"this(形参列表)",用来调用其他的构造器
关键字:package、import的使用
package
1.为了更好的实现项目中类的管理,提供包的概念
2.使用package声明类或接口所属的包,生命在源文件的首行
3.包,属于标识符,遵循标识符命名规则、规范(xxxyyyzzz)、“见名知意”
4.每"."一次,就代表一层文件目录。
补充:同一个包下,不能命名同名的接口,类。不同的包下,可以命名同名的接口,类。
JDK中主要的包介绍:
- java.lang---包含一些Java语言的核心类,如String、Math、Integer、System和Thread,提供常用的功能。
- java.net----包含执行与网络相关的操作的类和接口。
- java.io ----包含能提供多种输入/输出功能的类
- java.util----包含一些实用工具类,如定义系统特性、接口的集合框架类、使用与日4.期日历相关的函数。
- java.text----包含了一些java格式化相关的类
- java.sql----包含了java进行JDBC数据库编程的相关类/接口
- java.awt----包含了构成抽象窗口工具集 (abstract window toolkits)的多个类,这些类被用来构建和管理应用程序的图形用户界面(GUI)。 B/S C/S
import关键字的使用
import:导入
- 在源文件中显式的使用import结构导入指定包下的类、接口
- 声明在包的声明和类的声明之间
- 如果需要导入多个结构,则并列写出即可
- 可以使用"xxx.*"的方式,表示可以导入xxx下包的所有结构
- 如果使用的类或接口是java.lang包下定义的,则可以省略import结构
- 如果使用的类或接口是本包下定义的,则可以省略import结构
- 如果在源文件中,使用了不同包下的同名的类,则必须至少一个类需要以全类名的方式显示。
- 使用"xxx.*"方式表明可以调用xxx包下的所有结构。但是如果使用的是xxx包下的结构,则仍需要显式导包
- import static:导入指定类或接口中的静态结构:属性或方法。
扩展
mvc设计模式
MVC是常用的设计模式之一,将整个程序分为三个层次:视图模型层,控制器层,与数据模型层。这种将程序输入输出、数据处理,以及数据的展示分离开来的设计模式使程序结构变的灵活而且清晰,同时也描述了程序各个对象间的通信方式,降低了程序的合性。
模型层 model主要处理数据
数据对象封装 model.bean/domain
数据库操作类 model.dao
数据库 model.db
控制层 controller处理业务逻辑
引用界面相关 controller.activity
存放fragment controller.adapter
显示列表的适配器 controller.adapter
服务相关的 controller.service
抽取的基类 controller.base
视图层 view显示数据
相关工具类 view.utils
自定义view view.ui