谈谈Java对象及三大特性

来源:互联网 发布:金十数据是什么 编辑:程序博客网 时间:2024/05/16 07:42

为什么使用面向对象?

现实世界就是“面向对象的”,现实世界中的任何事物都可以看作是对象,比如人,建筑,交通工具等,而事物都有自己的属性和行为。比如人,它具有各种属性:姓名,性别,身高等,还可以做很多事情:吃饭,睡觉,劳动。

面向对象是采用“现实模拟”的方法设计和开发程序,而面向对象技术利用“面向对象的思想”去描述“面向对象的世界”,实现了虚拟世界和现实世界的一致性,符合人们的思维习惯。

面向对象和面向过程的区别?

面向过程化程序设计只为考虑实现用户的需求,不考虑以后的扩展,如果客户需求有变,那代码改变非常大,耗时也非常大。面向对象设计是根据客户的需求,用继承、封装、多态、抽象去设计程序,代码量虽然比面向过程花程序多出很多,但以后的扩展性

和维护性是相当高效。

面向对象设计类和对象是面向对象中的两个核心概念,类是对某一事物的描述,是抽象的,概念上的定义。对象是实际存在的该事物的个体,是具体的,现实的。面向对象设计的过程就是抽象的过程,分三步来完成,

1.发现类;

2.发现类的属性;

3.发现类的方法。

发现类,比如人,而人的属性有身高,年龄,男or女等,而人的行为(方法)有吃饭,睡觉,洗澡等,设计是一个逐步完调整、完善的过程,所以类图是面向对象设计的”图纸“,同志们一定要善用UML建模工具哈。

抽象时遵循的原则:属性、方法的设置是为了解决业务问题的,如没有必要,勿增加额外的类、属性和方法。

封装(Encapsulation)

封装是类的三大特性之一,就是将类的状态信息隐藏至类内部,不允许外部程序直接访问,而是通过该类提供的方法来实现对隐藏信息的操作和访问。

封装的具体步骤:修改属性的可见性来限制对属性的访问,即每个属性设为private,每个属性创建赋值set,取值get方法。

封装的好处:隐藏类的实现细节,让使用者只能通过规定的方法来访问数据,可以方便地加入存取控制语句,限制不合理要求,例如我们在年龄的set方法中设置年龄必须大于0岁。

class Person{ private String name;  //姓名 private int age;      //年龄 private char gender;  //性别 public String getName(){return name;} public String setName(String name){this.name = name;} private int getAge(){return age;} private int setAge(int age){ if(age > 0){   System.out.println("年龄必须大于0");  }else{   this.age = age;  } }private char getGender(){return gender;} private char setGender(){this.gender = gender;}}



this关键字

this关键字是对一个对象的默认引用,如果成员变量和局部变量同名时,使用this可以解决成员变量和局部变量的冲突。

this调用重载的的构造方法时,只能在构造方法的第一条语句中调用,例如:

public Person(String name,int age,char gender){ this(name,age); this.gender = gender;}


注:因为this是在对象内部指代自身的引用,所以this只能调用实例变量,实例方法和构造方法,也不能调用类变量、类方法和局部变量。

构造方法

何为构造方法?构造方法的名字和类名相同,没有返回值类型,构造的作用主要是在创建对象时执行一些初始化信操作,如给成员属性赋初值。

注:在没有给类提供任何构造方法时,系统会提供一个无参的方法体为空的默认构造方法,一旦提供了自定义构造方法,系统将不会再提供这个默认构造方法,如果要用它,须手动添加。否则会抛异常:Exception in thread  "main" java.lang.Error:构造函数 xxx() 未定义。

方法重载

一个类中包含2个或两个以上的方法,它们的方法名相同,方法参数个数不或参数类型不同,则该方法被重载了,这个过程称为方法的重载,成员方法和构造方法都可以进行重载。

继承(Inheritance)

如果两个类中有相同的方法和属性,则可以提取出来放到一个单独的类中,然后继承这个类,同时保留自己特有的属性和方法。在Java中,继承通过extends关键字来实现,继承是类的三大特性之一,是Java中实现代码重用的重要手段之一。Java中只支持单继承,即一个子类只能有一个直接父类,继承表达的是is  a 的关系。注:在Java中,所有的Java类都直接或者间接的继承了java.lang.Object类,Object类是所有Java类的祖先,在定义一个类时,没有使用extends关键字,那么这个类直接继承了Object类。

继承规则

继承public和protected修饰的方法和属性,不管子类是不是在同一个包里;继承默认权限修饰符修饰的属性和方法,但子类和父类必须在同一个包里;无法继承private修饰的属性和方法;无法继承父类的方法。

重写

如果子类从父类中继承的方法不能满足自身的需求,在子类中可以对父类同名方法进行重写(覆盖)。

重写规则

重写方法和被重写方法必须具有相同的方法名;重写方法和被重写方法必须具有相同的参数列表;重写方法的返回值类型必须和被重写方法的返回值类型相同或者是其子类;重写方法不能缩小被重写方法的访问权限。

super

super代表当前对象的直接父类对象的默认引用,在子类中可以通过super关键字来访问父类的成员。super必须是出现在子类中(子类的方法和构造方法中);可以访问父类的成员,例如父类的属性、方法和构造方法;无法访问父类的private成员。继承关系中的构造方法如果子类中的构造方法没有通过super显示调用父类的有参构造方法,也没有通过this显示调用自身的其它构造方法,则系统会默认先调用父类的无参构造方法,在这种情况下,写不写”super“都是一样的;如果子类的构造方法中通过super显示调用父类的有参构造方法,那将执行父类相应的构造方法,而不执行父类我参构造方法;如果子类的构造方法中通过this显示调用自身的其它构造方法,

在相应的构造方法中应用上两条规则。特别注意:如果存在多级继承关系,在创建一个子类对象时,以上规则会多次向更高一级父类应用,一直到执行顶级父类Object类的无参构造方法为止;在一个构造方法中不允许同时出现this和super语句。

继承关系中的构造方法执行过程例子

class Person{ String name;  //姓名 public Person(){  //super(); 写不写super效果都是一样   System.out.println("execute Person()"); } public Person(String name){  this.name = name;  System.out.println("execute Person(name)"); }} class Student extends Person{ String school; //学校 public Student(){  //super();写不写该语句,效果都一样  System.out.println("execute Student()"); } public Student(String name,String school){super(name); //显示调用父类的有参构造方法,将不执行无参构造方法  this.school = school;  System.out.println("execute Student(name,school)"); }} class PostGraduate extends Student{ String guide; //导师 public PostGraduate(){  //super();写不写该语句,效果都一样    System.out.println("execute PostGraduate()"); } public PostGraduate(String name,String school,String guide){  super(name,school);  this.guide = guide;  System.out.println("execute PostGraduate(name,school,guide)"); }}//测试程序class TestInherit{ public static void main(String []args){  PostGraduate guide = null;  guide = new PostGraduate();  System.out.println();  guide = new PostGraduate("高腾","麻省理工","皮尔老师"); }}输出结果:execute Person()execute School()execute PostGraduate()execute Person(name)execute School(name,school)execute PostGraduate(name,school,guide)


执行guide = new PostGraduate();后,共计创建了四个对象,对,就是四个,没错,你的眼睛没花。按照顺序,依次是Object、Person、School、PostGuaduate,不要忘记除了PostGuaduate还有另外三个对象,尤其是别忘了还会创建Object对象,在执行Person()时会调用它的直接父类Object的无参构造方法,该方法内容为空。执行guide = new PostGraduate("高腾","麻省理工","皮尔老师");后,共计也创建了四个对象,只是调用的构造方法不同而已,依次是Object()、public Person(String name)、public Student(String name,String school)、public PostGuaduate()。继承的缺点:破坏父类的封装性。

抽象类和final

用sbstract修饰的类称为抽象类,抽象类不能实例化,用abstract修饰的方法,则子类必须重写该方法,abstract不能用来修饰属性和构造方法。

问题,如果我们想让人类不被其它类继承,不允许再有子类,应该如何实现呢?如果人类可以有子类,但是增加一个居住地址home,规定只能取固定的值,应该如何实现呢?

可以使用final关键字来实现,用final修饰的类,不能再被继承,用final修饰的方法,不能被子类重写,用final修饰的变量(包括成员变量和局部变量)将变成常量,只能赋值一次。

final跟abstract的那些事

abstract可以用来修饰类和方法,不能修饰属性和构造方法;

final可以修饰类、方法和属性,不能修饰构造方法;

final修饰引用型变量,变量所指的对象的属性值是否能改变?

class Person{ String color; public Person(String color){  this.color = color; }} class Test{ public static void main(String []args){  final Person black = new Person("黑种人");  black.color = "黄种人";        //正确  black = new Person("白种人");  // 错误 }}


对应引用型变量,一定更要区分对象的应用值和对象的属性值两个概念。使用final修饰引用性变量,变量不可以再指向另外的对象,但是所指对象的内容是可以改变的。

多态(Polymorphism)

为什么使用多态?

例如我们要实现主人给宠物喂食功能,给Dog喂食,给Penguin喂食,给抽象类Pet类增加抽象eat()方法,让子类狗狗和企鹅继承Pet并重写eat()方法,实现吃饭功能,创建主人类Master,添加feed()方法,调用Dog、Penguin的eat()方法,实现喂食功能。

public abstract class Pet{ protected String name = "我是谁"; public Pet(String name){  this.name = name;  } // 省略set、get方法 public abstract void eat();} public class Dog extends Pet{ private String strain; //品种 public Dog(String name,String strain){  super(name);  this.strain = strain;} //实现吃饭功能 public void eat(){  System.out.println("狗狗:"+super.name+"吃饭啦!"); }} public class Penguin extends Pet{ private String sex; //性别 public Penguin(String name,String sex){  super(name);  this.sex = sex; }//实现吃饭功能 public void eat(){  System.out.println("企鹅:"+super.name+"吃饭啦!"); }} public class Master{ public void feed(Dog dog){dog.eat();} public void feed(Penguin penguin){penguin.eat();}}



上述例子已经实现了主人给宠物喂饭功能,但是如果要增加一个宠物,该如何实现给宠物喂食功能?当然我们可以在Master类中在增加一个feed()喂食方法,但这样做有如下缺点:每次增加宠物的时候都要修改Master类代码,如果宠物很多,那要重载很多的eat()方法。

如果能是实现如下效果就好,Master类中只定义一个feed()方法,可以实现对所有的宠物喂食,不管领养多少宠物,无需修改Master类源代码,能够实现吗?答案是肯定的,通过多态可以实现。

什么是多态?

多态是具有表现多种形态的能力的特征,更专业的说:同一个实现接口,使用不同的实例实现不同的操作。多态带给我们的好处?

1.可替换性,多态对已存在的代码具有可替换性;

2.可扩展性;

3.接口性,多态是通过方法签名向子类提供一个共同的接口,由子类来完善或者覆盖它而实现的;

4.灵活性,多态提高使用效率;

5.简化性;

注:多态并不能够解决提高性能和执行速度的问题,因为他是基于动态装载和地址引用,或称动态绑定,Java提供两种方法绑定,一种即静态绑定,动态绑定,静态绑定发生在编译期间,由编译器完成,可以提高代码的执行速度,动态绑定发生在运行期间,又JVM完成。

多态的条件

1.要有继承,要有重写;
2.子类重写父类方法;
3.父类引用指向之类对象;

子类到父类的转换(向上转型)

将一个父类的引用指向子类对象,称为向上转型(upcasting),自动进行类型转换;
此时通过父类引用变量调用的方法是子类覆盖或继承的方法,不是父类的方法;
此时通过父类引用变量无法调用子类特有的方法。

                                             
0 0
原创粉丝点击