目录
面向对象程序设计基础
结构化程序设计
结构化程序设计是一种面向过程的程序设计(POP)方法,即一个程序是由多个可独立编程的方法模块组成的,方法之间通过函数参数和全局变量进行相互联系。
优点:和以前的非结构化程序相比,在调试,可读性和可维护性等方面都有很大的改进。
缺点:代码复用性差,随着问题规模变大,程序长度增加,大大降低了程序的可维护性
面向对象程序设计方法及特征
面向对象程序设计是把一个复杂的问题分解成多个能够完成独立功能的对象(类),然后把这些类组合起来去完成这个复杂的问题。
类和对象
类的定义
类是对某类具有相同特征的对象的抽象描述,是面向对象程序设计中的一个非常重要的概念。类是数据属性和其相关操作封装在一起的集合体,包括了对象的数据成员(特征)和数据方法(行为),是对象的模板和蓝图。
Java程序中的类一般分为两种:
1.系统定义的类(Java类库):使用import语句引入系统类或系统类所在的包。例
//引入系统写好的栈类
import java.util.Stack;
2.用户自己定义的类:
一般格式如下([ ]内表示可省略部分 ):
[类修饰符] class 类名 [extends 父类名] [implements 接口列表]{
数据成员
成员方法
}
例:
public class StaticFunction {
private int a;
private static int aa;
public void fun(){
a = 100;
aa = 100;
}
类修饰符:
1.public公共类:可以被任何对象或类访问,同一个包或不同包的类都可以访问该类,一个源文件中只能有一个类被声明为public,类名须与源文件名相同。
2.private私有类:只能被该类的方法访问和修改,不能被其他任何类访问,包括该类的子类也不能访问。
类不写修饰符:默认被private修饰。
类成员
属性 -> 成员变量 属性全部被private修饰,也就是属性全部私有
行为 -> 成员方法
1.成员变量(属性)= 实例变量 + 静态变量
实例变量:跟对象有关,一个对象一份实例变量 对象.实例变量 存储在堆
静态变量:跟对象无关,一个类一份静态变量 类名.静态变量 存储在方法区 用static修饰
2.构造方法(专门初始化成员变量)
3.成员方法(行为)= 实例方法 + 静态方法
区别:有无this引用,静态无this,静态方法无this
对象
对象大小:对象存储位置
对象头+实例变量+内存填充
大小为8的倍数
对象头占用空间:
32位 存放Class指针的空间大小是4字节,MarkWord是4字节,对象头为8字节
64位 存放Class指针的空间大小是8字节,MarkWord是8字节,对象头为16字节
Class对象: 保存当前的类信息(类名,属性,方法)
类的初始化顺序
静态变量->静态块->实例变量->实例块->构造函数
静态块:专门对静态变量初始化
static {
count = 1;
}
实例块:专门对实例变量初始化
{
this.count = 0;
}
类的封装性
类的构造方法
- 构造方法名与类名相同
- 构造方法总是和new运算符一起被调用
- 构造方法不返回任何值,也没有返回类型
- 每个类可以有零个或多个构造方法,即构造方法可以重载
- 构造方法在创建对象是自动执行,一般不能显示的直接调用
- 如果用户未定义该类的构造方法,系统将为这个类定义一个空的构造方法
例:
public class People {
private String name;
private int age;
People(String name, int age) {
this.name = name;
this.age = age;
}
public String getName() {
return name;
}
@Override
public String toString() {
return "People{" +
"name='" + name + '\'' +
'}';
}
}
this和super引用
Java系统默认每个类都缺省地具有null、this、super三个对象引用变量,所以在任意类中可以不加说明直接使用这三个对象。
-
null:代表空对象,一般用null来代表为创建的对象
-
this:指当前对象的引用 (this.类中方法名(成员名))
如果局部变量的命名 的和成员变量命名出现冲突,需要强制指明当前对象
1.指明当前对象 : this.name = name;
2.this(): ->调用当前类的构造函数
注意:
1.构造函数之间不能相互调用
2.this() 必须位于当前构造函数有效代码第一行 -
super:指对父类对象的引用(super.父类中方法名(成员名))
使用的三种情况:
1.用来访问父类被隐藏的数据成员
2.调用父类中被子类覆盖的方法
3.调用父类的构造函数
类成员的访问权限修饰符
- private(私有的): 类中限定为private的成员,只能被这个类本身访问
- protected(保护的):可以被这个类本身、它的子类(包括同一个包中以及不同包中的子类)和同一个包中的其他所有类访问。
- public(共有的):可以被所有类访问
- 缺省的:类中不加任何访问权限限定的成员属于缺省的访问状态,可以被这个类本身和同一个包中的类所访问。
类的继承性
类的继承性表现为子类继承父类相关的数据成员和成员方法。
关键字 extends
Java中所有类都直接或间接的继承Java.lang.Object类。Object类事所有Java类的祖先。
例:
class People{
String name;
int age;
void eat(){
}
}
class Student extends People{
int id;
void eat(){
}
void study(){
}
}
类的多态性
多态事值同名的不同方法根据发送消息的对象以及方法传送参数的不同,采用不同的行为方式特性。一个类可以有多个同名、不同方法和方法参数的方法,程序运行时,Java虚拟机会根据调用该方法时传递参数个数的不同或参数类型的不同来决定调用相应的方法。这样就可以采用相同的方法获得不同的行为结果。多态性的概念也经常被说成是“一个接口,多种方法”。
Java中提供两种多态机制:覆盖和重载
覆盖和重载
方法的覆盖(Overriding)和重载(Overloading)是Java多态性的不同表现。覆盖(重写)是父类与子类之间多态性的一种表现,而重载是一个类中多态性的一种表现。
- 方法的覆盖(重写)
如果在子类中定义某方法与其父类有相同的名称和参数,则该方法覆盖(重写)父类的方法。子类的对象使用这个方法时,将调用子类中的定义,对其而言,父类中的定义被“屏蔽”。
例:
//父类
class A{
public int getValue(){
return 5;
}
}
//子类
class B extends A{
public int getValue(){
return 10;
}
}
//调用
public class Override {
public static void main(String[] args) {
B b = new B();
int a = b.getValue();
System.out.println(a);
}
}
覆盖方法的调用原则:
- 父类被覆盖的方法的声明必须要和子类的同名方法的声明完全匹配,才能达到覆盖的效果。
- 覆盖方法的返回值必须与被覆盖方法的返回值一致。
- 被覆盖的方法不能为private,否则只是在其子类中新定义了一个方法。
- 覆盖后方法的访问权限<=覆盖前方法的访问权限
2.方法的重载
如果在一个类中定义了多个同名的方法,它们有不同的参数个数、不同的参数类型或不同的参数次序,则称为方法重载。
例:
public class Overload {
//重载的方法
int add(int value1,int value2){
return (value1 + value2);
}
//重载的方法
double add(double value1,double value2){
return (value1 + value2);
}
//重载的方法
int add(int value1,int value2,int value3){
return (value1 + value2 + value3);
}
public static void main(String[] args) {
Overload overload = new Overload();
int a = overload.add(1,2);
double b = overload.add(1,2);
int c = overload.add(1,2,3);
System.out.println("a="+a);
System.out.println("b="+b);
System.out.println("c="+c);
}
}
覆盖和重载的区别:
运行时多态
运行时多态是面向对象程序设计代码覆盖的一个最强大机制,Java实现运行时多态性的基础是动态方法调用,它是一种在运行时而不是在编译器调用重载方法的机制。
由于子类继承了父类的所有属性(私有的除外),因此子类对象可以作为父类对象使用。程序中凡能使用父类对象的地方,都可以用子类对象来代替。一个对象可以通过引用子类的实例来调用子类的方法,这种机制就叫运行时多态。
例:
//定义父类superA
class superA{
int i = 100;
void fun(){
System.out.println("This is superA");
}
}
//定义superA子类subB
class subB extends superA{
int m = 1;
void fun(){
System.out.println("This is subB");
}
}
//定义superA的子类subC
class subC extends superA{
int n = 1;
void fun(){
System.out.println("This is subC");
}
}
public class Test {
public static void main(String[] args) {
superA a;
subB b = new subB();
subC c = new subC();
a = b;
a.fun();
a = c;
a.fun();
}
}
静态修饰符、静态数据成员和静态成员方法
有static关键字修饰的数据成员和成员方法称为静态数据成员或静态成员方法。
静态修饰符
static
使用效果:
- 保存一个特定的数据,无论创建多少个对象
- 需要一个特殊的方法,该方法没有与这个类的任何对象相关联。
静态数据成员
如果将一个类中的数据成员定义为static,那么该类的所有对象都将共享这个声明为static的数据成员。当用户对静态数据成员进行重新赋值时,该类的的所有对象访问该静态数据成员时都会得到这个新值。
例:
private static int id = 1;
静态常量
常量:是一种恒定的或不可变的数值或数据项。
用static修饰的常量为类常量,没有关键字修饰的常量为实例常量。
静态成员方法
用static修饰符修饰的方法时属于整个类的类方法,而不用static修饰符限定的方法是属于类的某个具体对象的。
调用:类名.方法名(参数)
例:
class Simple{
static void go(){
System.out.println("1");
}
}
public class Constants {
public static void main(String[] args) {
Simple.go();
}
}
抽象类
抽象类
abstract
抽象类无具体对象,即该类不能实例化,不能用new关键字创建该类的对象,而只能由他派生子类,由子类完成具体方法的实现。包含有抽象方法的类必须被声明为抽象类。
最终类
final
最终类不能作为父类被继承,也不能派生出子类。
基本数据类型的包装类
char -> Character
int -> Integer
float -> Float
double -> Double
byte -> Byte
long -> Long
short -> Short
booean -> Boolean
加包(装箱)操作:Integer a = 10; <=> Integer c = Integer.valueOf(10);
拆包(拆箱)操作:int c = b.intValue();