Java 学习总结
目录
最近因为工作的需要,学习了java和android 的应用程序开发,费时一个多月,一个月之前,我还只是一个C程序员,在C的道路上算是积累的一些经验,学习java除了是工作需要的因素外,另外一部分原因就是想感受下面向对象的编程思想。
第一章:Java入门(C与java的差异)
我的java学习的时间大概是1周,感觉对java的掌握还是比较深入,算是入门了吧,能够这么快入门,可能得益于有C语言的基础,还有就是有一个好老师。
程序Yuan的习惯之一:一边学习一边练习,主要是找到编程的感觉(人的记忆分很多种,编程感觉就是属于机械式记忆的一种)个人觉得看视频要要比看书要形象得多,所以我最初的学习是通过看mars的Java4Android视频来了解java,视频学习最大的问题在于费时间,有的人直接选择看书或者来得更快些(那些经常看书的人就比较有福了),我在看视频的时候使用了KMplay的快速播放模式,视频的播放速度是正常的2~3倍,对于一些冗长的细节甚至可以跳过,我将自己的java学习也分为了三个阶段:第一部分是java程序设计基础,在这个阶段主要是掌握java最基本的语法(基本的数据类型、变量、循环、选择、数组的使用),在主观的感受上,java的基本语法与C语言没有什么差别。相信C程序员可能都看过老美出过的一本叫做《C陷阱与缺陷》的书,里面介绍了一些C语言编写时应该注意的一些设计原则和编程技巧,java基本上可以完美的避过这些问题,举个最常见的例子,《C陷阱与缺陷》写到if(0 == variable)…. 可以减少编程失误带来的问题。可是java要求if的条件表达式必须是boolean型,如果将程序写成if(variable =0)将是一个非法的语句。以下列出我所了解到的C与java在基本语法上的差异
1.基本数据类型:
Java的数据类型与C不完全一致,数据所占内存的长度也不完全一致,大家看仔细了
2.类型转换:
各种数据类型在进行强制类型转换的时候保持连个原则:一是转换前后的数据要相互兼容,而是转换过程尽量不丢失精度。
3.运算符:
java中运算符的优先级基本保持与C一致(‘&’、‘*’、‘->’、‘.’、‘,’被java去除)
4.局部变量:
C语言所理解的局部变量和java是一致的(C语言规定在函数内存声明的变量当跳出函数后将不再有效,static除外,java也是如此)
5.一维数组使用方法与内存分配:
java一维数组 int a[]或者int []a,内存分配与C一致,由于java不存在指针的概念,所以是a在java代表一个数组对象,可以被其他数组对象引用,说到底java中的引用就是C语言中的指针,如果你懂C的指针,你就能明白java中的引用,java封装了C语言中指针的一些特性,避免程序员犯错, 在C语言中,指针几乎可以表示内存中的任意的字节地址,但是在java中被引用的只能是对象,所有的地址都已经被对象、属性、方法封装起来,引用是指针的一个子集。
6.多维数组内存分配:
java与C语言最明显的特点体现在内存分配上,C语言的世界里,内存的分配完全要靠程序员来完成(内存的名字、类型、大小、要考虑内存的对齐/泄露/释放/越界….其中最难解决的就是内存泄露和越界),在java的世界里面,程序员不需要关心这些繁琐的问题(开心吧),而是把内存形象化为具体的对象及对象的属性(一个对象的实例化就是为其分配内存,回收则由系统自动完成)。在C语言中二维数组是一串连续的内存,但是在java中二维数组却是由两个一维数据叠加起来的(系统先创建一个二维数组的空壳,然后创建两块内存填充到二维数组里面)
第二章 Java 面向对象基础
2.1对象的概念:
引用经典的语句“万物皆为对象”,所有的事物皆有两个方面:对象的描述(称为属性),对象能够做什么(对象的方法)。
以人为例,人的属性可以有肤色、年龄、性别、籍贯、受教育水平、身份证号、工作经验、甚至戴不戴眼睛、生活的地区、喜好····;一个人所能做的事情就是对象的方法,比如写作、编程、修水管····
面向对象的思想:以对象为中心、先抽象出对象的样子(有哪些属性和方法,被称为class),之后再决定在哪里生成这个对象,最后才是调用对象的方式来完成具体的事情,在设计程序时自顶而下的设计方法,一次考虑的是整个程序框架、程序需要使用到的资源和需要完成的事情、最后才是通过一定的顺序整合资源来完成具体的任务、在完成具体的任务的时候才考虑具体的算法。
面向过程的思想:由过程、步骤、函数组成、以过程为核心,在程序设计的时候依次考虑的是完成任务需要哪些过程、需要用到的算法、函数,很多时候都是在程序设计的后期才去添加新的数据结构、变量,变量和数据结构很有可能是散乱的摆列在代码的任意一个可能的地方。
2.2类的概念
如果非要同C语言做对比,java 中的类对应的是C语言中的结构体。类的出现能够实现代码的高内聚和低耦合,个人觉得高内聚和第耦合实际是一个统一的整体,通常在编程的时候其中的一个设计原则就是写要有高的可读性,尤其是在大型的软件项目中,这一点显得尤为重要,因为你写的代码不可能只有一个人来维护,当你离开一个项目或者一个公司的时候,能够让接替你的人尽快掌握你的代码的含义是首要的事情,如果你写的代码很糟糕,维护一段代码的成本会很高。提高可读性的其中一个方法就是将你代码要表达的意思能够像类一样集中起来,有类名,属性,变量就能够做到让你写的这块代码作用更明确些。java 的终极目标是消除重复的代码,如果掌握了一个类的作用,那么就能够很清晰的知道在什么地方可以使用到这个类。
2.3封装的概念
封装的目的是要展示给外界它希望外界看到的,屏蔽不希望外界看到的,如此一个对象与外界联系的接口就比较统一,外界只能通过某个方法去访问和指挥对象完成某些工作,而具体要怎么做则有由对象来决定。
2.4 继承的概念
继承的目的比较明显:一是提高可扩展性,二是提高复用性。代码的设计和编写总是有时代背景,时代的等众多要素的变化会带来的新的需求,而原有的代码架构已经成型,采用继承的方式则不需要重写原有代码,相当于是在原来的基础上抽象出新的类,而新的类除了包含父类的属性和方法外,还包含了自己独有的功能。
2.5 多态的概念
多态是指编译时类型变化,运行时类型不变。所以多态分为两种:一是“编译时”多态,而是“运行时”多态。所谓人的认识是主观的,对象是客观的。多态是一种数据类型的强制转换。
编译时多态是指:在加载对象的时候根据你强制转换的类型来决定能够访问的属性和方法。
运行时多态是指:一个对象可以被转换成多种类型,但是其原始的内存块(大小/位置)并不会发生变化。
从C语言的角度上分析,是否能转换成功取决于你最初new 一个对象时分配的内存模型。例如生成了对象student,该对象的类型是B,而B又是A的子类,在内存模型上,student包含了B和A的所有内存,所以student要强制转换成A也是可以的,且student 所占用的内存模型并没有因为强制转换成A类之后而丢失,所以之后student还可以再从A类型强制转换成B类型。如果最初new的对象就是A类型,其内存就只包含A,之后又想转换成B类型是出错滴。
使用instanceof 关键字可以判断出一个类是否是某个类的实例
2.6类的创建于使用
创建一个类:使用class关键字,定义一个类不会分配内存(类似于定义C中的结构体)
创建一个对象:使用new关键字实现,如果定义了一个student类,new studet()就会生成一个对象(就是为这个类分配内存),很简单吧。
构造方法:一个特殊的方法,当一个对象被创建的的时候一定会调用的方法(其作用相当于C中对一个数据结构的初始化),java是抽象出了内存的一个生命周期,就是初始化时期,调用构造方法就是告诉系统要如何初始化这块内存。这个大多数C 创建内存时需要做的事情,java就干脆将这个过程提出来。
构造方法与其他方法不同点在与构造方法没有返回值,方法的名字必须要和类的名字一致。
2.7 重载的概念(overloading)
这里讲的重载是指方法的重载,意思是一个类或者子类中包含的方法名字可以重复,但是方法的参数可以不一致,调用该方法时只要传入的参数不一致就能实现调用不同的方法。
2.8 复写的概念(overriding)
复写是指子类中可以编写了一个与父类名字和参数都一样的方法,可能是父类的方法不能满足子类的需要,也有可能是父类本来就希望子类来实现这个方法。
2.9 抽象类的概念(abstract)
抽象类是指在定义一个类的时候并不实现类中的方法,只声明这个方法的返回值,方法的名字和所需要传递的参数,要求子类在继承的时候要去实现这些抽象的方法。用处:当在定义一个类的方法时,可能这个方法在不同的环境下需要写不同的代码,但实现的总体功能是不变的。
抽象类的四条规则:
·抽象类和抽象类的方法必须使用abstract来声明
·抽象类不能被实例化,也就是不能使用new 关键字来产生一个对象
·抽象类只需要声明,而不需要具体的实现
·含有抽象类的方法必须声明为抽象类,抽象类的子类必须是想抽象类中的所有方法,否则这个子类还是一个抽象类
2.10 接口的概念(interface)
接口是一种特殊的抽象类,相当于是抽象类的子集,所以必须满足抽象类中的规则。
接口中也存在类和方法,只是在接口中要求接口的属性全部都是final 类型且必须初始化属性的值,,所有的类也都是抽象类,不会包含有一般方法。接口的 abstract、final关键字是可以省略的。(原因你懂的)
与抽象类不同的是一个子类只能同时继承一个抽象类,但是却可以同时实现多个接口。
在打造一个新类的过程被称为接口的事项,使用implements关键字标识。
2.11内部类
内部类就是定义在一个类里面的类,内部类的使用非常广泛(定义内部类的原则应该是,当一个类A只能被其他一种类B使用到的时候,那这个A类就可以定义在B类的内部)。内部类一共有四种类型:
·成员内部类
·局部内部类
·静态内部类
·匿名内部类
成员内部类是指非静态的定义在一个类的内部但不定义在任何方法当中的类,成员内部类中不能有静态属性。
局部内部类是指定义在一个类的方法中的内部类,如果这个局部内部类要访问所在方法中的局部变量,那这个局部变量的属性必须是final。
静态内部类是指静态的定义在一个类的内部但不定义在任何方法中的内部类。
匿名内部类是一种特殊的局部内部类,它是通过匿名的方式去实现一个接口。
2.12异常的概念
Java中的异常类似于C中的宕机,常见的异常有:
·算术异常(ArithmeticException)。
·没有给对象开辟内存空间时会出现空指针异常(NullPointerException)。
·找不到文件异常(FileNotFoundException)。
异常的处理
Java 中异常是以类的形式存在的,类的继承结构如下
有了对异常的捕捉和处理,当发生异常的时候,系统就还能正常运行,不至于系统崩溃。
2.13 包的概念(package)
当开发一个大型项目的时候,不同的开发人员有可能会定义出相同的类名,如果希望这些相同的类名能够正常的工作,就可以使用package来帮忙。
当在一个类文件开始的地方声明包名的时候,那这个内会被纳入到当前的包中。在实际存放代码的时候,Constant会被放置在com/bn/rcgl/目录下
当在某个类中要使用到其他包中的类时,可以使用import 关键字来导入这个包到当前类中。
2.14 访问权限
访问权限一共四种:public、protected、default、private
·public
当一个属性或者方法被声明为public的时候,那么它将可以被所有的类访问
·protected
当一个属性或者方法被声明为protected的时候,那么它将可以被当前包的所有类和其他包中的子类访问
·default
当一个属性或者方法被声明为default的时候,那么它将只能被当前包中的所有类使用
·private
当一个属性或者方法被声明为private的时候,那么它将只能在当前内的内部使用,且其子类也不能访问。
第三章 java应用程序
3.1 多线程
3.1.1 多线程与多进程的概念
Java 中多线程和多进程的概念与C语言是一致的。每个独立的进程会使用独立的内存空间,一个进程中可能多个进程,这些线程共享该进程的一块地址空间。
3.1.2 线程的创建
第一种是继承Thread类(extends Thread)
第二种是实现Rnnnanle接口
两种创建方式的差别
- implements 相当于回调函数,在不同的线程中使用的是相同的方法和属性
- extends 相当于是在不同的线程中使用各自独立的方法和属性
3.1.3 线程的操作方法
线程操作方法
- Thread.currentThread().getName();
获取当前线程的名字
- thread.isAlive()
检查当线程是否被激活
- setDaemon(true)
将线程设置为后台线程,对java来说,只要有一个前台线程正在运行这个进程就不会结束。
由于将myThread设置为后台线程,所以当执行完main函数之后整个进程就结束了。
- thread1.join();
强制运行thread1所引用的函数,join还可以带参数以决定运行的时间。
- Thread.sleep(millsecond);
线程的休眠,以毫秒为单位。
- thread1.interrupt();
用来中断thread1的运行。
3.1.4线程的同步 (synchronized)
- 同步代码块
- 同步方法
- 死锁
当几个不同的线程需要使用到两个以上的相同“同步资源”的时候,应该保证获取资源的顺序是的一致性或释放资源的逆序。
比如线程th1 和th2 都要使用到同步资源A、B,那么要保证th1和th2在获取A/B是的顺序都是A->B(或者是B->A),释放资源时的顺序要和获取资源要一致。
否则当th1先获得A ,而B此时已经被th2获得,此时th1需要获取资源B,而th2需要获取资源A,就会造成一直等待对方线程释放资源的情况,从而导致死锁。
3.1.5线程间的同步通讯方法
- wait()
- notify()
- notifyall()
3.2文件I/O操作
3.2.1 摘要
·Java中要进行IO操作,需要导入java.io包。
·Java中的File类是唯一操作磁盘文件的类。
·Java中的数据操作主要分为两种:
1)、 字节流(OutputStrea、InputStream)
2)、 字符流(Writer、Reader)
这四个类都是抽象类,使用时,都必须依靠其子类实例化。
·Java定义了两个特殊的流对象:System.in和System.out。System.in对应键盘,是InputStream类型的,程序使用System.in可以读取从键盘上输入的数据;System.out对应显示器,可以向显示器上输出内容。
·InputStreamReader和OutputStreamWriter,这两个类是字节流和字符流之间转换的类,InputStreamReader可以将一个字节流中的字节解码成字符,OuputStreamWriter将写入的字符编码成字节后写入一个字节流。
·一个类实现了Serializable接口之后,此类的对象可以被序列化,就表示可以保存在文件之中、或网络传输之中。如果不希望类中的某个属性被保存下来,可以用transient关键字声明属性。
3.2.2 继承关系图
3.2.3 知识要点
- File 类
- RandomAccessFile类
- 流类
- 字节流
- InputStream(输入字节流)
- FileInputStream(文件输入流)
- DataInputStream
- PipedInputStream(管道输入流)
- ByteArrayInputStream(虚拟文件输入流)
- BufferedInputStream
- FileInputStream(文件输入流)
- OutputStream(输出字节流)
- FileOutputStream(文件输出流)
- PrintStream(打印)
- DataOutputStream
- PipedOutputStream(管道输出流)
- ByteArrayOutputStream(虚拟文件输出流)
- BufferedOutputStream
- FileOutputStream(文件输出流)
- InputStream(输入字节流)
- 字符流
- Reader
- FileReader(文件)
- PipedReader(管道)
- BufferedReader
- Writer
- FileWriter(文件)
- PipedWriter(管道)
- PrintWriter(打印)
- BufferedWriter
- Reader
- 其他流
- 管道流
- PipedInputStream
- PipedWriter
- PipedOutputStream
- PipedReader
- 虚拟文件流
- ByteArrayOutputStream
- ByteArrayInputStream
- 打印流
- PrintStream
- PrintWriter
- 数据处理流
- DataInputStream
- DataOutputStream
- 合并流
- SequenceInputStream
- 管道流
- IO包中类的层次关系
- 字节流
- 字符编码
- 对象序列化
- ObjectlnputStream
- ObjectOutputStream
- Serializable
- 字符编码
- GBK
- Unicode
- ASCII