1.Java中的闭包与回调

  闭包(Closure)是一种能被调用的对象,它保存了创建它的作用域的信息。JAVA并不能显式地支持闭包,但是在JAVA中,闭包可以通过“接口+内部类”来实现,因为对于非静态内部类而言,它不仅记录了其外部类的详细信息,还保留了一个创建非静态内部类的引用,通过它可以访问外部类的私有成员,因此可以把非静态内部类当成面向对象领域的闭包。通过内部类提供闭包的功能是优良的解决方案,比指针更为灵活、安全。

  回调的价值在于它的灵活性—它可以动态地决定需要调用什么方法,在Swing中,回调被大量使用。简单地说来就是类A提供了一个方法C,但是A不直接调用C,而是通过另外一个类B来调用。

  通过内部类实现闭包时,内部类可以轻松访问外部类,完成回调。

public interface Teachable{
void work();
}
public class Programmer {
private String name;
public Programmer(){} public Programmer(String name){
this.name = name;
}
public String getName(){
return this.name;
}
public void work(){
System.out.println(name + "在灯下敲键盘...");
}
}

  那么假如有一个人既是教师又是程序员,也就是需要定义一个类既继承Programmer父类又要实现Teachable,问题在于这个类只能定义一个work方法,那怎么去实现这个需求呢,这里就可以利用内部类可以访问外部类的私有成员的特点来解决这个问题。

  这里需要注意的是内部类Closure 是私有的,只能通过外部类的getCallbackReference获得。获得Closure对象后又可以轻松地访问到外部类的私有方法。

package com.home;

public class TeachableProgrammer extends Programmer {

    public TeachableProgrammer() {
super();
} public TeachableProgrammer(String name) {
super(name);
} // 教学工作任然由TeachableProgrammer定义
private void teach() {
System.out.println(getName() + "正在讲课");
} private class Closure implements Teachable { @Override
public void work() {
// 非静态内部类实现Teachable的work方法,作用仅仅是向客户类提供一个回调外部类的途径
teach();
}
} // 返回一个非静态内部类的引用,允许外部类通过该引用来回调外部类的方法
public Teachable getCallbackReference() {
return new Closure();
}
}

  测试类:

package com.home;

public class TestClosure {

    public static void main(String[] args) {
TeachableProgrammer tp = new TeachableProgrammer("xx");// 直接调用TeachableProgrammer从Programmer类继承下来的work方法
tp.work();
// 表明上看是调用的Closure的work方法,实际上是通过通过work方法回调TeachableProgrammer的teach方法
tp.getCallbackReference().work();
} }

2.容器类

  Java容器类的用途是用来保存对象,可以分为以下的两个大类:

  1>Collection,一个用于存储对象的序列。又可以具体的分为List,Set和Queue。

  2>Map,一个以键值对来存储对象的序列。

  Arrays和Collections类中提供了很多实用的静态方法。 

  1.创建一个空的collection,向collection中添加元素或者集合,这种添加的方式效率是比较高的

  public boolean addAll(Collection<? extends E> coll)

List<String> c = new ArrayList<String>();
Collection col = new ArrayList();
Collections.addAll(col, 1,2,3,c);

  2.根据元素自然顺序 对指定列表按升序排序。此方法内部调用了Comparable 的compareTo()方法。

   public static <T extends Comparable<? super T>> void sort(List<T> list)

  3.根据元素的自然顺序,返回给定 collection 的最大元素

  public <T extends Object &   Comparalbe<? super T>> T max(Collection<? extends T> col)

  4.使用指定元素替换指定列表中的所有元素

  public static <T> void fill(List<? super T> list,T obj)

  5. 使用另一个值替换列表中出现的所有某一指定值

  public static T replacAll(List<T>,T oldValue,T newValue)

  6.反转指定列表中元素的顺序

  public static void reverse(List<?> list)

  7.如果搜索键包含在列表中,则返回搜索键的索引,否则返回 (-(插入点) - 1)

  public static <T> int binarySearch(List<? extends t> list,T key,Comparator<? extends T> c)

  Arrays常用的方法:

  1.二分查找
   private static int binarySearch0(double[] a, int fromIndex, int toIndex,double key)  

  2.复制

  public static <T> T[] copyOf(T[] original, int newLength) 

  3.复制部分

  public static <T> T[] copyOfRange(T[] original, int from, int to)

  4.排序

  Arrays.sort();

  5.填充  

  Arrays.fill()
  6.将数组转为List

  Arrays.asList()

  注:System.arraycopy(Object src, int srcPos, Object dest, int destPos, int length)也能实现数组复制的功能,只是System.arraycopy是native的,效率也是较高的。

  新的程序中不应该出现过时的Vector、HashTable和Stack。

  a.如果需要大量的随机访问,就应该使用ArrayList,如果需要从表中间进行大量的插入或删除操作,则应该使用LinkedList。

  b.如果访问速度优先考虑,则应该使用HashMap,如果希望顺序访问键值对中的键,则应该使用TreeMap,LinkedHashMap保持了元素的插入顺序,同时也进行了hash散列。

  c.Set中没有重复的元素,和Map类似,HashSet访问速度快,TreeSet是有序的,LinkedTreeSet保持了插入的顺序。可以在构造TreeSet时传入自己的Comparator来按照自己的意愿完成排序。

  d.可以使用iterator()方法要求集合返回一个迭代器,来顺序遍历和操作集合中的元素。迭代器的功能也可以通过增强for循环来完成。 

        List<String> c = new ArrayList<String>();
Collections.addAll(c, "l","o","v","e"); Iterator<String> it = c.iterator();
while(it.hasNext()){
System.out.println("get by iterator: "+ it.next());
} for(String s : c){
System.out.println("get by for: "+ s);
}

  e.Iterator只能向后移动,ListIterator是其的子类,但是却可以实现前后移动,只适用于List类型的容器。

  f.尽管Java中已经提供了栈(Stack)、队列(Queue)、双端队列的实现,但是自己用LinkedList来实现功能更为强大的队列和栈也是不错的。

  g.LinkedList实现了Queue接口,可以向上转型为Queue

Queue<String> queue = new LinkedList<String>();

  h.Queue默认的是先进先出,使用Queue的子类PriorityQueue可以实现按优先级排序,让下一个弹出的对象是优先级最高的对象,可以通过自己的Comparator来改变弹出的顺序。

  i.通过EntrySet来访问Map类型的容器

        Map<String,String> map=new HashMap<String,String>();
for (Map.Entry<String, String> m : map.entrySet()) {
System.out.println("key:"+m.getKey()+" value"+m.getValue());
}

3.comparator和comparable的区别  

  都是为了完成对象的排序功能,不同的是Comparable和类本身进行了绑定,Comparator和类本身是没有直接的关系。

class Person implements Comparable {
String name;
int age; @Override
public int compareTo(Object o) {
Person another = (Person) o;
int i = 0;
i = name.compareTo(another.name); // 使用字符串的比较
if (i == 0) { // 如果名字一样,比较年龄, 返回比较年龄结果
return age - another.age;
}
else {
return i; // 名字不一样, 返回比较名字的结果.
}
}
}

  可以直接用 Collections.sort( personList ) 对其排序。

class PersonComparator implements Comparator {
@Override
public int compare(Object o1, Object o2) {
Person one = (Person) o1;
Person another = (Person) o2;
int i = 0;
i = one.name.compareTo(another.name); // 使用字符串的比较
if (i == 0) { // 如果名字一样,比较年龄,返回比较年龄结果
return one.age - another.age;
}
else {
return i; // 名字不一样, 返回比较名字的结果.
}
} }

  Collections.sort( personList , new PersonComparator()) 可以对其排序。

4.equals和hashcode

  hashCode()方法和equals()方法是在Object类中就已经定义了的,所以在java中定义的任何类都会有这两个方法。

   Object类中的equals()方法用来比较两个对象内存地址的值,而原始的hashCode()方法用来返回其所在对象的物理地址。

   如果在比较两个对象时,比较的是对象的内容而不是内存地址,据需要对类中的equals()进行重写。在重写了equals()方法后一定不要忘了重写hashCode()方法,否则该类的对象在HashMap、HashSet中使用时可能会出现问题。

  

   覆盖equals方法看起来似乎很简单,但是如果覆盖不当会导致错误,正确的依据应是:  

  • 自反性。对于任何非null的引用值x,x.equals(x)必须返回true。
  • 对称性。对于任何非null的引用值x和y,当且仅当y.equals(x)返回true时,x.equals(y)必须返回true
  • 传递性。对于任何非null的引用值x、y和z,如果x.equals(y)返回true,并且y.equals(z)也返回true,那么x.equals(z)也必须返回true。
  • 一致性。对于任何非null的引用值x和y,只要equals的比较操作在对象中所用的信息没有被修改,多次调用该x.equals(y)就会一直地返回true,或者一致地返回false。
  • 对于任何非null的引用值x,x.equals(null)必须返回false。

  hashCode()方法和equals()方法间的关系应该是:

  如果X.equals(Y)成立,那么它们的X和Y的hashCode值一定相同。

  如果两个对象X和Y的hashCode相同,但是X.equals(Y)不一定成立。但是X.equals(Y)不成立时,返回不同的hashCode,会提高散列的性能。

5.JAVA重定向输入输出

  重定向标准输入和输出Java的标准输入和输出分别通过system.in和system.out来代表,默认情况下他们分别代表键盘和显示器。

  在system类中提供了3个重定向标准输入和输出的方法:

  setErr(PrintStream err) 重新分配“标准”错误输出流。

  setIn(InputStream in) 重新分配“标准”输入流。

  setOut(PrintStream out) 重新分配“标准”输出流。

  当然我们可以自己来写程序,修改我们应用程序的输入和输出。比如说现在不希望标准输出到显示器上,而是我自己的一个文件里面,或者是说我现在不需要从键盘上来录入内容,而是读我本地的一个文本。

   重定向输出和错误的例子:

import java.io.FileOutputStream;
import java.io.PrintStream; public class RedirectOut {
public static void main(String [ ] args) {
PrintStream ps = null;
try {
ps = new PrintStream(new FileOutputStream("src/Redirect.txt"));
System.setOut(ps);
System.setErr(ps); System.out.println("这里重定向了标准输出");
System.out.println("结束");
throw new RuntimeException("exception happens");
}
catch (Exception e) {
e.printStackTrace();
}
finally {
if (ps != null) {
ps.close();
}
}
}
}

  重定向输入的例子:

import java.io.FileInputStream;
import java.io.IOException;
import java.util.Scanner; public class RedirectIn {
public static void main(String [ ] args) {
FileInputStream fis = null;
try {
fis = new FileInputStream("src/Redirect.txt");
System.setIn(fis);
// 使用system.in创建Scanner对象,用来获取标准输入
Scanner sc = new Scanner(System.in);
sc.useDelimiter("\n");// 增加分隔符
while (sc.hasNext()) {
System.out.println(sc.next());
}
}
catch (Exception e) {
e.printStackTrace();
}
finally {
if (fis != null) {
try {
fis.close();
}
catch (IOException e) {
e.printStackTrace();
}
}
}
}
}

6.Process和子进程的通信

  Runtime对象有exec方法,他可以运行jvm命令行,该方法产生一个Process对象,Process对象代表由该Java程序启动的子进程,Process类有以下方法,可以和子进程通信;

  InputStream getErrorStream():获取子进程的错误流

  InputStream getInputStream():获取子进程的输入流

  OutputStream getOutputStream():获取子进程的输入流

《Thinking in Java》学习笔记(四)的更多相关文章

  1. 《CSS网站布局实录》学习笔记(一)

    今天开始,认真学习前端技术,哈哈哈~~~加油~~~ 推荐这本<CSS网站布局实录>(第2版)给初级入门选手,虽然这本书年代有点久远,不过很经典. 注明一下:这里讲述的CSS均为CSS 2. ...

  2. 《CSS网站布局实录》学习笔记(四)

    第四章 CSS网站元素设计 4.1 网站导航 网站导航是网站中最重要的元素.从形式上看,网站导航主要分横向导航.纵向导航.下拉及多级菜单导航灯3种常见形式. 横向导航:作为门户网站的设计而言,主导航一 ...

  3. 《CSS网站布局实录》学习笔记(六)

    第六章 CSS高级应用与技巧 6.1 id与class 6.1.1 什么是id id是XHTML元素的一个属性,用于标识对象名称.无论是class还是id,都是XHTML所支持的公共属性,并且也是其核 ...

  4. 《CSS网站布局实录》学习笔记(三)

    第三章 CSS网页布局与定位 3.1 div 几乎XHTML中的任何标签都可以用于浮动与定位,而div首当其冲.对于其他标签而言,往往有它自身存在的目的,而div元素存在的目的就是为了浮动与定位. 3 ...

  5. 《CSS网站布局实录》读书笔记

    从Web标准.HTML标记.CSS语法基础介绍到实用技巧,事无巨细.实体书已不印刷,只能下载电子版 书的背景: 国内第一本web标准的CSS布局书,2006年9月第一版,作者李超. 环境背景: 当时主 ...

  6. 《css网站布局实录》(李超)——读书札记

    1.web表现层技术 2.HTML链接设计思想 3.对信息进行合理的分析.分类与处理来创造商业价值. 4.头部描述浏览器所需信息,主体包含所需要展现的具体内容. 5.HTML(XHTML)XML 6. ...

  7. 《CSS网站布局实录》学习笔记(二)

    第二章 XHTML与CSS基础 2.1 XHTML基础 XHTML是网页代码的核心内容,标准XHTML代码如下: <!DOCTYPE html PUBLIC "-//W3C//DTD ...

  8. 《CSS网站布局实录》学习笔记(五)

    第五章 CSS内容排版 5.1 文字排版 5.1.1 通栏排版 进行网页通栏排版时,只要直接将段落文字放置于p或者其他对象中,再对段落文字应用间距.行距.字号等样式控制,便形成了排版雏形. 5.1.2 ...

  9. 全新的css网站布局--Grid布局

    Grid布局全新的css网站布局 CSS Grid 布局由两个核心组成部分是 wrapper(父元素)和 items(子元素). wrapper 是实际的 grid(网格),items 是 grid( ...

  10. C#可扩展编程之MEF学习笔记(四):见证奇迹的时刻

    前面三篇讲了MEF的基础和基本到导入导出方法,下面就是见证MEF真正魅力所在的时刻.如果没有看过前面的文章,请到我的博客首页查看. 前面我们都是在一个项目中写了一个类来测试的,但实际开发中,我们往往要 ...

随机推荐

  1. C++课程设计类作业3

    #include <bits/stdc++.h> using namespace std; class A { public: A() { a=b=; cout<<" ...

  2. UVA - 12050-Palindrome Numbers

    12050 - Palindrome Numbers Time limit: 3.000 seconds A palindrome is a word, number, or phrase that ...

  3. Spring框架学习笔记(10)——Spring中的事务管理

    什么是事务 举例:A给B转500,两个动作,A的账户少500,B的账户多500 事务就是一系列的动作, 它们被当做一个单独的工作单元. 这些动作要么全部完成, 要么全部不起作用 一.注解添加事务管理方 ...

  4. UI Automation

    public Form1() { InitializeComponent(); this.textBox1.AccessibilityObject.Name = "t1"; thi ...

  5. angular $cookies、$cookieStore

    js 文件 加载 <script src="angular-cookies/angular-cookies.js"></script>注入:angular. ...

  6. php 类的相互访问

    ========================================================================================== // public ...

  7. SQLITE3 使用总结(3~5)(转)

    3 不使用回调查询数据库/ `- ^# T6 ?, F: H* m2 ~# ~上 面介绍的 sqlite3_exec 是使用回调来执行 select 操作.还有一个方法可以直接查询而不需要回调.但是, ...

  8. PostgreSql问题:ERROR: column "1" does not exist

    摘录自:http://blog.csdn.net/shuaiwang/article/details/1807421 在PostgreSQL中,不论是在pgAdmin中还是在命令行控制台里面,在SQL ...

  9. 深入理解HashMap的扩容机制

    什么时候扩容: 网上总结的会有很多,但大多都总结的不够完整或者不够准确.大多数可能值说了满足我下面条件一的情况. 扩容必须满足两个条件: 1. 存放新值的时候当前已有元素的个数必须大于等于阈值 2. ...

  10. mysql主从同步(4)-Slave延迟状态监控

    mysql主从同步(4)-Slave延迟状态监控  转自:http://www.cnblogs.com/kevingrace/p/5685511.html 之前部署了mysql主从同步环境(Mysql ...