首页 > 代码库 > Java知识汇集(1)

Java知识汇集(1)

由于一些原因需要整理一些Java的知识,把整理出来的结果分享一下。

1、三大基本特性

我们以Java的三大基本特性为角度展开

封装、继承、多态

封装:

封装是把过程和数据包围起来,对数据的访问只能通过已定义的接口。面向对象计算始于这个基本概念,即现实世界可以被描绘成一系列完全自治、封装的对象,这些对象通过一个受保护的接口访问其他对象。封装主要实现了隐藏细节,对用户提供访问接口,无需关心方法的具体实现。

Java的权限控制等级由大到小依次为:public、protected、(default)、private,对应的访问权限分别为所有、本包内和子类、本包、自己。

继承:

继承是面向对象最显著的一个特性。继承是从已有的类中派生出新的类,新的类能吸收已有类的数据属性和行为,并能扩展新的能力。Java继承是使用已存在的类的定义作为基础建立新类的技术,新类的定义可以增加新的数据或新的功能,也可以用父类的功能,但不能选择性地继承父类。这种技术使得复用以前的代码非常容易,能够大大缩短开发周期,降低开发费用。关键字:extends。

多态:

多态性是指允许不同类的对象对同一消息作出响应。多态性包括参数化多态性和包含多态性。多态性语言具有灵活、抽象、行为共享、代码共享的优势,很好的解决了应用程序函数同名问题。

多态有两种表现形式:重载和重写。

2、重载和重写

首先我们来讲讲:重载(Overloading)

(1) 方法重载是让类以统一的方式处理不同类型数据的一种手段。多个同名函数同时存在,具有不同的参数个数/类型。

重载Overloading是一个类中多态性的一种表现。

(2) Java的方法重载,就是在类中可以创建多个方法,它们具有相同的名字,但具有不同的参数和不同的定义。

调用方法时通过传递给它们的不同参数个数和参数类型来决定具体使用哪个方法, 这就是多态性。

(3) 重载的时候,方法名要一样,但是参数类型和个数不一样,返回值类型可以相同也可以不相同。无法以返回型别作为重载函数的区分标准。

然后我们再来谈谈 重写(Overriding)

(1) 父类与子类之间的多态性,对父类的函数进行重新定义。如果在子类中定义某方法与其父类有相同的名称和参数,我们说该方法被重写 (Overriding)。在Java中,子类可继承父类中的方法,而不需要重新编写相同的方法。

但有时子类并不想原封不动地继承父类的方法,而是想作一定的修改,这就需要采用方法的重写。

方法重写又称方法覆盖。

(2)若子类中的方法与父类中的某一方法具有相同的方法名、返回类型和参数表,则新方法将覆盖原有的方法。

如需父类中原有的方法,可使用super关键字,该关键字引用了当前类的父类。

(3)子类函数的访问修饰权限不能少于父类的;

3、对象与引用

首先解释一下heap(堆)和stack(栈)的概念。

Heap和stack都属于内存中的两块区域,其中,stack的存取速度更高一些。

Heap:所有的对象(实例变量存在所属的对象中,所以也存放在heap上)。

Stack:方法调用和局部变量。

其中,heap中的对象一旦没有了引用,则会被垃圾回收器回收。

我们需要明确一个概念,那就是每当我们在写如下语句的时候:A a = new A();我们一共做了三件事情:申明了一个a;新建了一个A对象并在heap上为它开辟了一部分空间;把a指向了A对象。

所以,一个简单的例子:

Book b = new Book();

Book c = new Book();

b = c;//第一个Book对象被回收

c= null;

b= null;//第二个Book对象也被回收

4、集合

Java API中所用的集合类,都是实现了Collection接口,他的一个类继承结构如下:

(最下面一层之外全是借口)

Collection<--List<--Vector

Collection<--List<--ArrayList

Collection<--List<--LinkedList

Collection<--Set<--HashSet

Collection<--Set<--HashSet<--LinkedHashSet

Collection<--Set<--SortedSet<--TreeSet

Map<--HashMap

Map<--LinkedHashMap

Map<--Hashtable

Map<--SortedMap <--TreeMap

简单讲解一下他们的区别:

Set

Map

List

注重独一无二的性质,不允许重复,它知道某物是否已经存在与集合中

使用成对的键值和数据值,key不能重复

知道某物在系列集合中的位置,可以有多个元素引用相同的对象

推荐资料:http://www.cnblogs.com/eflylab/archive/2007/01/19/625086.html

5、日期处理

在写代码的时候经常会碰到对日期的处理,而DateFormat、NumberFormat、Calendar 均是抽象类,不能进行实例化,只能通过getInstance()方法获得实例对象。DateFormat a = DateFormat.getInstance();

NumberFormat b = NumberFormat.getInstance();

Calendar c = Calendar.getInstance();

下面我介绍几种主要的方式

Calendar calendar = Calendar.getInstance();// 取当前日期  

int year =calendar.get(Calendar.YEAR);  

int month=calendar.get(Calendar.MONTH)+1;  

int day =calendar.get(Calendar.DAY_OF_MONTH);  

int hour =calendar.get(Calendar.HOUR_OF_DAY);  

int minute =calendar.get(Calendar.MINUTE);  

int second =calendar.get(Calendar.SECOND); 

 

java.util.Date today=new java.util.Date();  

java.text.SimpleDateFormat dateFormat = new java.text.SimpleDateFormat("yyyy-MM-dd");

String now = dateFormat.format(today);

 

Date date  = new Date();  //取得当前日期,精确到毫秒

DateFormat dateformat1 = DateFormat.getDateInstance(0);

String datestr1 = dateformat1.format(date);    

// datestr1 = 2014年5月7日 星期三

DateFormat dateformat2 = DateFormat.getDateInstance(1);

String datestr2 = dateformat2.format(date); 

// datestr2 =  2014年5月7日

DateFormat dateformat3 = DateFormat.getDateInstance(2);

String datestr3 = dateformat3.format(date);  

// datestr3 = 2014-5-7

DateFormat dateformat4 = DateFormat.getDateInstance(3);

String datestr4 = dateformat4.format(date); 

// datestr4 = 14-5-7

DateFormat dateformat5 = DateFormat.getDateInstance();

String datestr5 = dateformat5.format(date);

// datestr5 = 2014-5-7

SimpleDateFormat simpledateformat = new SimpleDateFormat("yyyy年MM月dd日  HH:mm:ss");

String datestr6 = simpledateformat.format(date);  //datestr6 = 2014年5月7日  15:24:07

 

推荐资料:http://www.cnblogs.com/ggjucheng/p/3352467.html

6、字符串

String、StringBuffer、StringBuilder

String 类型和 StringBuffer 类型的主要性能区别其实在于 String 是不可变的对象, 因此在每次对 String 类型进行改变的时候其实都等同于生成了一个新的 String 对象,然后将指针指向新的 String 对象,所以经常改变内容的字符串最好不要用 String ,因为每次生成对象都会对系统性能产生影响,特别当内存中无引用对象多了以后, JVM 的 GC 就会开始工作,那速度是一定会相当慢的。

而如果是使用 StringBuffer 类则结果就不一样了,每次结果都会对 StringBuffer 对象本身进行操作,而不是生成新的对象,再改变对象引用。所以在一般情况下我们推荐使用 StringBuffer ,特别是字符串对象经常改变的情况下。

比如说

String a = “su”;

a += 1;

这里就会创建两个String对象。

StringBuilder:线程非安全的

StringBuffer:线程安全的

当我们在字符串缓冲去被多个线程使用是,JVM不能保证StringBuilder的操作是安全的,虽然他的速度最快,但是可以保证StringBuffer是可以正确操作的。当然大多数情况下就是我们是在单线程下进行的操作,所以大多数情况下是建议用StringBuilder而不用StringBuffer的,就是速度的原因。

7、正则表达式

具体的正则表达式看毛文卉讲不讲了,我只简单的讲一点。

在Java中使用正则表达式的方法非常多,最简单的就是和字符串一起使用。在String中有四个方法可以使用正则表达式,它们是matches、split、replaceAll和replaceFirst。

matches方法可以判断当前的字符串是否匹配给定的正则表达式。如果匹配,返回true,否则,返回false。matches方法的定义如下:public boolean matches(String regex)。

split方法使用正则表达式来分割字符串,并以String数组的形式返回分割结果。split有两种重载形式,它们定义如下:

public String[] split(String regex)

public String[] split(String regex, int limit)

replaceAll和replaceFirst的定义如下:

public String replaceAll(String regex, String replacement)

public String replaceFirst(String regex, String replacement)

这两个方法用replacement替换当前字符串中和regex匹配的字符串。

推荐资料:http://blog.csdn.net/x_jian/article/details/4096029

http://www.blogjava.net/xzclog/archive/2006/09/19/70603.html

8、I/O

Java的I/O其实内容很多,我这里也只能稍微从类层次,框架的设计模式来论述。

总体来说,I/O可以分为字节流和字符流,不同在于字符流由字节流包装而来,在I/O读入之后经过JVM处理,把字节流转换成字符流。而字符流的字符采用哪种字符编码实现由JVM默认编码决定。

而每个流都分输入和输出,所以,总体来说,I/O有四个顶层类:

InputStream

OutputStream

Reader

Writer

而作为机器级别于机器直接交互的则是字节流:

InputStream

OutputStream

以IO的中间类,进行字节流到字符流的转换过渡,通常可作为字符流类的构造参数,可指定编码:

InputStreamReader

OutputStreamWriter

而字节流和字符流的缓冲容器来看有byte和char之分,所以派生出:

ByteArrayInputStream

ByteArrayOutputStream

CharArrayInputStream

CharArrayOutputStream

以上类只是表示流的表示形式,而在传输形式上还表现为是否有缓冲。所以,可以派生出子类为可缓冲类:

BufferInputStream

BufferOutputStream

BufferReader

BufferWriter

每一个顶层类都有对目录文件(File)的支持:

FileInputStream

FileOutputStream

FileReader

FileWriter

在Java中,一个强大的功能就是可以对对象进行序列化,转成二进制文件输出,也就是字节流输出而不是字符流输出,所以有顶层的InputStream和OutputStream派生类:

ObjectInputStream

ObjectOutputStream

流包括了节点流和过滤流,注意的是过滤流,可在读写的同时对数据进行操作,并且实现了同步操作,顶层过滤流类:

FilterInputStream

FilterOutputStream

其子类则在其基础上,对节点流进行封装,常见子类有:

BufferInputStream          BufferOutputStream

DataInputStream            DataOutputStream

LineNumberInputStream      PrintStream

可参考子类的构造方法。

 

以上IO操作几乎就是把流装载到内存中,对其进行操作的时候是顺序读写,而需要随机读写时:

RandomAccessFile

从整个类框架的结构实现的接口来看,顶层类:

InputStream implements Closable,

OutputStream implements Closable, Flushable

Reader implements Closable, Readable

Writer implements Closable, Flushable, Appendable

各个接口方法:

Closable: close();

Flushable: flush();

Readable: read(CharBuffer cb);

Appendable: append();

从IO类使用时的规则来看,实现这些方法就是很自然的了,也是必须要实现的。如:流使用完必须关闭,流输出前必须刷新。

 

Java IO 框架中主要应用了两个设计模式:装饰模式和适配器模式。

姑且就把Java IO划分为元素和行为两个部分,元素则是适配,行为则是装饰加强。

适配器模式主要在于字节流到字符流的转换和元素的包装上,如类:InputStreamReader, CharArrayReader, FileReader, PipedReader, StringReader。

装饰模式主要在对流的强化之中,如缓冲、过滤、行定位等,如类:BufferedReader, FilterReader, LineNumberReader。

一个典型的例子就是:

BufferReader br = new BufferReader(new InputStreamReader(System.in));

综合了两种模式:把InputStream适配成InputStreamReader,再把InputStreamReader加强装饰城BufferedReader。

推荐资料:http://blog.csdn.net/evoline/article/details/14455173

http://www.cnblogs.com/rollenholt/archive/2011/09/11/2173787.html

http://www.cnblogs.com/maxupeng/archive/2010/12/30/1922281.html

9、序列化

序列化是一个不太直观的概念,我们可以这么理解:

Java平台允许我们在内存中创建可复用的Java对象,但一般情况下,只有当JVM处于运行时,这些对象才可能存在,即,这些对象的生命周期不会比 JVM的生命周期更长。但在现实应用中,就可能要求在JVM停止运行之后能够保存(持久化)指定的对象,并在将来重新读取被保存的对象。Java对象序列 化就能够帮助我们实现该功能。
使用Java对象序列化,在保存对象时,会把其状态保存为一组字节,在未来,再将这些字节组装成对象。必须注意地是,对象序列化保存的是对象的"状态",即它的成员变量。由此可知,对象序列化不会关注类中的静态变量。
除了在持久化对象时会用到对象序列化之外,当使用RMI(远程方法调用),或在网络中传递对象时,都会用到对象序列化。

一个简单的例子:

public class SimpleSerial {

 

    public static void main(String[] args) throws Exception {

        File file = new File("person.out");

 

        ObjectOutputStream out = new ObjectOutputStream(new FileOutputStream(file));

        Person person = new Person("John", 101, Gender.MALE);

        out.writeObject(person);

        out.close();

 

        ObjectInputStream in = new ObjectInputStream(new FileInputStream(file));

        Object newPerson = in.readObject(); // 不用强制转换到Person类型

        in.close();

        System.out.println(newPerson);

    }

}

 

推荐资料:http://www.blogjava.net/jiangshachina/archive/2012/02/13/369898.html

http://www.cnblogs.com/rollenholt/archive/2012/11/26/2789445.html

10、static

静态方法与静态类都是属于类而不是对象的,也就是说,不管类创建了多少个对象,所有的静态属性都只有一个。java类在加载时,程序首先会把该类的静态变量加载进内存中,也就是在堆空间中开辟一个区域专门存放。以后不管你new多少个类的对象,该静态变量永远都是在那里的。

对它的基本性质总结如下:

1. 若需要一个类的多个对象共享一个变量,则该变量需要使用 static 修饰.

2. 因为 static 修饰的变量为类的所有的实例所共享,所以 static 成员不属于某个类的实例, 而属于整个类.所以在访问权限允许的情况下,可以使用 "类名." 直接访问静态成员(成员包括属性和方法).

3. 注意: 在静态方法里只能直接调用同类中其它的静态成员(包括变量和方法),而不能直接访问类中的非静态成员.这是因为,对于非静态的方法和变量,需要先创建类的实例对象后才可使用,而静态方法在使用前不用创建任何对象.

4. 同 3 的道理: 静态方法不能以任何方式引用this和super关键字.

5. 非静态方法中可以直接来访问类的静态成员.

6. main() 方法是静态的,因此JVM在执行main方法时不创建main方法所在的类的实例对象.

7. 静态初始化指对类的静态属性进行初始化. 不应该在构造器中对静态成员进行初始化: 因为静态成员不因类的实例而改变.

11、抽象类与接口

Interface这个关键字产生一个完全抽象的类,没有提供任何的具体实现。它的出现是为了为了解决Java中只能单继承的问题。一个类可以实现多个接口。

在面向对象的概念中,我们知道所有的对象都是通过类来描绘的,但是反过来却不是这样。并不是所有的类都是用来描绘对象的,如果一个类中没有包含足够的信息来描绘一个具体的对象,这样的类就是抽象类。抽象类往往用来表征我们在对问题领域进行分析、 设计中得出的抽象概念,是对一系列看上去不同,但是本质上相同的具体概念的抽象。比如:如果我们进行一个图形编辑软件的开发,就会发现问题领域存在着圆、 三角形这样一些具体概念,它们是不同的,但是它们又都属于形状这样一个概念,形状这个概念在问题领域是不存在的,它就是一个抽象概念。正是因为抽象的概念 在问题领域没有对应的具体概念,所以用以表征抽象概念的抽象类是不能够实例化的。

抽象类是普通的类与接口之间的一种中庸之道。

1.abstract class 在 Java 语言中表示的是一种继承关系,一个类只能使用一次继承关系。但是,一个类却可以实现多个interface。

2.在abstract class 中可以有自己的数据成员,也可以有非abstarct的成员方法,而在interface中,只能够有静态的不能被修改的数据成员(也就是必须是static final的,不过在 interface中一般不定义数据成员),所有的成员方法都是abstract的。

3.abstract class和interface所反映出的设计理念不同。其实abstract class表示的是"is-a"关系,interface表示的是"like-a"关系。

4.实现抽象类和接口的类必须实现其中的所有方法。抽象类中可以有非抽象方法。接口中则不能有实现方法。

5.接口中定义的变量默认是public static final 型,且必须给其初值,所以实现类中不能重新定义,也不能改变其值。

6.抽象类中的变量默认是 friendly 型,其值可以在子类中重新定义,也可以重新赋值。

7.接口中的方法默认都是 public,abstract 类型的。

 

另外,我们知道抽象类是不能实例化的,也就是说如果存在一个抽象类abstract Class A,那么久不存在new A();的说法,那A有没有构造器呢,A的构造器有没有机会执行呢?(所以说,在创建新对象的时候,所有继承下来的构造函数都会被执行)

推荐资料:http://www.cnblogs.com/LittleRedPoint/p/3478023.html

12、多态

方法的重写、重载与动态连接构成多态性。Java之所以引入多态的概念,原因之一是它在类的继承问题上和C++不同,后者允许多继承,这确实给其带来的非常强大的功能,但是复杂的继承关系也给C++开发者带来了更大的麻烦,为了规避风险,Java只允许单继承,派生类与基类间有IS-A的关系(即“猫”is a “动物”)。这样做虽然保证了继承关系的简单明了,但是势必在功能上有很大的限制,所以,Java引入了多态性的概念以弥补这点的不足,此外,抽象类和接口也是解决单继承规定限制的重要手段。同时,多态也是面向对象编程的精髓所在。

要理解多态性,首先要知道什么是“向上转型”。

我定义了一个子类Cat,它继承了Animal类,那么后者就是前者是父类。我可以通过

Cat c = new Cat();

实例化一个Cat的对象,这个不难理解。但当我这样定义时:

Animal a = new Cat();

这代表什么意思呢?

很简单,它表示我定义了一个Animal类型的引用,指向新建的Cat类型的对象。由于Cat是继承自它的父类Animal,所以Animal类型的引用是可以指向Cat类型的对象的。那么这样做有什么意义呢?

一、使用父类类型的引用指向子类的对象;

二、该引用只能调用父类中定义的方法和变量;

三、如果子类中重写了父类中的一个方法,那么在调用这个方法的时候,将会调用子类中的这个方法;(动态连接、动态调用)

四、变量不能被重写(覆盖),”重写“的概念只针对方法,如果在子类中”重写“了父类中的变量,那么在编译时会报错。

推荐资料:http://www.cnblogs.com/LittleRedPoint/p/3478028.html