您的位置:首页 > 职场人生

黑马程序员——Java中的面向对象

2015-09-05 19:46 447 查看
——- android培训java培训、期待与您交流! ———-

一,面向对象简介

1. 面向对象概念

面向对象是相对面向过程而言,面向对象和面向过程都是一种思想。

面向过程,强调的是功能行为;面向对象,将功能封装进对象,强调具备了功能的对象。



2. 基本特征(3个):

封装(Encapsulation):将对象实现细节隐藏,通过一些共用方法来暴露对象的功能;提高类的内聚性,降低了对象之间的耦合性;

私有仅仅是封装的一种表现形式,提供对外访问方式(set和get方法)可以对数据进行操作判断,提高安全性

包也是一种封装形式

包与包之间的类进行访问,被访问的包中的类必须是public的,被访问的包中的类的方法也必须是public的。

继承(Inheritance):类之间共享属性和操作的机制(子类继承父类,直接获得父类的属性和方法,实现类复用);通过extends关键字让类与类之间产生继承关系

特点:

子类可以直接访问父类中的非私有的属性和行为,子类无法继承父类中私有的内容(方法和变量)

提高了代码的复用性

Java只支持单继承,不支持多继承,但支持多层继承

继承代码示例:

class Fu {
Fu() {
super();
show();// 该方法被子类复写,调用的是子类的show方法,此时其成员变量num还未进行显示初始化
}

void show() {
System.out.println("fu show");
}
}

class Zi extends Fu {
int num = 8;

Zi() {
super();// 通过super初始化父类内容时,子类的成员变量并未显示初始化,等super()父类初始化完毕后,才进行子类的成员变量显示初始化
}

void show() {
System.out.println("zi show..." + num);
}
}

class ExtendsDemo {
public static void main(String[] args) {
Zi z = new Zi();
z.show();
}
}


运行结果:


多态(Polymorphism):子类对象直接赋给父类变量,运行时依然表现子类特征。

定义:某一类事物的多种存在形态。

作用:多态的存在提高了程序的扩展性和后期可维护性(弊端:前期定义的内容不能调用后期子类的特有内容)

多态时,成员的特点

成员函数(非静态):示例中为method1()、method2()和method3()。

在编译时期:参考引用型变量所属的类中是否有调用的函数(有,编译通过(method1()被复写,method2()为父类);没有,编译失败(如method3()父类中不存在))。

在运行时期:参考的是对象所属的类中是否有调用的函数

简单说:编译看左边,运行看右边。

静态成员函数:实例中的method4()。

继承中,父类为static的方法无法被覆盖

编译时:参考的是对象所属的类中是否有调用的函数

运行时:参考的是对象所属的类中是否有调用的函数

简单说:编译和运行看左边。

成员变量(静态和非静态):非静态的str1与静态的str2。

在编译时:参考引用型变量所属的类中是否有调用的成员变量(有,编译通过,没有,编译失败)。

在运行时:参考引用型变量所属的类中是否有调用的成员变量,并运行该所属类中的成员变量。

简单说:编译和运行都参考等号的左边

代码示例:

/*
多态中成员(函数和变量)调用特点示例:
*/

class BaseClass {
String str1 = "父类非静态成员变量";
static String str2 = "父类静态成员变量";

void method1() {
System.out.println("base method_1");
}

void method2() {
System.out.println("base method_2");
}

static void method4() {
System.out.println("static base method_4");
}
}

class SubClass extends BaseClass {
String str1 = "子类非静态成员变量";
static String str2 = "子类静态成员变量";

//复写父类的method1()方法
void method1() {
System.out.println("sub method_1");
}

void method3() {
System.out.println("sub method_3");
}

static void method4() {
System.out.println("static sub method_4");
}
}

class PolymorphismDemo {
public static void main(String[] args) {
System.out.println("多态中非静态成员函数调用示例:");
BaseClass bs = new SubClass();
bs.method1();       //sub method_1
bs.method2();       //base method_2
// f.method3();     //编译不能通过,因父类没有method3()函数
System.out.println("----------------------- ");
System.out.println("多态中静态成员函数调用示例:父类");
bs.method4();       //static base method_4
System.out.println("--------------------------");
System.out.println("多态中成员变量调用示例:均为父类");
System.out.println(bs.str1);    //父类非静态成员变量
System.out.println(bs.str2);    //父类静态成员变量
}
}


以下为运行结果:



开发和设计过程

开发过程:不断创建对象、使用对象和指挥对象做事

设计过程:管理和维护对象之间的关系

二,类与对象

1. 类:

具有共同属性(成员变量)、共同方法(成员函数)的一类事物

[b]内部类:[/b]

将一个类定义在另一个类的里面,里面那个类就称为内部类(内置类,嵌套类)。

特点

内部类可以直接访问外部类中的成员,包括私有成员

而外部类要访问内部类中的成员必须要建立内部类的对象。

定义时机:分析事物时,发现该事物描述中还有事物,而且这个事物还在访问被描述事物的内容,这时候就定义内部类。

访问格式

当内部类定义在外部类的成员位置上,而且非私有,可以在外部其他类中直接建立内部类对象

格式:

外部类名.内部类名 变量名=外部类对象.内部类对象;

e.g.: Outer.Inner in=new Outer().new Inner();

当内部类在成员位置上,就可以被成员修饰符所修饰。比如:private:将内部类在外部类中进行封装当内部类被static修饰后,只能访问外部类中的static成员。出现了访问局限

在外部其他类中,内部类为静态,直接访问static内部类的非静态成员

格式:new Outer.Inner().function();

在外部其他类中,内部类为静态,直接访问static内部类的静态成员:可以不用创建内部类对象,直接调用

格式:Outer.Inner.function();

内部类能直接访问外部类中的成员的原因:因为内部类持有了外部类的引用,外部类名.this

注意

当内部类中定义了静态成员,该内部类必须是static的

当外部类中的静态方法访问内部类时,内部类也必须是static的。

内部类定义在局部位置上,也可以直接访问外部类中的成员。同时可以访问所在局部中的局部变量,但必须是被final修饰的。

[b]匿名内部类:[/b]

定义:内部类的简化写法

前提:内部类可以继承或实现一个外部类或者接口

格式:

new 父类构造器([实参列表]) 或 接口()
{
//匿名内部类的类体部分
}


[b]抽象类:[/b]

定义:Java中定义只有功能声明,没有方法体的方法,该方法的具体实现由子类完成,该方法称为抽象方法,包含抽象方法的类就是抽象类。

格式:
修饰符 abstract 返回值类型    函数名(参数列表);


特点:

- 抽象类和抽象方法必须用abstract关键字来修饰

- 抽象类不可以被实例化,也就是不可以用new创建对象

- 抽象类需通过其子类实例化,而子类需要覆盖掉抽象类中所有的抽象方法后才可以创建对象,因此抽象类一定是父类

- 抽象类中可以定义抽象方法和非抽象方法,子类继承后,可以直接使用非抽象方法

[b]接口:[/b]

概念:当一个抽象类中的方法都是抽象的时候,这时可以将该抽象类用另一种形式定义和表示,就是接口。

格式:
interface{}


接口中的成员修饰符是固定的:

1. 成员常量:public static final

2. 成员函数:
public abstract 返回值类型 函数名(参数列表);


特点:

接口中的成员都是公共的权限

接口是对外暴露的规则,接口是程序的功能扩展

接口的出现将“多继承”通过另一种形式体现出来,即“多实现”

一个类在继承另一个类的同时,还可以实现多个接口。

类与类之间是继承关系,类与接口直接是实现关系,可以多实现

接口与接口之间是继承关系,而且接口可以多继承

接口中只能定义抽象方法,必须由子类去实现

成员变量和局部变量区别:

成员变量(2种):实例Field(不以static修饰)和类Field(以static修饰):

范围:定义在类中,在整个类中都可以被访问。

存储:实例Field**堆内存**(随对象的建立而建立,随对象对象被回收而释放);

类Field(静态变量)存储在方法区(共享数据区)的静态区,随着类的加载而存在,随着类的消失而消失。

默认初始化值:有。

局部变量(3种):形参(方法签名中定义的变量)、方法局部变量(在方法内定义)和代码块局部变量(在代码块定义)

范围:只定义在局部范围内(3处)只在所属的区域有效。

存储:栈内存中(作用的范围结束,变量空间会自动释放)。

默认初始化值:无。

2. 对象:

类的具体存在,该类事物实实在在存在的个体。

对象的产生:创建对象的根本途径是构造器(特殊的方法),通过new关键字来调用某个类的构造器即可创建这个类的实例。

[b]匿名对象:[/b]

对象的简化形式(一个没有名字的对象, 创建了一个对象出来,没有赋给一个变量);使用情形:当对对象方法仅一次调用时;作为实际参数进行传递时。

基本数据类型参数及引用数据类型参数传递比较示例:

//基本数据类型参数传递
class Demo {
public static void main(String[] args){
int x = 3;  //方法局部变量
show(x);

/*输出结果为3,因为show()方法中的x为方法局部变量,当主函数调用结束后,show方法出栈。
show方法参数x也随之出栈。main方法打印x的值。此时x指的是main方法中的x变量的值。
*/

System.out.println("x=" + x);

}
public static void show(int x){
x = 4;  //方法局部变量
}
}


//引用数据类型参数传递
class Demo {
int x = 3;      //实例Feild,整个类中都可以访问。
public static void main(String[] args){
Demo d = new Demo();
d.x = 9;
show(d);   //show方法的参数d和main方法中的变量d同时指向了堆内存中同一个实体对象,堆内存中的实体对象的x属性值变为4。

/*show方法出栈,show方法参数d也随之出栈,main方法的变量d依然引用着堆内存中的实体对象,
因此堆内存中的实体对象不会被垃圾回收器清除。
*/

System.out.println(d.x);//输出结果为4
}
public static void show(Demo d){
d.x = 4;
}
}


2. 两者关系

类是对象的抽象,对象是类的实例。

三,构造器和初始化块

1. 构造器(构造函数)

[b]简介:[/b]

一个用于创建实例时,执行初始化的特殊方法。

构造器是一个类创建对象的根本途径,系统默认为类提供一个空参的构造器(其执行体为空),当创建一个对象时,系统默认初始化,将基本类型的Field设为0(数值型)或false(布尔型),引用类型的Feild设为null;若想改变这种默认初始化,即可使用构造器来实现。

一旦自定义构造器后,系统将不会提供默认的构造器(一般建议为该类额外编写一个无参的做保留)。

[b]特点:[/b]

函数名与类名相同

不用定义返回值类型(在构造函数前面加上返回值就只是一般函数了)

没有具体的返回值

多个构造函数是以重载的形式存在的

继承中,子类构造函数执行时,父类构造函数也运行了(原因:在子类的构造函数中,第一行有一个默认的隐式语句:super())

[b]作用:[/b]

给对象进行初始化。

定义时机:

分析事物,该事物具备一些特性或者行为,就把把这些内容定义到构造函数中,若需要参数进行运算就定义参数。

2. 初始化块(构造代码块)

关于局部代码块:局部代码块可以定义局部变量的生命周期

class IfDemo{
public static void main(String[] args){
{
int m = 89;
System.out.println("Hello World..." + m);
}
/*
*变量m是局部变量,生命周期仅在局部代码块括号中,当代码执行到局部代码块右括号外,变量m便消失了。
*局部代码块外的代码当然也就访问不到变量m了。
*/
//System.out.println("over..." + m);
}
}


[b]作用:[/b]

给对象初始化,定义的是不同对象共性的初始化内容对象一建立就运行,而且优先于构造函数执行。

[b]与构造函数区别:[/b]

构造代码块是给所有对象进行统一初始化,而构造函数是给对应的对象初始化。

[b]代码示例:[/b]

class Person {
private String name;
private int age;
//构造代码块,可以给所有对象进行初始化;
{
System.out.println("Running!");
}

Person() {
System.out.println("nane="+name+"...age="+age);
}

Person(String name) {
this.name=name;//this 代表它所在函数所属对象的引用:哪个对象在调用this所在函数,this就代表哪个对象,该处为作用一
System.out.println("nane="+name+"...age="+age);
}

Person(String name,int a) {
//this.name=name; //该句将少打印"name:null...age:0"
this(name); //this(name),this语句用于构造函数之间的调用,将打印"name:null...age:0",this语句只能定义在构造函数的第一行,因为初始化要先执行,该处为作用二
age=a;
System.out.println("nane="+name+"...age="+age);
}

public void setAge(int a) {
if(a>0 && a<130)
age =a;
else
System.out.println("age非法!");
}

public int getAge() {
return age;
}

public boolean campare(Person p) {
return this.age==p.age;//函数内部要用到调用该函数的对象时,这时用this来表示这个对象,该处为作用一
}
}

class PersonDemo2 {
public static void main(String[] args) {
Person p1=new Person();
Person p2=new Person("小明");
p2.setAge(25);
System.out.println(p2.getAge());
Person p3=new Person("小亮",26);
Person p4=new Person("小贤",24);
System.out.println(p4.campare(p3));
}
}


运行结果:

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: