Java基础系列之类和接口(一)

2014-11-24 00:41:56 · 作者: · 浏览: 2

个人胡说

类是面向对象的核心概念,在目前我得理解来说,其实就是提供了一种将数据结构和对应的服务封装,而面向对象,除了高深的面向对象思想,再者便是与类相关的一系列相关技术的支持,比如多态等。为什么面向对象编程会成为目前主流的编程?我看来一是这种编程相对于数据流(面向过程编程)来说,面向对象更加符合人类的思维习惯和事物的一些本质,另外就是它强大繁多的库。当然,如果面向过程语言自然也可以实现代码复用、API编程等,但是由于没有封装等概念,所以这样的实现会显得比较撇脚。而提供这些面向对象技术是要付出代价------程序的效率,由于支持了许多的技术和特性,所以效率相对于面向过程语言(特别是C语言)自然无法抗衡,所以,要正确的认识面向对象和面向过程这两种技术,各自适应于不同的领域,就拿C语言和Java语言作为代表,C语言对于执行效率有较高的程序是十分恰当的选择(比如OS、Web服务器、数据库、嵌入式等等),而Java更加适合作为生产语言(Web开发、桌面程序等等)。在这两个不同的层次,我钟爱C语言的简洁、效率、对数据结构的描述能力,又对Java强大的API和生产效率执着,使用C语言编程的时候,我大多数时候都在关注数据结构、数据流等和实际事务处理相关度并不是太大(虽然是事务的底层)的细节,对于整体的编程任务有时候并不能整体的把握(后来我发现如果一开始就设计出相关的API便可以解决很多的问题---自顶向下的设计),使用Java的时候,几乎都在关注事务的处理,对于底层的数据结构只有在高效的算法才会重点关注细节,更多的提高了自己处理事务的效率(因为别人已经帮我做了很多的事情),所以面对C语言和Java语言,在我看来都是影响我一生编程思想的语言。PS:有时候我会想设计出一种新的编程语言,既有C语言的底层能力,又有Java的高层抽象能力(绝对不是C++,我确实不太喜欢C++,至少教科书中的C++我不喜欢),哇,那一定很cool!

Java中的类有class关键字支持,一个public类的名字必须和文件名相统一,不然会编译出错,其生成的.class文件也和主类具有相同的名字(自然和文件名也相同)。

类是创造对象的模板,相对于类另外的一个代名词就是“封装”,将数据结构和相应的服务结合在一起的机制。也正是这个机制,让类所产生的对象绝大多数的时候更加倾向于提供服务(服务其实就是方法调用),由于服务是基于数据结构,但是在编程的时候,他人更多的时候是想获得某些服务,而对于服务室基于何种数据结构和如何实现关心并不是太多。而没有类就无法做事,所以Java编程的基本任务就是创建各式各样的类。

类的创建一般是一个名词,类中的属性也是类中的一些名词,相应的动词形成服务。比如,人(Person)这个类,设计出来后其中的属性便有name,sex,age等等,相应的服务便有起床、吃饭、学习、睡觉等等。

内部类

内部类是创建在类内部的类,分为三种:

1.静态/非静态成员内部类

2.非静态局部内部类

3.匿名内部类

内部类从设计与解决编程问题来看,是使得多重继承更加完善的机制。由于内部类具有类的所有性质,从而可以实现接口和继承非接口类型,而作为类的普通成员,可以毫无阻难的访问外围类的属性和服务,之所以成为内部类是大部分原因是辅助本类解决需要解决的问题,特定的属于某个外围类,所以它虽然是一个成员,却没有必要再去考虑太多其他的事物,比如继承等等。

每个种类的内部类都具有相应的特点,自然具有不同的用处。如果声明成员类不要求访问外围类的实例,就要始终把static修饰符放在它的声明中。如果一个内部类在单个方法之外是可见的,或者它十分的长,那么就不适合放在方法的内部,而应该作为成员类。

内部类支持的关键字:.this与 .new 。如果你需要外部对象的引用,就可以使用外部类名字后面紧跟圆点和this,很明显,这个.this是无法用于静态方法或者静态类(只会出现在内部类中(也叫嵌套类))的。另外有一点需要注意的是,普通内部类是不允许声明static成员变量和方法的。.new 关键字则是通过外围类对象生成内部类的对象。相关的代码参考实例可以参考Java集合中HashMap的实现。

匿名内部类有一个特别的用处,就是实现事件监听器。

内部类也会生成独立的.class文件,拥有自己的特殊标识符$。

基本来说,内部类的用法在设计中某些时候能够起到十分巧妙的作用,如何设计好内部类还是经验的问题,Java的接口和内部类结合解决了C++多继承所能解决的问题,相对于C++的多继承,简单且容易理解了许多。

类进阶

与类相关的一个名词叫---信息隐藏或者叫封装,是软件设计的基本原则之一,其最大的原因便是它可以有效的解除组成系统的各个模块之间的耦合关系,使得这些模块可以独立的开发、测试、优化、使用和修改。正式由于这个模块化单独并行开发,所以大大的提高了生产效率。一个系统,如果使用面向对象语言,进行了良好的模块划分,不论是开发效率,还是程序整体的健壮和以维护性都会提高,而类的设计便成为了开发的核心。

设计准则:

1.使类和成员的可访问性最小化

类一旦被设计出来,很多的时候对于其使用者便是一种公开的承诺,对于类中的核心数据结构应该隐藏,防止使用者的不小心破坏从而导致服务的错误甚至程序的崩溃。除了静态final域的特殊情况之外,共有类都不应该包含公有域。对于其中的某些可能会被外界访问的数据,应该使用访问方法而不是设置域为公开。有时候你可能会觉得麻烦,但是这一定是你值得做的事情。

2.使可变性最小化

在设计类的时候,大多数时候都是具体的特定功能类(不是用来被继承的类),这个时候就应该将该类设置为final类,有时候一个类其实只需要一个实例便足够了,单例模式在此时就应该被用来设计这个类。

由于类是不可变的,所以不能被继承从而潜在的造成某些影响,其中的域也尽可能不变,由于不可变域本质上是线程安全的,不要求同步机制。在设计某些可能存在多个线程同时访问的类,线程安全显得特别的重要,比如servlet类,其本质上就是一个遵循单例模式设计的类,没有公有可变域,所以线程不需要去花时间考虑如何使安全。

想让类变得更加可控和final,那么使用静态工厂模式来代替构造器同时私有化类的构造器是一个十分不错的选择。这种方式一个的好处便是可能通过改善静态工厂的算法,从而在后续的改进中增加该类的性能。另外一个好处便是当对类的要求发生变化,可以直接重载静态方法,修改相应的算法,而不用去新创建构造器,由于静态工厂创建对象可以在方法中添加相应的算法和处理,使得创建对象和对类维护的灵活性大大提高。

3复合优先于继承

继承是面向对象三大技术之一,却打破了类的封装性,且继承也有着诸多的缺点和让人烦恼的地方,比如1.父类的改变导致对子类可能产生影响,而子类越多影响越大,父类的设计必须有足够的眼光和经验才能设计出优秀的父类。2.子类重写父类的方法,向上转型后可能会存在由于对父类中内部方法调用机制不清楚从而导致重写的方法无效甚至错误。3.父类的一些方法的设计缺陷由于各种原因无法修改,子类继承后很有可能依然无法解决,所以会有承担父类API缺陷的风险。在面向对象编程六大原则中,第二条称为“里氏替换原则”便是对类继承的相关约定