Java面向对象之 类与对象

java是标准的面向对象语言,本博文首先介绍 面向对象之三大特征五大原则,然后详细介绍了对象与类的相关知识。

三大特征五大原则:

三大特征:封装,继承,多态

1、所谓封装,也就是把客观事物封装成抽象的类,并且类可以把自己的数据和方法只让可信的类或者对象操作,对不可信的进行信息隐藏。封装是面向对象的特征之一,是对象和类概念的主要特性。 简单的说,一个类就是一个封装了数据以及操作这些数据的代码的逻辑实体。在一个对象内部,某些代码或某些数据可以是私有的,不能被外界访问。通过这种方式,对象对内部数据提供了不同级别的保护,以防止程序中无关的部分意外的改变或错误的使用了对象的私有部分。

2、所谓继承是指可以让某个类型的对象获得另一个类型的对象的属性的方法。它支持按级分类的概念。继承是指这样一种能力:它可以使用现有类的所有功能,并在无需重新编写原来的类的情况下对这些功能进行扩展。 通过继承创建的新类称为“子类”或“派生类”,被继承的类称为“基类”、“父类”或“超类”。继承的过程,就是从一般到特殊的过程。要实现继承,可以通过“继承”(Inheritance)和“组合”(Composition)来实现。继承概念的实现方式有二类:实现继承与接口继承。实现继承是指直接使用基类的属性和方法而无需额外编码的能力;接口继承是指仅使用属性和方法的名称、但是子类必须提供实现的能力;

3、所谓多态就是指一个类实例的相同方法在不同情形有不同表现形式。多态机制使具有不同内部结构的对象可以共享相同的外部接口。这意味着,虽然针对不同对象的具体操作不同,但通过一个公共的类,它们(那些操作)可以通过相同的方式予以调用。

五大原则:

单一职责原则SRP(Single Responsibility Principle)

是指一个类的功能要单一,不能包罗万象。如同一个人一样,分配的工作不能太多,否则一天到晚虽然忙忙碌碌的,但效率却高不起来。

开放封闭原则OCP(Open-Close Principle)

一个模块在扩展性方面应该是开放的而在更改性方面应该是封闭的。比如:一个网络模块,原来只服务端功能,而现在要加入客户端功能,
那么应当在不用修改服务端功能代码的前提下,就能够增加客户端功能的实现代码,这要求在设计之初,就应当将服务端和客户端分开,公共部分抽象出来。

替换原则(the Liskov Substitution Principle LSP)

子类应当可以替换父类并出现在父类能够出现的任何地方。比如:公司搞年度晚会,所有员工可以参加抽奖,那么不管是老员工还是新员工,
也不管是总部员工还是外派员工,都应当可以参加抽奖,否则这公司就不和谐了。

依赖原则(the Dependency Inversion Principle DIP)

具体依赖抽象,上层依赖下层。假设B是较A低的模块,但B需要使用到A的功能,这个时候,B不应当直接使用A中的具体类: 而应当由B定义一抽象接口,并由A来实现这个抽象接口,B只使用这个抽象接口:这样就达到了依赖倒置的目的,B也解除了对A的依赖,反过来是A依赖于B定义的抽象接口。通过上层模块难以避免依赖下层模块,假如B也直接依赖A的实现,那么就可能造成循环依赖。一个常见的问题就是编译A模块时需要直接包含到B模块的cpp文件,而编译B时同样要直接包含到A的cpp文件。

接口分离原则(the Interface Segregation Principle ISP)

模块间要通过抽象接口隔离开,而不是通过具体的类强耦合起来

对象与类

把客观世界中的事物映射到面向对象的程序设计中就是对象。对象是面向对象程序设计中用来描述客观事物的程序单位。客观世界中的许多对象,无论其
属性还是其行为常常有许多共同性,抽象出这些对象的共同性便可以构成 类。所以,类是对象的抽象和归纳,对象是类的实例。
既然类是对象的抽象,所以在创建对象之前首先要定义类。类分为两种:预定义的java类库中已经定义好的类、用户自定义
类。

是同类操作的集合,如Math类就是数学方法的一个集合。这里要想深入全面的了解,就多看API文档吧。

用户自定义类: 定义类三个方面必不可少:类的标识(类名)、数据(类的属性)、操作(方法)。下面是定义一个简单类的 
public class Employee {
    // 属性     同意类对象的共同属性
    private String  name;
    private double salary;
    private Date hireDay;

    // 构造器
    public Employee(String n,double s,int year,int month,int day)
    {
        name=n;
        salary=s;
        GregorianCalendar calendar=new GregorianCalendar(year,month-1,day);
        hireDay=calendar.getTime();
    }

    // 实例方法
    public String getName()
    {
        return name;
    }
    public double getSalary()
    {
        return salary;
    }
    public Date getHireDay()
    {
        return hireDay;
    }
    public void raiseSalary(double byPercent)
    {
        double raise=salary*byPercent/100;
        salary+=raise;
    }

}
对象
对象是对现实中事物的抽象,实际应用中如果要用某个事物,就需要创建对应的对象,如果已有给对象的类了就可 以直接实例化一个对象,否则先定义类。

Java中创建对象分为显示创建和隐式创建

4种显式地创建对象的方式:

1、用 new语句 创建对象,这是最常用的创建对象的方式。
2、运用反射手段,调用 java.lang.Class 或者 java.lang.reflect.Constructor 类的 newInstance() 实例方法。
3、调用对象的clone() 方法。
4、运用 反序列化 手段,调用 java.io.ObjectInputStream 对象的 readObject() 方法。

下面演示了这四种方法创建对象的过程:

创建对象的程序
创建对象的程序

创建对象对应的类的定义
创建对象对应的类的定义

以上程序打印的结果如下:

这里写图片描述

从以上打印结果可以看出,用new语句或Class对象的newInstance()方法创建Customer对象时,都会执行 Customer类的构造方法;而用对象的 clone()
方法创建对象和用反序列化创建对象时,不会执行 Customer 类的构造方法。(区别)

需要注意以下几点:

1、要想克隆对象,对象对应的类必须实现 cloneable 接口,
2、要想序列化反序列化对象,对应的类必须实现 serializable 接口。
3、在使用反射机制创建对象时,Class.forName()方法的参数必须是类的全路径。
Class objClass=Class.forName("类与对象.Customer");

4种隐式创建对象:

1、对于java命令中的每个命令行参数,Java虚拟机都会创建相应的String对象,并把它们组织到一个String 
数组中,再把该数组作为参数传给程序入口main(String args[])方法。
2、程序代码中的String类型的直接数对应一个String对象,例如:
String s1="Hello";  
String s2="Hello"; //s2和s1引用同一个String对象 
3、字符串操作符“+”的运算结果为一个新的String对象。例如:
String s1="H";  
String s2=" ello";  
String s3=s1+s2; //s3引用一个新的String对象 
4、当Java虚拟机加载一个类时,会隐含地创建描述这个类的Class实例。

封装的好处
类的数据域最好标识为 private ,免得被外部方法非法更改。但是有时候需要获取或设置实例域的值,所以应该提供下面三项内容:

  1. 一个私有的数据域;
  2. 一个共有的域访问器方法;
  3. 一个共有的域更改器方法。

一些小的零碎知识点:

1、注意不要编写返回引用可变对象的访问器方法。(string 是不可变对象)

因为如果这样做了,当拿到返回的可变对象引用后,便可对其进行更改,因为这个返回的对象和原对象的实例域是只想同一个对象的,所以破坏了封装性。 

解决的方法:如果需要返回一个可变对象的引用,应该首先对其进行克隆,然后返回其克隆值。

2、静态变量使用的比较少,但是静态常量使用的很多。

System.out就是静态常量,理论上 静态常量是不能有更改器的,即不可以被改变的。但是有一个方法 setOut可以将System.out设置为不同的流。这是为什么呢? 原因在于,setOut方法是一个本地方法,而不是用java语言实现的,本地方法可以绕过java语言的存取控制机制。

3、在下面两种情况下可以使用静态方法:

(1)、一个方法不需要访问对象状态,其所需参数都是通过显示参数提供
(2)、一个方法只需要访问类的静态域。

4、Java程序设计语言对对象不是采用的引用调用,而是进行的值传递。

(1)、一个方法不能修改一个基本数据类型的参数
(2)、一个方法可以改变一个对象参数的状态
(3)、一个方法不能让一个对象参数引用一个新的对象

5、仅当没有提供任何构造器时,系统才会提供一个默认的构造器,如果此时还需要类具有默认构造器,就要手动添加一个默认构造器。

6、如果在构造器中没有显示地给域赋予初值,就会被自动地赋为默认值(不推荐这样做),可以定义一个无参构造器,手动赋予默认值。也可以显示域初始化,有如下几种方法:

(1)、声明时赋予初始值 (初始值不一定是常量)
在运行时,首先运行初始化块,然后再运行构造器的主体部分。
如果对类的静态域进行初始化的代码比较复杂,那么可以使用静态的初始化块。
class Employee
{
    private static int nextId;
    private int id=assignId();
    private static int assignId()
    {
        int r=nextId;
        nextId++;
        return r;
    }
}
2、初始化块
class Employee
{
    private static int nextId;
    private int id;
    private String name;
    private double salary;
    {
        id=nextIn;
        nextId++;
    }

    public Employee(String n, double s)
    {
        name=n;
        salary=s;
    }
    public Employee()
    {
        name="";
        salary=0;
    }
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值