java语言学习

java语言学习

11月15日(周四)

java基础语法

开始阅读head first java,初步了解java面向对象的编程范式,认识了java的主数据类型和引用,了解了数组的用法,编写了一个小程序。

11月16日(周五)

继承与多态
  1. 学会了java中继承的用法,方法的覆盖(子类方法覆盖父类方法)和重载(同名函数参数数量和类型不同)

  2. 了解java中的多态。引用和对象可以是不同的类型。父类的引用变量可以指向任意子类对象(但父类引用变量不可以调用子类特有的方法或实例变量,但如果我们确定父类引用的是子类的对象,可以做强制转换)。参数和返回类型也可以是多态的(例如参数声明为父类对象,实际传入参数可以为父类或子类的引用变量)

  3. 了解了抽象类,抽象类不能被实例化。抽象类应该定义好抽象方法,以便在多态运用中使用这些方法(保证所有子类都有这类方法)

  4. 了解了java中接口的使用。接口是对具有共同特征的部分子类的再一次抽象。使用接口作为参数或返回类型我们就可以传入任何有实现过该接口的东西,以便我们设计出任意层次的多态。

    更新: 看了一个GUI接口实现的例子,加深了对接口的理解。以ActionListener接口为例,首先我们创建implements了该接口的对象(假设命名为someListener),然后我们重写该接口的方法actionPerformed(), 在这里定义监听到action后需要做的操作。假设我们创建一个Button对象,该对象有一个方法addActionListener(Actionlistener l),我们可以把someListener传进去(这里体现了多态,其实任何实现过该接口的对象都可以被传进去),这个方法会将传进去的对象的引用添加到一个Button对象内部的一个list里面。当事件被监听到的时候Button对象会调用到我们重写的actionPerformed().
    在上层的程序设计中,我们需要实现的就是创建对象implements相应接口,重写接口中的方法,调用Button类的添加方法就可以了。

11月19日(周一)

构造函数
  1. 初步了解了java中堆(heap)和栈(stack), 了解了堆栈中内存使用和释放的机制
  2. 了解了构造函数在继承中的重载和调用规则,this和super关键字的使用。写了一篇博文记录下来:
    java中继承与构造函数之间的关系
静态
  1. 了解了静态类,静态方法和静态变量。静态的含义是不可出现可变的变量。这三者之间的关系式由上而下的,即静态类中所有成员都是静态的,静态方法中所有的变量和调用必须是静态的,反过来非静态类或方法则不必排除静态的东西。
  2. 静态变量属于类不属于具体的对象,在类加载(通常是第一次创建该类的实例)时被初始化,被所有对象共享
  3. 静态方法不必通过对象调用(虽然也可以),可以直接被类调用。
  4. java定义常数需要使用静态final变量,以Mathp.PI为例:
    public static final double PI = 3.141592653589793;
    
    需要注意静态final变量声明和初始化可以分开,但必须初始化。常量变量的命名习惯上必须全部大写。
主数据类型包装
  1. 主数据类型和对象在java中有本质区别,从java 5.0开始可以用 autoboxing 自动将主数据类型自动转化成包装过后的对象。主数据类型对应的包装类名称:

    boolean; char; byte; short; int; long; float; double
    Boolean; Character; Byte; Short; Integer; Long;Float;Double

    举个栗子

    public void doNumsNewWay(){
    	ArrayList<Integer> listOfNumbers = new ArrayList<Integer>(); //创建Integer类型的ArrayList
    	listOfNumbers.add(3); //可直接添加int,编译器会自动包装成类
    	int num = listOfNumbers.get(0);//编译器也会自动解开Integer对象的包装赋值给int
    }
    

    这种包装类具有很多api和静态方法,很多情况下比较方便使用,比如Integer.parseInt()可以输入String取得int,反过来Integer.toString()。。autoboxing可以让主数据类型和包装类直接互相替换而不需手动压包拆包。

数字的格式化
  1. String.format()方法可以将数字格式化为我们想要的格式。格式化语法:%[arg number][flags][width][.precision]type, 其中只有type是必要的。基本用法同C++
	>Type: %d decimal, %f float, %x hexadecimal, %c character
	> Date and time: 完整的日期和时间: %tc ; 只有时间: %tr; 周月日%tA %tB %tC
  1. 日期的操作可以通过Calendar对象
java的异常处理
  1. 编写有风险的代码是应该设计满足某种条件(放弃治疗了)时抛出异常(throw), 当调用该方法时,使用try…catch…来捕获异常并处理异常(补救,恢复等) RuntimeExecption不会被编译器检查。 finally块用来放不管有没有异常都必须执行的程序。
  2. 代码可以声明可能有多个异常,对应多个catch,也可以以异常的父型来声明异常,catch异常。设计上应该按照从小到大的原则,先catch子类异常,再退而求其次catch父类。
  3. 除了try/catch,也可以直接duck掉,只需声明一下有可能会遇到异常即可。但这只是为了通过编译器罢了。

11月20号(周二)

java的GUI
  1. swing组件的使用, layout等。
  2. *Listener接口的使用(actionListener, mouseListener, etc)
  3. 了解内部类的使用
例子

研究了书中的musicplayer小程序,了解了监听相关的程序设计方法。

11月21号(周三)

GUI的layout管理
  1. 三管理器BorderLayout, FlowLayout, BoxLayout
储存对象
  1. 序列化(serialization) 和解序列化(deserialization)
    可以把对象转化成可以写入串流的数据,写入文件。反过来也可以从文件读取并展开成对象,相当于encode-decode。对象被序列化时其所引用的所有对象(直到引用链的最后一个对象)都会被序列化。 implements Serializable接口以告诉java虚拟机该对象可以被序列化。不需要被序列化的实例变量应该被标记为transient(会被记为null)。
  2. 解序列化时,java虚拟机会尝试加载对象的类,如果找不到该类会抛出异常。恢复对象时构造函数不会被执行。transient变量会变成null对象引用或主数据类型的默认值。
  3. 把字符串写入文本文件。用BufferedWriter效率更好。
客户端和服务器的通信连接

一般情况下可以分开成客户端程序与服务器程序,这两者共同完成服务器和客户端之间的通信。客户端程序需要一个socket和服务器连接通信。服务器应用程序需要一对socket(等待用户请求的ServerSocket及发给用户通信的Socket)

java的多线程

需要Thread类。java的多线程可以让几个任务看似在同时进行,直到所有线程被执行完毕。

  1. 如何启动新线程: 使用Runnable接口定义类,实现run方法,再将实例传给Thread的构造函数,调用start方法即可开始执行。
  2. java的线程调度器没有API可以调用,有时我们需要保证线程被均等地执行或有顺序,这时可以(非必要)使用sleep使线程沉睡以保证其他线程被执行。这个方法可能会抛出InterruptedException, 对它的调用需要try/catch。
  3. 并发性(concurrency)问题:两个或以上的线程同时对一个对象进行存取。可以使用synchronized关键字修饰方法使他的每次所有步骤在别的线程进来前都会完成。也可以用synchronized关键字只修饰一行或数行指令。
  4. 对象就算是有多个同步化过的方法,也只有一个锁。一旦某个线程进入该对象的同步化方法,其他线程就无法进入该对象上的任何同步化线程。
  5. 死锁(deadlock)问题:两个线程分别交互执行两个同类对象的同步化方法,可能会因为互相持有对方的钥匙而导致另一对象排斥该线程,从而造成程序无法进行。

11月22号(周四)

java中的数据结构

泛型
  1. 泛型: 类似C++中的模板,泛化了类对象或函数的参数类型,可以用一个大写字母来表示,比如说<E>。有几件事情需要注意,首先是创建泛型化类时要声明一下容许的对象(比如new ArrayList()),其次是多态的问题,涉及到泛型类型本身的多态(如List和ArrayList)及容器内对象的多态(容许元素类型的多态),还有就是说类方法取用含有多态类型的变量时有一些限制。下面详细说。
  2. 运用泛型的常见方法有两种,一种是在类声明里定义的类型参数(ex. public class ArrayList<E> extends AbstractList<E> …{ public boolean add(E o) }), 另一种是使用未定义在类声明中的类型参数,比如在方法中我想对参数类型使用泛型,但是这个泛型没有在类声明里定义,可以用这种语法:(ex. public <T extends Animal> void takeThing (ArrayList<T> list), T指定为Animal类或者子类,声明在方法的返回类型之前, 代表这个方法能够传入以Animal或子型来初始化的ArrayList对象)
  3. 泛型的好处:泛型写的程序主要和集合相关。用泛型后编译器会检查集合的类型安全性,不会等到运行的时候才发现错误。还有就是多态参数的问题,见我的博文:使用多态参数与泛型
集合

书上只介绍了这么多,更多的集合相关的东西需要翻阅java数据结构。

  1. 最常用的集合类型: ArrayList,重要的方法有:add(E o), add(int index, E o), addAll(Collection<? extends E> c) , addAll(int index, Collection<? extends E> c), clear(), clone(), contains(), toArray(), set(int index, E element), …etc 需要查阅API文档。注意ArrayList中没有定义sort()方法。add新元素到指定索引会比加到最后要慢,LinkedList对中间的插入会比较快,但有时也可以忽略这中间的差异除非元素量真的很大。
  2. HashSet 是防止重复的集合,使用hashcode来达成存取速度较快的存储方法,可以快速寻找相符的元素。如果使用自定义类型元素的HashSet的话,有一个问题是java不知道一个元素是否与另一个元素重复。见我的博文 HashSet自定义元素类型的重复判定问题
  3. Map中元素以键值对(key:value)存储。适用于需要根据名称取得值的情况。
  4. 对于排序,先忽略具体的java底层实现的排序算法,可以直接调用一些内部的api。
    1. Collections类的sort()静态方法可以对对象list排序。有两种版本的sort(), 第一种sort(List<T> list) 传进去的list的对象需要实现Comparable接口, 实现这个接口需要重写compareTo()方法。另一种重载版本的sort(List<T> lsit, Comparator<? super T> c)不调用compareTo(),而是需要一个参数comparator然后调用comparator的compare()方法,这个版本的sort()不需要我们的类实现Comparable接口,我们可以自定义comparator对list排序。
    2. Treeset类可以以有序状态保持并防止重复。TreeSet的默认构造函数会和sort()一样使用compareTo()方法排序,这种情况下集合中的元素必须是实现Comparable类型的元素。或者,也可以传入Comparator给构造函数,用法同上。

11月26日(周一)

java应用程序部署

Executable JAR
  1. JAR(Java ARchive) 是一个pkzip格式的文件,它能将一组类文件包装进来,因此在交付的时候只需一个JAR文件。
  2. 创建可执行的JAR需要确保编译出来的所有类文件都在classes目录下,需要一个manifest.txt文件描述哪个类带有main()方法。然后执行jar工具来创建带有所有类及manifest的JAR文件。jar -cvmf manifest.txt app1.jar *.class(打包所有的类文件)
  3. 将类放入包中可以避免命名冲突。一般的命名规则是域名反写(com.mogolola)+ 自定义的包名(.projectX)+类名(Myclass)。 source下应设置层次的目录结构。在类中需要加入包指令(package com.mogolola.projectX;)。每个原始文件都只能有一个包指令,因此同一文件的类都会在同一个包中。source文件编译后classes的目录是一样的。
  4. 编译包中的java文件可以直接使用javac -d …/classes/ com/mogolola/projectX/*.java,编译器会自动组织相应的类文件目录
  5. 以包创建JAR目录时,包目录必须完整地包括在JAR中。同样需要manifest.txt指定main()位置,然后用jar工具从com目录开始执行就可以。ex. jar -cvmf manifest.txt App1.jar com 。jar工具除了打包外还会自动创建META—INF目录存放manifest.txt文件。jar -tf指令可以列出jar文件目录,jar -xf可以解压jar文件。java虚拟机可以直接执行JAR文件 java -jar app1.jar. Windows和Mac也支持直接双击执行jar文件。
Java Web Start
  1. JWS可以让程序的首次启动由浏览器执行。当JWS下载程序时,会调用程序的main(),然后用户就可以通过JWS helper app启动应用程序而不需要回到当初的网页。JWS也可以检测服务器上应用程序的局部的更新在不需要用户介入的情况下自动下载更新过的程序。
  2. 工作方式:首先用户点击某网页上JWS应用程序的链接(.jnlp文件),web服务器收到请求发出.jnlp文件给用户的浏览器。浏览器启动JWS, JWS的helper app读取.jnlp文件,然后向服务器请求jar文件。Web会向用户发送.jar文件。JWS取得jar并执行main()。
  3. .jnlp文件(java network launch protocol)是个xml文件,里面记录了相关文件(jar)的起始目录,相对路径,一些tag和config,java版本,可执行jar的名称,哪一个类带有main等。

11月27日

Remote method invocation(RMI)
  1. 本地调用远程的方法,java分布式的基础方法。原理是通过stub(客户端辅助设施)和skeleton(远程服务设施)之间的通信把本地对远程的调用传过去,再把结果传回来。直观的结果是本地向web server请求服务,取回一个辅助设施stub,然后就像调用本地对象或方法一样调用在stub上的远程方法
  2. 一个实现RMI的例子:head first java中创建远程服务的例子
servelet
  1. servelet是放在HTTP Web服务器上运行的java程序。当用户通过浏览器和网页交互时,请求(Request)会送给网页服务器。如果请求需要java的servlet时,服务器会执行或调用servlet代码,执行用户发出请求需要的结果。
  2. 一个简单的servlet应用程序通常是服务器处理请求,以响应对象来响应。实际上servlet通常不会直接和客户端打交道。请求通常先通过容器(container),比如Tomcat

Tomcat可以用作web application server,但主要还是用做servlet的容器。通过实现java servlet和JSP的API们,Tomcat可以接收来自用户的请求,并给用户返回结果。此方法可以产生动态的内容并十分快速,线程化,与平台无关地处理请求。
java servlet 标准(specification) 是为其他主要的java web技术的互用性设计的,Tomcat server上的servlet可以处理Tomcat上给它的任何resource。Tomcat的hierarchical的XML配置文件可以允许非常详细的访问控制(access control),同时保持弱连接(loose coupling),易于部署,容易理解的架构描述(architecture description)
我的简要翻译How Apache Tomcat uses Servlets to quickly deliver a wind range of dynamic content to a client

  1. servlet也可以使用RMI,以远程调用远端的方法。

其他

java位操作

按位非运算符:~

int x = 10;  //00001010
x = ~x; //11110101

按位与运算符:&
按位或运算符:|
按位异或运算符:^

int x = 10; // 00001010
int y = 6; //00000110
int a = x&y // 00000010
int b = x|y //00001110
int c = x^y //00001100 

右移运算符: >>
无符号右移运算符:>>>
左移运算符:<<
x<<y 相当于 x*2y ;x>>y相当于x/2y

不变性

String对象的值一旦创建就不能被改变,String被创建后会被放在叫String Pool的存储区域,不受Garbage Collector管理。Stringbuffer/StringBuilder对象的值是可以改变的

assert

在你认为一定为true的地方加入assert命令,并可以显示信息帮助调试:

assert (height>0):"height = "+ height + "weight = " + weight;
//if true continue
//if false throw out AssertionError
block

程序区段(if{], for(){})中声明的变量生命周期仅在其所在的block中。

参考资料

Java™ Platform, Standard Edition 8 API Specification

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值