您的位置:首页 > 编程语言 > Java开发

面向对象

2016-04-06 14:29 429 查看

3.1 面向对象概念

3.1.1 理解面向对象

(1)面向对象是相对面向过程而言;

(2)面向对象和面向过程都是一种思想;

(3)面向过程:强调的是功能行为,“过程”可以理解为动作。面向对象:重点强调具体的事物,将功能封装进对象,强调具备了功能的对象;

(4)面向对象是基于面向过程的。

例如:将大象装入冰箱,使用面向过程的思想步骤为:

①将冰箱打开(函数1);

②将大象放入(函数2)冰箱;

③关上(函数3)冰箱门。

这些动作便是面向过程的体现。C语言就是使用面向过程思想的语言,编写时都是使用函数(方法,动作)来实现的。

使用面向对象的思想步骤为:

①冰箱打开(fridge.open);

②冰箱存储大象(fridge.storage);

③冰箱关上(fridge.close)。

面向对象强调的是冰箱,而这些动作都是冰箱应该具备的动作。只要找到了冰箱,就可以操作冰箱的这些动作。

3.1.2 面向对象的特点

(1)面向对象是一种思想,是符合现在人们思考习惯的一种思想。

(2)面向对象的出现将复杂问题简单化。

(3)面向对象将过程中的执行者,转换成了指挥者。面向对象基于面向过程,将过程进行封装封装到了对象中。

例如:你去电脑城买电脑,面向过程的思想:①查资料,网络,报纸,了解硬件参数信息;②询价,砍价;③装机,并检查;④运输。

面向对象的思想:找老师(懂行的人)一起陪着去,对象:老师。①老师帮我看看这些信息;②老师帮我询价,砍价;③老师帮我监督;④老师运输。只要指挥老师做事情即可,因为老师具备这些功能。

(4)解决问题时:先找具备所需功能的对象,如果没有就造一个具备所需功能的对象。

例如:人开门,解决问题就是先找到该问题领域中涉及的对象。

①名词提炼法:人、门

②开是一个动作。

开定义在人对象中,还是门对象中呢?这个功能定义在哪个对象中最合适,就定义哪个对象中。最合适:哪个对象最清楚这个功能。开的动作用使用到了门这个事物中的内容比如门轴等。门最清楚开的动作,所以开应该定义门事物中。

3.1.3 面向对象开发,设计,特征

(1)开发的过程:其实就是不断的创建对象,使用对象,指挥对象做事情。

(2)设计的过程:其实就是在管理和维护对象之间的关系。

(3)面向对象的特征:封装(encapsulation)、继承(inheritance)、多态(polymorphism)

3.2 类与对象的关系

3.2.1 类与对象

(1)类是抽象的,它是具有相同特性的事物的总称,例如:手机。

类里有成员变量描述对象的属性,成员方法描述对象的行为。

(2)对象是具体的,它是客观存在的事物,对象即是该类事物实实在在存在的个体例如:iPhone手机。

类就是对象的模板(template),而对象就是类的一个实例(instance)。

3.2.2 类的定义

生活中描述事物无非就是描述事物的属性和行为。如:人有身高,体重等属性,有说话,打球等行为。Java中用类class来描述事物也是如此。其中属性对应类中的成员变量,行为对应类中的成员函数。定义类其实在定义类中的成员(成员变量和成员函数)。

要定义一个JAVA类,要具备三个条件:第一:类名;第二:类的属性,它主要描述类的形态,也就是“有什么”;第三:类的方法,它描述类的行为,也就是能“干什么”。

例如:类名:手机;

属性(“有什么”):屏幕,CPU,外壳

方法(“干什么”):打电话,发短信

public class Telphone{
//属性
float screen;
float cpu;
//方法
void call(){
System.out.println("打电话");
}
void sendMessage(){
System.out.println("发短信");
}
}


3.2.3 成员变量与局部变量

(1)概念

①成员变量(本类或他类):在类中定义,用来描述对象将要什么,可以被本类的函数或者其他类的函数使用。

②局部变量(本函数中):局部变量只定义在局部范围内,如:函数内,语句内等。

(2) 区别

①作用域不同:局部变量的作用域仅限于定义它的函数。成员变量的作用域在整个类内部都是可见的。

②初始化值。

成员变量:因为在堆内存中,都有默认初始化。

局部变量:没有默认初始化。

③在同一个函数中,不允许有同名局部变量。在不同的函数中,可以有同名局部变量。

④两类变量同名时,局部变量具有更高的优先级。

⑤内存出现的时间和位置不同。

成员变量:当对象创建时,出现在堆内存的对象当中。

局部变量:所属区间被运算时,出现在栈内存中。

⑥生命周期不同。

成员变量:随着对象的出现而出现,随着对象的消失而消失。

局部变量:随着所属区间运算结束,立刻被释放。

3.2.4 对象的创建(类的实例化)与使用

(1)JAVA对象的创建

类名 对象名 = new 类名();

Telphone iphone = new Telphone();

(2)JAVA对象的使用

引用对象的属性:对象名.属性

iphone.screen=5;//给screen属性赋值5


引用对象的方法:对象名.方法名()

iphone.sendMessage();//调用sendMessage()方法


再比如:

class Car//对Car这类事物进行描述
{
String color = "red";
int num = 4;
void show()
{
System.out.println("color="+color+"..num="+num);
}
}
class CarDemo
{
public static void main(String[] args)
{
Car c = new Car();//建立对象
c.color = "black";//对对象的属性进行修改
c.show();//使用对象的功能
}
}


3.2.5 对象内存结构

http://m.blog.csdn.net/article/details?id=7651251#modile.qq.com

进入正题前首先要知道的是Java程序运行在JVM(Java Virtual Machine,Java虚拟机)上,可以把JVM理解成Java程序和操作系统之间的桥梁,JVM实现了Java的平台无关性,由此可见JVM的重要性。所以在学习Java内存分配原理的时候一定要牢记这一切都是在JVM中进行的,JVM是内存分配原理的基础与前提。

堆:存放new出来的对象。

常量池:存放字符串常量和基本类型常量(public static final)以及某些情况下的某些基本数据类型封装类。

对于栈和常量池中的对象可以共享,对于堆中的对象不可以共享。栈中的数据大小和生命周期是可以确定的,当没有引用指向数据时,这个数据就会消失。堆中的对象由垃圾回收器负责回收,因此大小和生命周期不稳定,具有很大的灵活性。

预备知识:

1.一个Java文件,只要有main入口方法,我们就认为这是一个Java程序,可以单独编译运行。

2.无论是普通类型的变量还是引用类型的变量(俗称实例),都可以作为局部变量,他们都可以出现在栈中。只不过普通类型的变量在栈中直接保存它所对应的值,而引用类型的变量保存的是一个指向堆区的指针,通过这个指针,就可以找到这个实例在堆区对应的对象。因此,普通类型变量只在栈区占用一块内存,而引用类型变量要在栈区和堆区各占一块内存。

class Car//对Car这类事物进行描述
{
String color = "red";
int num = 4;
void show()
{
System.out.println("color="+color+"..num="+num);
}
}
class CarDemo
{
public static void main(String[] args)
{
Car c1 = new Car();//建立对象
c1.color = "black";//对对象的属性进行修改
Car c2 = new Car();//建立对象
}
}


只要是用new操作符定义的实体就会在堆内存中开辟一个新的空间。并每一个对象中都有一份属于自己的属性(该属性便是在类Car中描述事物中有color和num的属性)。通过“对象.对象成员”的方式操作对象中的成员,对其中一个对象的成员进行了修改,和另一个对象没有关系。

3.2.6 对象调用的细节

class Car//对Car这类事物进行描述
{
String color = "red";
int num = 4;
void show()
{
System.out.println("color="+color+"..num="+num);
}
}
class CarDemo
{
public static void main(String[] args)
{
Car c1 = new Car();//建立对象
c1.color = "black";//对对象的属性进行修改
Car c2 = new Car();//建立对象
}
}


上述代码执行到“
Car c1 = new Car();
”时有人误以为是通过“class Car//对Car这类事物进行描述”来创建对象的。事实上,在执行main入口方法时,要通过“
Car c1 = new Car();
”创建对象,实际上调用了Car.class文件。可以将上述代码编译运行后,再将Car类删除来证明。因为将上述代码编译运行后,生成了Car.class文件,再将Car类删除后,代码执行到“Car c1 = new Car();”时便会自动调用已经生成的Car.class文件。

上述代码执行到“
c1.color = "black";
” 时有人误以为是将类Car中的color的值改变了。事实上,类Car中的属性只是描述事物中有什么。“
c1.color = "black
“;”改变的其实是c1指向内存中的对象中的color的值。即“
c1.color = "black
“;”改变的是对象的属性而不是类的属性。

3.2.7 匿名对象的创建与使用

new Dog().jump(); //创建一个匿名对象并直接调用这个对象的方法(jump)


注意:匿名对象使用完一次后就没有了,下次找不到它。

匿名对象的使用:

(1)当对象对方法进行一次调用的时候,可以使用匿名对象来简化。

//  Car c = new Car();
//  c.run();
new Car().run();


当对对象的成员进行多次调用时,必须起名字。

(2)可以将匿名对象作为实际参数进行传递。

//  Car c = new Car();
show(new Car());
//定义功能,对汽车进行改装
public static void show(Car cc) {
cc.color = "black";
cc.num = 3;
cc.run();
}


3.3 封装

3.3.1封装的概念

将类的某些信息隐藏在类的内部,不允许外部程序直接访问,而是通过该类提供的方法来实现对隐藏信息的操作和访问。

3.3.2封装的好处

(1)只能通过规定的方法访问数据;

(2)隐藏类的实例细节,方便修改和实现。

【例16-1】类未封装性使用实例。

package com.FengZhuang;
public class Person {
String name;
int age;
void talk(){
System.out.println("我叫"+name+";我的年龄是:"+age);
}
}
package com.FengZhuang;
public class Test {
public static void main(String[] args) {
// TODO 自动生成的方法存根
Person p=new Person();
p.age=-100;
p.name="张三";
p.talk();
}
}


运行结果:



从上面的运行结果可知,给age赋值为-100时,显然是一个不合法的值,最终打印出来就会显示错误的信息。在程序设计时,这是绝对不允许的。于是,我们就会使用封装的思想。

3.3.3封装的实现步骤

(1)修改属性的可见性:设为private;

(2)创建getter/setter方法:用于属性的读写;

(3)在getter/setter方法中加入属性控制语句:对属性值得合法性进行判断。

【例16-2】类封装性使用实例。

package com.FengZhuang;
public class Person {
private String name;//修改属性的可见性:设为private,Test类不能//直接通过创建p对象再使用p.name修改其值
private int age;
void setName(String name){//创建getter/setter方法:用于属性
//读写
this.name=name;
}
void setAge(int age){
if(age>0)
this.age=age;
}
String getName(){
return this.name;
}
int getAge(){
return this.age;
}
void talk(){
System.out.println("我叫"+name+";我的年龄是:"+age);
}
}
package com.FengZhuang;
public class Test {
public static void main(String[] args) {
// TODO 自动生成的方法存根
Person p=new Person();
p.setAge(-100);
p.setName("张三");
p.talk();
}
}


运行结果:



当给age赋值为-100时,在Person中的属性里设置了条件,因-100<0,所以-100没有赋值给age.所以age的值仍然是初始值0.这便是用private将属性封装的思想。当然,也可以使用private封装方法。

【注意】

private int age;//私有的访问权限最低,只有在本类中的访问有效。


私有的成员:其他类不能直接创建对象访问,所以只有通过本类对外提供具体的访问方式来完成对私有的访问,可以通过对外提供函数的形式对其进行访问。

记住:私有仅仅是封装的一种体现形式而已。

3.4 构造函数

3.4.1 概念

构造函数是定义在JAVA类中的一个用来初始化对象的函数,构造函数与类必须同名且没有返回值,也不能使用void来修饰。

3.4.2 特点

(1)函数名与类名相同;

(2)不用定义返回值类型;

(3)没有具体的返回值;

(4)任何用class定义的类中,都有一个默认的空参数的构造函数。用于给该类对象进行初始化。如果该类中指定了具体的构造函数,那么默认的构造函数就没有了。

3.4.3 作用

(1)使用new+构造函数 创建一个新的对象,并且自动执行构造函数里的内容。

Telphone iphone = new Telphone();

new:用于在堆内存中开辟空间的关键字,用于创建对象。

Telphone:明确要创建Telphone类的对象。

():创建Telphone类的对象,需要通过哪个构造函数进行初始化。这里需要用到一个无参的构造函数。

(2)给对象进行初始化。

创建的每个对象都是一个实体,每个实体必须要进行初始化后才可以使用。实体的初始化是需要通过动作完成的。这个动作就是构造函数。构造函数作用就是给对象进行初始化。

(3)普通函数的调用通常使用“.”,例如:a.show( ) ,而构造函数不能被直接调用,必须使用new+构造函数的方式在创建对象时才会自动调用。

(4)无参构造函数的使用

package com.gouzao;
public class GouzaoWay {
GouzaoWay(){                     //创建了一个无参的构造函数
System.out.println("我是无参构造函数");
}
package com.gouzao;
public class TestGouzaoWay {
public static void main(String[] args) {
GouzaoWay a=new GouzaoWay();
}
}


运行结果:

我是无参构造函数

从上面我们可以看到,当在main中创建对象时,自动调用了类GouzaoWay的构造函数。

(5)有参构造函数的使用(它可以为初始成员变量赋值)

package com.gouzao;
public class GouzaoWay {
int a,b,c;
GouzaoWay(int a1,int b1,int c1){  //创建了一个有参的构造函数
a=a1;
b=b1;
c=c1;
System.out.println("我是有参构造函数");
System.out.println("a="+a+";b="+b+";c="+c);
}
}
package com.gouzao;
public class TestGouzaoWay {
public static void main(String[] args) {
GouzaoWay p=new GouzaoWay(1,2,3);//通过有参的构造函数调用了构造函数,并且给对象中的成员变量赋初始值
}
}


运行结果:

我是有参构造函数

a=1;b=2;c=3

具体案例见E:\Java demo\GouzaoWay

3.4.4 对象内存初始化(构造函数)

3.5.重载

3.5.1 重载概念

如果同一个类中包含了两个或者两个以上函数名相同,函数参数的个数、顺序或者类型不同的函数(统称为参数列表不同),则称为函数的重载:

public class Chongzai {
public void show(){                     //show函数无参数
System.out.println("Welcome!");
System.out.println("***********");
}
public void show(String name){          //重载show函数,一个字符串参数
System.out.println("Welcome!"+name);
System.out.println("***********");
}
public void show(String name,int age){  //重载show函数,两个参数
System.out.println("Welcome!"+name);
System.out.println("age:"+age);
System.out.println("***********");
}
public void show(int age,String name){  //重载show函数,两个参数顺序不同
System.out.println("Welcome!"+name);
System.out.println("age:"+age);
}
}
3.5.2 重载的使用
当调用被重载的函数时,JAVA会根据参数的个数和类型来判断应该调用哪个重载函数,参数完全匹配的函数将被执行。如:
public class TestChongzai {
public static void main(String[] args) {
Chongzai a=new Chongzai();
a.show();
Chongzai b=new Chongzai();
b.show("Mike");
Chongzai c=new Chongzai();
c.show("Mike",20);
Chongzai d=new Chongzai();
d.show(21,"Jack");
}
}


运行结果:



3.5.3 函数重载的现实意义

在现实生活中,函数重载的思想比比皆是。例如,假设类名为“人”,类的行为有“洗”,但是“洗”的总数众多,有洗澡,洗衣服,洗手等等。

class Person{
void Xi(){
System.out.println("洗衣服!");
}
void Xi(int a){
System.out.println("洗澡!");
}
void Xi(String b){
System.out.println("洗碗!");
}
}


3.6 this关键字

this代表其所在函数所属对象的引用,换言之:this代表本类对象的引用。this还可以调用本类中的构造函数。

3.6.1 作用

(1)当局部变量和成员变量同名的时候,可以用this来区分。当定义功能时,功能内部使用到了调用该功能的对象。这时就用this来表示。

(2)使用this调用本类中的构造函数。

3.5.2 区分局部变量和成员变量

使用this调用成员变量(不是局部变量)与成员函数,记住一句话:把this当成一个对象!

我们经常创建一个对象,例如:Dog dog=new Dog(); 其中Dog类中有成员变量:“String name;int age;”当dog 对象调用Dog类中的变量时,通常使用以下方式:“dog.name=”哈哈”;dog.age=3;”我们在使用this时,也可以将this直接看成一个对象,例如有以下代码:

package com.ThisExample;
public class ThisExample {
String name;
void talk(){
System.out.println("my name is:"+this.name); //this可看成一个对象,调用了ThisExample类中的成员变量name,这里this可以省略
}
}
package com.ThisExample;
public class TestThisExample {
public static void main(String[] args) {
// TODO 自动生成的方法存根
ThisExample a=new ThisExample();
a.name="哈哈";
a.talk();
}
}


运行结果:



有一种情况this不可以省略:

package com.ThisExample2;
public class ThisExample2 {
String name;
void talk(String name){
System.out.println("my name is:"+name);
}
}
package com.ThisExample2;
import com.ThisExample.ThisExample;
public class TestThisExample2 {

public static void main(String[] args) {
// TODO 自动生成的方法存根
ThisExample2 b=new ThisExample2();
b.name="哈哈";
b.talk("哦哦");
}
}


运行结果:

my name is:哦哦

可以发现,程序中并没有调用成员变量,若要调用成员变量,必须将name改成this.name,即可以看成this这个对象调用了成员变量name.当函数中参数列表的名称与成员变量名称一致时,可以使用this区分两者。例如:

public class Person{
String name;
int age;
String address;
void Person(String name,int age ,String address){
this.name=name; //将参数列表中的name赋值给成员变量name
this.age=age; //将参数列表中的age赋值给成员变量age
this.address=address; //将参数列表中的address赋值给成员变量address
}
}


3.6.3 调用本类中构造函数

this还有另外一个重要的作用,就是调用本类中的构造函数。构造函数之间的调用可以使用this关键字,后面跟上小括号,指定具体的实参即可明确要调用的构造函数。

注意:调用本类中构造函数的this语句必须定义在构造函数的第一行,因为初始化动作要先完成。

public class Person{
String name;
int age;
String address;
void Person(String name,int age){
this.name=name; //将参数列表中的name赋值给成员变量name
this.age=age; //将参数列表中的age赋值给成员变量age
void Person(String name,int age ,String address){
this.name=name; //将参数列表中的name赋值给成员变量name
this.age=age; //将参数列表中的age赋值给成员变量age
this.address=address; //将参数列表中的address赋值给成员变量address
}
}


可以发现以上代码重复较多,而面对对象程序设计最重要的一点就是要减少重复代码,于是,我们可以改写如下:

public class Person{
String name;
int age;
String address;
void Person(String name,int age){
this.name=name; //将参数列表中的name赋值给成员变量name
this.age=age; //将参数列表中的age赋值给成员变量age
void Person(String name,int age ,String address){
this(name,age)//直接调用上一个构造函数,减少代码重复
this.address=address; //将参数列表中的address赋值给成员变量address
}
}


3.7 局部代码块和构造代码块

局部代码块一般定义在函数中,它控制变量的生命周期。执行完局部代码块,局部代码块内的局部变量就消失了。

构造代码块一般定义在类中,它可以给所有对象进行初始化。创建一个对象,构造代码块就执行一次。

构造代码块与构造函数的区别:给所有的对象初始化!只要创建一个对象,构造代码块就执行一次。构造函数只对对应的对象初始化!

class Person
{
private String name;
private int age;
{//构造代码块(定义在类中),它可以给所有对象进行初始化。
System.out.println("cons code run");
cry();
}
Person()//对对应的对象进行初始化。
{
System.out.println("Person run");
//      cry();
}
Person(String name,int age)
{
this.name = name;
this.age = age;
System.out.println(this.name+":::::"+this.age);
//      cry();
}
public void  cry()
{
System.out.println("哇哇...");
}
}
class ConsCodeDemo
{
public static void main(String[] args)
{
Person p = new Person();
Person p1 = new Person("lisi",29);
{//局部代码块(定义在主函数中),控制变量的生命周期。
int x = 9;
System.out.println("x="+x);
}
}
}


3.8 static关键字

用于修饰成员(成员变量和成员函数)与代码块。

3.8.1 静态成员变量

(1)被static修饰的成员变量,被所有对象所共享;

(2)静态随着类的加载而加载,随着类的消失而消失;

(3)优先于对象存在;

(4)静态成员可以直接被类名所调用。

因为静态成员变量随着类的加载而加载,随着类的消失而消失,优先于对象存在。所以,静态成员变量可以使用类名直接访问,也可以使用对象名进行访问。

package com.staticExample;
public class Helloworld {
static String speak="Hellowold!";
public static void main(String[] args) {
//静态变量可以直接使用类名访问,无需创建对象
System.out.println("通过类名访问speak"+Helloworld.speak);
//使用对象名访问静态变量
Helloworld a=new Helloworld();
System.out.println("通过对象名访问speak:"+a.speak);
//通过对象名修改静态变量的值
a.speak="Exchange";
Helloworld b=new Helloworld();
System.out.println("通过类名访问speak:"+b.speak);
}
}


运行结果:



注意:我们可以基于一个类创建多个对象,每个对象拥有自己的成员变量,互相独立;static修饰的成员变量属于整个类所有,而不是某个对象所有,即被类的所有对象所共享。

3.8.2 静态成员函数

与静态变量一样,可以使用类名调用静态函数,也可以通过对象名调用。

package com.staticExample;
public class Helloworld2 {
//使用static关键字声明静态函数
public static void print(){
System.out.println("我是静态函数!");
}
public static void main(String[] args) {
//直接使用类名调用静态函数
Helloworld2.print();
//也可以通过对象名调用
Helloworld2 a=new Helloworld2();
a.print();
}
}


运行结果:



注意:静态函数中不能直接调用非静态成员变量!不能调用普通成员变量!

package com.staticExample;
public class Helloworld3 {
String name1="Mike";//普通成员变量
static String name2="迈克";//静态成员变量
public static void main(String[] args) {
System.out.println("不能直接调用非静态变量:"+name1);
System.out.println("直接调用静态变量:"+name2);
}
}


3.8.3 静态代码块

static {
......
}


静态代码块在类加载时就执行,且只会执行一次。同时,静态初始化块只能给静态变量赋值,不能初始化普通的成员变量。

package com.staticExample;
public class Helloworld4 {
int num1;//声明普通成员变量num1
int num2;//声明普通成员变量num2
static int num3;//声明静态变量num3
public Helloworld4(){//构造函数
num1=91; //声明局部成员变量num1
System.out.println("通过构造函数为变量num1赋值");
//(第三步:构造函数最后执行)
}
{//初始块(第二步:在其次执行)
num2=71;
System.out.println("通过构造函数为变量num2赋值");
}
static{//静态初始块(第一步:首先执行)
num3=83;
System.out.println("通过静态初始块为静态变量num3赋值");
}
public static void main(String[] args) {
Helloworld4 a=new Helloworld4();//立马加载构造函数
System.out.println("num1:"+a.num1);
System.out.println("num2:"+a.num2);
System.out.println("num3:"+num3);
Helloworld4 b=new Helloworld4();//立马再次加载构造函数
//不会再次加载静态初始块
}
}


运行结果:



通过输出结果,我们可以看到,程序运行时静态初始块最先被执行,然后执行普通初始块,最后才执行构造方法。由于静态初始块只在类加载时执行一次,所以当再次创建对象b时并未执行静态初始化块。

3.8.4 使用注意事项

(1)静态方法只能调用静态成员,不能调用非静态成员;

非静态方法可以调用静态成员,也可以调用非静态成员。

(2)在静态方法中不允许出现this,super关键字;

this代表对象,而静态方法执行时还没有对象呢!static对象可以在它的任何对象创建之前访问。

(3)主函数是静态的。

静态是有访问局限性的,只能访问静态的内容。

3.8.5 静态成员变量和非静态成员变量的区别

(1)非静态成员变量又称为实例变量;

静态成员变量又称为类变量。

(2)非静态成员变量,随着对象的创建而存在,随着对象的消失而消失;

静态成员变量,随着类的加载而存在,随着类的消失而消失。

(3)非静态变量存在于对象堆内存中;

静态变量存在于方法区中。

(4)非静态变量只能被对象所调用;

静态变量可以被类名调用,也可以被对象调用。

3.9 面向对象思维模式

(1)对象——首先确定谁去做,其次考虑怎么做。(买饭)

(2)整体与局部——首先考虑整体,其次考虑局部。(电梯:整体(电梯的行为:升降停),局部(电机,门,绳索))

(3)具体与抽象——首先考虑抽象,其次考虑具体。(学东西:首先确定要好好学习,其次可以去图书馆看书,请教他人)(类(手机)是抽象的,对象(iphone)是具体的)

3.10 面向对象设计的终极目标

减少重复代码

3.11 面对对象的三个基本特征

继承,封装,多态

(1)继承

如果类B具有类A的全部属性和方法,而且又具有自己特定的某些属性和方法,则把类A称作一般类,B称作特殊类。

特殊类(B)的对象拥有一般类(A)的全部或部分属性和方法,称特殊类对一般类的继承。

我们称被继承的类A为基类、父类或超类,而称继承类B为A的派生类或子类。

继承的特征:

①传递性;

②清晰地体现了类之间的层次结构关系;

③提供软件复用功能;

④易于维护;

⑤提供多重继承机制。从理论上说,一个特殊类可以继承多个一般类,这便是多重继承。而Java出于安全性和可靠性的考虑,仅支持单继承,而通过使用借口机制来实现多重继承。

(2)封装

封装(Encapsulation)是将代码及其处理的数据绑定在一起的一种编程机制,该机制保证了程序和数据都不受外部干扰且不被误用。理解封装性的一个方法就是把它想成一个黑匣子,它可以阻止在外部定义的代码随意访问内部代码和数据。对黑匣子内代码和数据的访问通过一个适当定义的接口严格控制。

(3)多态性

多态性(Polymorphism,来自于希腊语,表示“多种形态”)是允许程序中出现重名的现象。Java语言中含有方法的重载与成员覆写两种形式的多态。

方法重载:在一个类中,允许多个方法使用同一个名字,但方法的参数不同,完成的功能也不同

成员覆写:子类与父类允许具有相同的变量名称,但数据类型不同,允许具有相同的方法名称,但完成的功能不同。

3.12 包与访问权限

3.12.1 包的概念与使用

当一个大型程序由多个不同的组别或人员共同开发时,用到相同的类名称是很有可能的事。如果这种情况发生,还要确保程序可以正确运行,就必须通过package关键字来帮忙了。

package是在使用多个类或接口时,为了避免名称重复而采用的一种措施。一般在类或接口的最上面一行加上package的声明就可以了,package的声明如下:

package 名称;

经过package的声明之后,同一文件内的接口或类就会被纳入package中。

注意:包名的写法规范:所有字母都小写。

//package cn.njupt.pack.demo;


包是一种封装形式,用于封装类,想要被包以外的程序访问,该类必须public;

类中的成员,如果被包以外访问,也必须public;

包与包之间访问可以使用的权限有两种:

1:public

2:protected:只能是不同包中的子类可以使用的权限。

注:(1)不写权限修饰符就是default权限。

(2)protected权限和default拥有一样的权限,并且可以在不同包子类(必须有继承关系!)中使用,但protected只能修饰成员函数与成员变量,不能修饰类!

3.12.2 import语句的使用

如果几个类分属于不同package,在某个类要访问到其他类的成员时,则必须做以下修改:

①若某个类需要被访问时,则必须把这个类公开出来,也就是说需要将此类声明成public。

②若要访问不同package内某个public类的成员时,在程序代码内必须使用import语句明确指明“被访问package的名称.类名称”。

//创建一个包,名称为com.nupt.a
package com.nupt.a;
public class Person {
public String talk(){
return "OK!";
}
}
//创建一个包,名称为com.nupt.b
package com.nupt.b;
//为访问包com.nupt.a中的Person类,需要使用import
import com.nupt.a.Person;
public class Test {
public static void main(String[] args) {
// TODO 自动生成的方法存根
Person a=new Person();
System.out.println(a.talk());
}
}


运行结果:

OK!

3.12.3 Java的命名习惯

(1)包名中的字母一律小写,如demo.java

(2)类名、接口名应当使用名词,每个单词的首字母大写,如TestPerson。

(3)方法名第一个字母小写,后面的每个单词首字母大写,如talkMySelf()。

(4)常量名的每个字母一律大写,如COUNTER。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  java