1. 面向对象的编程设计思想(第三章内容)
区别于面向过程的设计思想
面向对象,封装过程在对象的内部,合适的方法应该出现在合适的类里面,(张三的名字让张三写最合适,让李四写并不合适)让对象更了解自己的内部,调用对象来调用方法。首先考虑作用域中的对象,而不是考虑通过过程达到,再考虑对象,类应该有怎样的属性和方法,最后考虑作用域中对象与对象之间的关系,类与类之间的关系。
对象与类的关系
本质是面向类的编程,对象用计算机语言对问题的描述,对象通过属性(也可以叫成员变量)和方法来分别对应事物所具有的静态属性和动态属性。
类就像脑子中抽象的一种事物所具有的特点(一类事物的抽象,拥有静态属性,动态属性来下定义,定义这个类)其中静态属性对应成员变量,动态属性对应方法。瓶子
对象(也可以叫实例)这一类事物具体的某一种特征的具体的某个东西叫做对象。某一个瓶子(谁谁的某个怎样的瓶子)
类可以衍生出多个对象,类可以认为是一个模板,其衍生出的对象应具有他的静态,动态属性。但由于对象的不同其在类中的特点都有,但取值不同,所以区别了每个对象,每个对象都有自己的属性,区别于其他对象不同的属性。
类与类之间的关系
对象与对象之间的关系
1,关系与关系(弱):关联关系(最不紧密)常用:一个类的方法是另外一个类的对象
2,继承关系(强):(一般和特殊)…是一种…说的通就是继承关系(球类运动员是一种运动员,球类运动员从运动员中继承,篮球运动员是一种球类运动员,篮球运动员又从球类运动员中继承)这种关系很有可能派生出一个继承树,一个类可以从多个类中继承,同时也可以被多个类继承,从多个节点中(基本的),衍生出多个(特殊的),与c++中的多重继承相关。
3,聚合关系(强):(整体和部分的关系)谁谁是谁谁的一部分,说通之后就是聚合关系。也可以细分为聚集关系和组合关系,聚集关系往往成员之间是可以分开的(一个部分的。。也属于别的整体),但组合关系中成员与整体之间往往是密不可分的(一个部分只属于某个整体)。
4,实现关系(父类与子类之间的关系):去…,用车,用…车,怎样去,继承子类,通过某种方法实现叫实现关系。
5,多态:以后介绍。
对象和类的分析。(方法:找名词)
例1:
分清名词是类,还是方法。
旅行社,机票,旅客,账簿,目录是类。
机票所具有的属性:价格,时间,班次
……机票所具有的方法:作废,显示价格,显示航班时间。
方法与所需目的有关才需要封装在此类里,否则并不需要封装。
Java与面向对象
必须先定义类才能有对象,对象是java的核心。
对象是静态属性(成员变量)动态属性(方法)的封装体。
就像写程序时,写public class 在这个class中写成员变量,和方法。
这个成员变量(属性)应该有他的类型。方法应该有返回值,也可以没有返回值。
定义好类之后,开始做一个类的对象出来,类名 对象名 new 类名
J2sdk本身提供了许多类供编程人员使用,编程人员本身也可以定义自己的类(string,system)
为什么使用面向对象
Reusebility可重复使用性,属性方法的复用(同时),extensibility可扩展性,可维护性…比面向过程高级,还有更高级的—面向组件的编程,component-orinted,向更高级的抽象(所有语言可以互相访问)
Java中的面向对象与内存
6, class关键词(用class定义一个类)
成员变量(属性,class静态属性):声明—初始化(赋值)—用值
成员变量与局部变量区别:成员变量可以是java中的任何一种数据类型(包括基本类型和引用类型),其可以不初始化(也就是赋值),其有默认初始化。注意class与class之间同名属性,其实不一样。
引用类型(一小块内存指向一大块内存,指针,调用):除了8种基本类型之外所有都是引用类型—String s;(占两块内存,未初始化之前内存中装的是空值—null,与基本变量占一块内存不同)
S = newString(“hello world”);(new出来的东西<对象>在heap
(堆内存动态分配内存的当不用时,就是垃圾垃圾收集器会回收)里)
所谓new就是在内存中命名一块空间,所有的引用类型全部是指针
变量(对象)对class的引用就是指针,类是静态的在代码区里,类的每个成员变量在每个类中都有不同的值(除了静态变量)。方法只有一份,执行的时候才占内存。
对象的创建和使用:
使用对象.成员变量(或来引用对象的成员变量)。
使用对象.方法
同一类的每个对象有不同的成员变量储存空间。
同一类的每个对象共享该类的方法。
内存中类和对象的关系
局部变量c1,c2在steak里,引用class c时用c1.i使其指向heap里的new对象中的属性中的i。
构造函数(构造方法)
New + 构造方法 创建一个新的方法
必须和class名相同,不能有任何的返回值,不能写void
方法调用完成之后,占内存中所有局部变量占用内存消失(局部变量消失),对象不会消失(留在heap里),当没有定义构造函数时,编译器为类自动添加
类名(){}的构造函数(空的构造方法,默认自定义初值)
构造方法出现的问题:
加入void 构造方法变成普通方法,构造方法没有返回值
普通方法调用:引用名.方法名(穿值)
构造方法:类名 对象名=new 方法名();
约定俗成:
Class名大写,变量名方法名首字母小写,运用驼峰标示:如果名字由好几个单词构成,除了第一个词之外,其他的词都应该大写。
没有任何引用指向堆内存中的内存,垃圾收集器会收集它。
方法的重载
一个类中可以定义多个名字相同的方法,参数(类型)不同,根据参数输入类型可以调用不同的方法。重载与重名不同,尽管可能返回值有无不同但只要输入参数类型相同,方法名字相同,就是重名而并非重载。除了普通的方法以外,构造方法也可以构成重载。
对象的创建和使用
必须使用new关键字来穿件对象
对象.用成员变量或来引用对象的成员变量
使用对象引用.方法来调用对象的方法
同一类的每个对象有不同的成员变量储存空间
同一类的每个对象共享该类的方法
非静态的方法是针对每个对象进行调用(在没有static的情况下)
This:一般出现在方法中,当对象进行使用时才决定this指的是谁,此前不一定,用于避免重名问题,此后this永远代表对象本身(在堆内存中),此后进行的一系列运算都是对象的值和变量类型。
Static:static声明的成员变量为静态成员变量,他是该类的成员变量,第一次使用时被初始化,对于该类的所有对象static只有一份(不向普通《非静态》成员变量,每个对象都有一份)。在data内存中一直存在无论是否有对象,没有对象也可以访问这个变量,用class名.静态变量名(注意字符串常量也在data中)与常量不同该静态变量可以改变
静态变量可以用于记对象数(基础类型不存在引用只有一块内存)
Static声明的所有方法为静态方法,静态方法中只能引用的东西。
Package和import:为了避免类的重名冲突。给包起名的方法:约定俗成—把公司的域名倒过来。(如com.bjsxt.java140)class必须位于正确目录下,如果想在另外一个类中使用该类,要写全这个名字。<该类源代码可能会产生影响>,
Import 域名(包裹).类名(或者*,其中的所有类都引进)
(提供类的包裹在java jrelib 运行时《rt》中)Java.lang提供java语言核心类如String,math,integer,System,thread.
Java.awat 包含了抽象窗口工具集,用来构建和管理应用程序的图形用户界面(gui)
Java.applet 包含了applet运行所需要的类
Java.net包含执行与网络想相关输出的类。
Java.io包含提供多种输入输出功能的类
Java.util包含一些实用工具,如定义系统特性,适用于日期日历相关的函数。
Jar -cvf用命令提示符可以生成jar包。
Classpath中设置jar包的位置设置进去就可以打开其中的所有的class文件。
继承和权限控制:
Public关键字,访问控制符,权限修饰符(private,default,protected,public)
继承:类的继承,extends关键字实现继承机制,通过继承子类拥有了基类(superclass)所有的成员变量和方法,java只允许单继承不允许多继承(只有一个爸爸),多重继承应有意义,多重接口可以解决。
继承在堆内存中显示为(子类中套有父类对象,以及类对象所有的成员变量),
所以子类比父类大,子类对象包含父类对象
访问控制通过访问修饰符来完成,访问修饰符可以修饰成员变量,成员方法
可以显示class名
Private (私有的)最严格的权限修饰符:只有在该class里可以访问,在其他class中无法访问
Default(默认权限,包权限):被修饰对象前无访问修饰符认为是default修饰,
同一个包里的其他类可以访问该方法或者成员变量
Public:在所有位置都可以访问。
Protected(受一定保护):除了类内部,同包,子类<子类不一定同包>也可以访问。
与private不同,子类索然继承值,但不能访问。
对于class的权限修饰只能用public或者default
在继承时,子类必须重写父类的构造方法
重写方法不能使用比父类更严格的权限。
Super关键字,super来引用基类的对象,this是对当前的引用(指向当前对象),super是对当前对象中父类的的对象进行引用(指向当前对象中的父类对象)。
继承中的构造方法:
子类可以在自己的构造方法中使用super调用其父类的构造方法,用this调用本类的其他的构造方法。Super (参数);调用父类构造方法。This(参数);调用本类的构造方法。若调用了父类的构造方法,一定写在子类构造方法的第一行。
而且若有构造方法一定调用父类构造方法,若不调用,自动默认调用父类空值构造方法。
如果子类的构造方法没有调用父类的构造方法,系统默认调用父类构造方法中没有参数的构造方法。若不满足上述条件,则编译出错。
在new某个类的对象时,自动使用该类的构造方法。
具体见person package
Jdk提供的类——object类
object:http://docs.oracle.com/javase/1.5.0/docs/api/index.html
object类中的常用方法
java由于不可以多继承,java提供了一个根基类,所有的类都要从这个类中继承
这个类就是object类。
Public class Person{}=public class Person extends object{}它是classroot。
object类中的常用方法之toString() 方法
返回值:String(代表对象的字符串)
描述当前信息的有关信息
在进行String类型与其他类型数据进行连接时自动调用该对象的toString()方法
转换非String类型变量变为String类型
toString 方法每个类都应该重写,注意返回值是String类型,默认toString返回值前面是类名后面是该类的阿西编码(可以找到类位置的16进制码)。
Hashcode(hashcodes table根据hashcode编码表可以在内存中找到某个对象)
Object之 equals方法
Equals用来比较对象所包含的内容是否相同(若简单地比较路径<引用>)
两个对象首先不能为空,当两个对象都指向同一个对象,x==y才会返回true。
所以Equals方法也应该重写。重写时勿忘加static让其可以使用。
Jdk中date,string等类已经重写了equals方法(object.equals())。
Instanceof可以去对象的类型,从而比较是否相同或者输出。
对象转型(casting)
分为两种类型——向上转型,向下转型(与int转short等相似)
一个父类的引用型变量可一指向其子类对象。
注意若父类类型转为子类类型(父类引用指向子类对象),只能访问父类的属性。比如animal类型a转换为dog——a=new dog(m,n),此时他变成了一只狗,但系统会认为他只是一只普通的animal。可以进行强制转换。
Dog d1=(dog)a;d1=a;
面向对象最核心机制:动态绑定(多态)(迟绑定)
在执行期间,而非编译期间,判断所引用对象的实际类型,来进行方法的引用。
运行之后是根据实际来判定方法调用,而非引用类型。动态绑定指的是,实际绑定的(new的是谁)用的就是谁的方法,而非简单的引用方法,所以叫动态绑定。
最核心内存分析:(见test4)<注意不能随便传值>
若重写了父类方法,在new对象时(子类套父类),在父类的内存里就有一个指针指向子类重写的方法。从而达到了空前的可扩展性。
多态的三个条件,1,要有继承2,要有重写3,父类引用指向子类对象(三个条件一旦满足)
实际中如果对某个对象引用父类方法,实际是哪类对象就引用那类的方法,而非父类的方法。
游戏物体的多态包装:
如飞机大战游戏。将子弹和敌方飞机定义为对象。将显示其图形的方法,定义为若这个对象是子弹则画出子弹的图形,如果是敌方飞机则定义为敌方飞机的类型(当然敌方飞机也分为好多种,可以构建其子类,敌方飞机1,敌方飞机2,敌方boss…)如果临时再加入一个新的类型的敌人,这种情况,首先继承敌人这个类,重写,父类中的Draw方法,系统根据对象运行方法,这里叫多态,给程序的可扩展性带来了极大的好处。
抽象类
Abstract修饰类叫抽象类,修饰方法叫抽象方法。父类中由于多态,自己的方法只需要定义,不需要运行,但父类本身并不知道自己的子类如何定义。
只有定义没有实现,叫抽象方法。当一个类含有抽象方法时,这个类也得定义为抽象类,abstractclass 类名。但此时不能再定义一个对象为这个类的对象,而且子类必须对这个抽象类进行方法重写。 此时这个抽象类必须被继承,且这个子类若也为抽象,一定循环下去,找到一个非抽象的子类重写这个方法。抽象类不能被实例化,抽象方法只要生命不需要实现。
Final关键字: (只读,不写)
可以修饰变量,方法,类。Final的方法不能被重写,final的变量为常量(与static不同,static可以根据每个对象的属性进行改变但,final不可以。),final的类不能被继承。Final的形式参数在方法内部不能被改变(因为要传实参。)
如果传一只猫,这只猫只能指向一个内存。(如public final class math不能被继承或者重写)
接口(面向对象的最后一个概念)
由于java不能用多继承,只支持单继承,所以产生接口,接口可以帮助我们。
接口(interface):接口是一种特殊的抽象类。其中所有的方法都是抽象方法,不需要实现的,其中所有的成员变量都是具有public,static,final属性的。
定义它:
Public interface runner{
Publicstatic final int id=1;//蓝色可以不写,写不写前面的内容都是一样
Public void start();
Public void run();
Public void stop();
}
为什么要定义其所有成员变量为final:为了修正c++中多继承的易出错问题(当多个父类对象拥有相同成员变量时)。<其实这个变量并不属于这个类>
所有的方法都是abstract的所以,每个方法都不用考虑实现,只需考虑返回值(与子类有关),局部变量。
多个无关的类可以实现同一个接口,一个类可以实现多个无关的接口,与继承类似,接口与实现存在多态性(父类与继承也存在多态性<动态绑定>)
定义java类的格式 clss<name>[extends<superclass>][ implements <interface>]
在子类中,这些未实现的方法必须全部被实现。
, 比如接口(painter singer)与类(student teacher)。如果singer a=new teacher();则只能调用singer的方法,和其中的成员变量,其他看不到,但也可以将其强制转换。如teacher b=(teacher)a;
接口与抽象类的不同主要在于成员变量,方法是否都是抽象方法。
接口的进一步理解:
interface Comparable
中写了怎样比较大小,什么样是大,什么样是小,这样在子类比较时,不用每一种类型比较大小的时候都写一个方法,无论怎样的类型,都只需要一个算法实现,达到了可扩展性。
同时接口之间可以相互继承,且不用实现父类接口。
两个接口中有两个名字相同的方法,一个子类同时实现这两个接口,若这两个方法的返回值相同,则重写时系统默认这两个方法被同一个方法重写,若返回值不同则无解。(若输入值不同则重写可以认为构成重载)
总结:内存分析很重要
对象和类,面向对象,class,new(引用,构造方法),方法重载,this,static,package&import,访问修饰符(private 成员变量只能看不能用),继承,重写,final,Object toString,Object equals,对象转型(向上转型,向下转型),多态(继承,重写,父类对象指向子类方法),abstract class,interface(implements)。