11.20互联网组实习第一天笔记

11.20(今天主要学会用git,从git上clone了一个项目看看代码)

意思是一样,都是用于判断是否为null
但是比较而言(设a为比较对象),null== a 更为安全,当你编写代码是很有可能把==写为=,则 a==null变为了a=null,显然这是一个恒为真的,所以会影响你的程序,而且很难查出错误的原因

 

 

你这样写字符串的equal,发生错误是很常见的。你怎么知道strName或是strPasswrod不是null ?!!
如果为空,显然会抛出空异常。我们在比较字符串的时候最好是这样写:
    if( "hello" .equals( strName) ){
         //.......
    }
这样可以避免空异常。
 当然,更保险的是先判断null再做比较
      if( strName != null  &&  "hello" .equals( strName) ){
         //.......
      }

 

 

 

 

printwriter是向文本输出流打印对象的格式化表示形式。此类实现在PrintStream中的所有 与PrintStream类不同,如果启用了自动刷新,则只有在调用 println、printf 或 format 的其中一个方法时才可能完成此操作,而不是每当正好输出换行符时才完成。这些方法使用平台自有的行分隔符概念,而不是换行符。 此类中的方法不会抛出 I/O 异常,尽管其某些构造方法可能抛出异常。客户端可能会查询调用checkError()是否出现错误。

 

 

Java中instanceof和isInstance区别详解

 一次性搞定instanceofisInstanceinstanceofisInstance长的非常像,用法也很类似,先看看这两个的用法:

obj.instanceof(class)

也就是说这个对象是不是这种类型,

1.一个对象是本身类的一个对象

2.一个对象是本身类父类(父类的父类)和接口(接口的接口)的一个对象

3.所有对象都是Object

4.凡是null有关的都是false  null.instanceof(class)

 

class.inInstance(obj)

这个对象能不能被转化为这个类

1.一个对象是本身类的一个对象

2.一个对象能被转化为本身类所继承类(父类的父类等)和实现的接口(接口的父接口)强转

3.所有对象都能被Object的强转

4.凡是null有关的都是false   class.inInstance(null)

类名.class和对象.getClass()几乎没有区别,因为一个类被类加载器加载后,就是唯一的一个类。

 

 

bufferwriter和stringwriter的异同

如它们的名字所暗示的,BufferedWriter 仅仅是额外增加了缓冲(Buffered) 功能,也就是它依然将数据写入到原来的那个 Writer (就是你创建 BufferedWriter 时的那个参数 writer) 中,只是它可能不是每次调用立即写出去而是有缓冲,至于缓冲的方法和时机这我们不需要关心。我们只需要按它文档说的,事情做完了之后或你认为需要立即写出时就 flush 一下就可以了。StringWriter 则是把一个东西写成一个 String 的一部分,它用来拼接字符串。

所有这些都叫 "Wrapper" ,在 Java 流式 API 中它是 Filtered ...,就像 FilteredInputStream, FilteredOutputStream 的功能一样。 像 ZipOutputStream 就是一个 Wrapper 在写入数据时压缩,数据本身依然是写入到原来的 OutputStream,我们只是额外增加了 Zip 压缩的功能。

 

使用StringReader和StringWriter操作字符串

编程举例:写一函数把StringReader中输入流中的字符串全部转换成大写,然后将结果写到一个StringWriter中,然后使用这一函数将以字符串全部转成大写

[java] view plain copy

  1. package cn.itcast.stringstream;  
  2. import java.io.IOException;  
  3. import java.io.StringReader;  
  4. import java.io.StringWriter;  
  5. public class StringStreamTest {  
  6.     public static void main(String[] args) {  
  7.         String str = "abcdefghijklmn";  
  8.         transform(str);  
  9.     }  
  10. 10.     public static void transform(String str) {  
  11. 11.         StringReader sr = new StringReader(str);  
  12. 12.         StringWriter sw = new StringWriter();  
  13. 13.         char[] chars = new char[1024];  
  14. 14.         try {  
  15. 15.             int len = 0;  
  16. 16.             while ((len = sr.read(chars)) != -1) {  
  17. 17.                 String strRead = new String(chars, 0, len).toUpperCase();  
  18. 18.                 System.out.println(strRead);  
  19. 19.                 sw.write(strRead);  
  20. 20.                 sw.flush();  
  21. 21.             }  
  22. 22.             sr.close();  
  23. 23.             sw.close();  
  24. 24.         } catch (IOException e) {  
  25. 25.             e.printStackTrace();  
  26. 26.         } finally {  
  27. 27.             sr.close();  
  28. 28.             try {  
  29. 29.                 sw.close();  
  30. 30.             } catch (IOException e) {  
  31. 31.                 e.printStackTrace();  
  32. 32.             }  
  33. 33.         }  
  34. 34.     }  

35. }  

 

 

 

 

 

 

 

printwriter

 编辑

printwriter是向文本输出流打印对象的格式化表示形式。此类实现在PrintStream中的所有 与PrintStream类不同,如果启用了自动刷新,则只有在调用 println、printf 或 format 的其中一个方法时才可能完成此操作,而不是每当正好输出换行符时才完成。这些方法使用平台自有的行分隔符概念,而不是换行符。 此类中的方法不会抛出 I/O 异常,尽管其某些构造方法可能抛出异常。客户端可能会查询调用checkError()是否出现错误。

 

 

e.printStackTrace()介绍


public void printStackTrace()将此 throwable 及其追踪输出至标准错误流。此方法将此 Throwable 对象的堆栈跟踪输出至错误输出流,作为字段 System.err 的值。输出的第一行包含此对象的 toString() 方法的结果。剩余行表示以前由方法 fillInStackTrace() 记录的数据。此信息的格式取决于实现,但以下示例是最常见的:
java.lang.NullPointerException
         at MyClass.mash(MyClass.java:9)
         at MyClass.crunch(MyClass.java:6)
         at MyClass.main(MyClass.java:3)
本示例通过运行以下程序生成:
class MyClass {
     public static void main(String[] args) {
         crunch(null);
     }
     static void crunch(int[] a) {
         mash(a);
     }
     static void mash(int[] b) {
         System.out.println(b[0]);
     }
}

 

还有就是,

catch(Exception e){
e.printStackTrace() ;

当try语句中出现异常是时,会执行catch中的语句,java运行时系统会自动将catch括号中的Exception e 初始化,也就是实例化Exception类型的对象。e是此对象引用名称。然后e(引用)会自动调用Exception类中指定的方法,也就出现了e.printStackTrace() ;。
printStackTrace()方法的意思是:在命令行打印异常信息在程序中出错的位置及原因。(这是白话解释,比较容易理解)

关于System.out.println(e)与e.printStackTrace()

在抛出异常的情况下,有很多方法,System.out.println(e);这个方法打印出异常,并且输出在哪里出现的异常;e.printStackTrace()也是打印出异常,但是它还将显示出更深的调用信息。比如说:

A extends ---> B extends---> C

当在创建A的过程中出现问题了,我们抛出异常。<

System.out.println(e),除了标准异常外,只打印at A 然后再向外层层输出。

e.printStackTrace(),除了标准异常外,打印

 at C

 at B

 at A

 .......再向外层调查。

在向外层调查的情况下,都一样。最后都会回到com.sun.midp.main.Main.main

 

System.out.println();当发生异常时显示你自己设定的字符串信息;就比如下面的代码,try里面进行IO操作,你知道要抛出异常肯定也是IO异常,catch里面就写上特定的IOException,自己打印就行了

try{
//function
}
catch(IOException exc){
    System.out.println("IOException");
}
e.printStackTrace();是打印异常的堆栈信息,指明错误原因,其实当发生异常时,通常要处理异常,这是编程的好习惯,所以e.printStackTrace()可以方便你调试程序!

 

 

 

 

 

初识国际化和ResourceBundle

这个类主要用来解决国际化和本地化问题。国际化和本地化可不是两个概念,两者都是一起出现的。可以说,国际化的目的就是为了实现本地化,详细的介绍可以看本文的最后。比如对于“取消”,中文中我们使用“取消”来表示,而英文中我们使用“cancel”。若我们的程序是面向国际的(这也是软件发展的一个趋势),那么使用的人群必然是多语言环境的,实现国际化就非常有必要。而ResourceBundle可以帮助我们轻松完成这个任务:当程序需要一个特定于语言环境的资源时(如 String),程序可以从适合当前用户语言环境的资源包(大多数情况下也就是.properties文件)中加载它。这样可以编写很大程度上独立于用户语言环境的程序代码,它将资源包中大部分(即便不是全部)特定于语言环境的信息隔离开来。

这使编写的程序可以:

  • 轻松地本地化或翻译成不同的语言
  • 一次处理多个语言环境
  • 以后可以轻松进行修改,以便支持更多的语言环境 

测试及验证

下面我们来模拟一个多语言的环境

定义四个资源文件:res_en_US.properties、res_zh_CN.properties、res_zh.properties、res.properties

res_en_US.properties:cancelKey=cancel

res_zh_CN.properties:cancelKey=\u53D6\u6D88(取消)

res_zh.properties:cancelKey=\u53D6\u6D88zh(取消zh)

res.properties:cancelKey=\u53D6\u6D88default(取消default)

 

命名规则按照:资源名+_语言_国别.properties,每个资源文件中定义了本地化的信息,那么系统如何取到对应的资源文件呢?

[java] view plain copy

  1. ResourceBundle bundle = ResourceBundle.getBundle("res", new Locale("zh", "CN"));  

 

其中new Locale("zh", "CN");这个对象就告诉了程序你的本地化信息,就拿这个来说吧:程序首先会去classpath下寻找res_zh_CN.properties

若不存在,那么会去找res_zh.properties,若还是不存在,则会去寻找res.properties,要还是找不到的话,那么就该抛异常了:MissingResourceException

我们可以来写个测试程序验证一下:

 

[java] view plain copy

  1. package bundle.test;  
  2.   
  3. import java.util.Locale;  
  4. import java.util.ResourceBundle;  
  5.   
  6. public class BundleTest {  
  7.   
  8.     public static void main(String args[]) {  
  9.         ResourceBundle bundle = ResourceBundle.getBundle("res", new Locale("zh", "CN"));  
  10. 10.         String cancel = bundle.getString("cancelKey");  
  11. 11.         System.out.println(cancel);  
  12. 12.           
  13. 13.         bundle = ResourceBundle.getBundle("res", Locale.US);  
  14. 14.         cancel = bundle.getString("cancelKey");  
  15. 15.         System.out.println(cancel);  
  16. 16.           
  17. 17.         bundle = ResourceBundle.getBundle("res", Locale.getDefault());  
  18. 18.         cancel = bundle.getString("cancelKey");  
  19. 19.         System.out.println(cancel);  
  20. 20.   
  21. 21.         bundle = ResourceBundle.getBundle("res", Locale.GERMAN);  
  22. 22.         cancel = bundle.getString("cancelKey");  
  23. 23.         System.out.println(cancel);  
  24. 24.     }  

25. }  

 

输出:

取消

cancel

取消

取消

 

这里前三个都在我们的预期范围之内,但是最后一个GERMAN,应该会去使用res.properties这个资源包吧?怎么使用了res_zh_CH.properties?

原来ResourceBundle为我们提供了一个fallback(也就是一个备用方案),这个备用方案就是根据当前系统的语言环境来得到的本地化信息。

所以若是找不到GERMAN的,之后就会去找CHINA了,所以找到了res_zh_CH.properties这个资源包

这点我也是看了源代码才明白的,下面就贴上一些关键的源代码:

[java] view plain copy

  1. ResourceBundle baseBundle = null;  
  2. for (Locale targetLocale = locale;  
  3.      targetLocale != null;  
  4.      targetLocale = control.getFallbackLocale(baseName, targetLocale)) {// 这里就是去拿备用方案的  
  5.     // do something 我们暂时不关心  
  6. }  

 

跟踪control.getFallbackLocale(baseName, targetLocale)看看备用方案到底是什么?

[java] view plain copy

  1. public Locale getFallbackLocale(String baseName, Locale locale) {  
  2.     if (baseName == null) {  
  3.     throw new NullPointerException();  
  4.     }  
  5.     Locale defaultLocale = Locale.getDefault();  
  6.     return locale.equals(defaultLocale) ? null : defaultLocale;  
  7. }  

当显式定义的本地化信息并不是当前系统的本地化信息时,若未能通过显式定义的找到资源包,那么就去转而通过当前系统的本地化信息去找了~

最后放一点小知识吧~

 

国际化和本地化

国际化(Internationalization)是设计一个适用于多种语言和地区的应用程序的过程。适用于多种语言和地区的含义是当使用不同语言及处于不同的地区的用户在使用这个应用程序时,应用程序必须使用他们能看懂的语言和符合他们文化习惯来显示信息。国际化有时候被简称为i18n,因为有18个字母在国际化的英文单词的字母i和n之间。


一个国际化的程序通常具有以下特征:

  • 有一个附加的本地化数据(localized  data)及拥有在全世界各个地区执行的能力。
  • 文本的元素,比如状态信息或GUI截面的lables,不是直接写(hardcoded)在程序中,而是被存储在本地化的数据中,并且能被程序正确的动态的使用。
  • 支持新的语言时,不需要修改程序,不需要重新编译。
  • 文化差异的数据,比如日期和货币,必须根据拥护的语言和习惯显示不同的格式。
  • 可以被迅速的本地化。

        本地化(Localization)是指通过增加本地描述的构件(locale-specific components )和文字翻译工作来使应用程序适应于不同的语言和地区的过程。本地化有时候被简称为l10n,应为有10个字母在本地化的英文单词的字母l和n之间。通常本地化最耗时的工作应该是文字翻译。本地化工作者们要根据地区的具体需求来为日期、数字和通货等数据建立新的格式。其他类型的数据,象声音,图象等,也需要根据具体需要来决定是否本地化。

 

 

 

SLF4J基本介绍

每一个Java程序员都知道日志对于任何一个Java应用程序尤其是服务端程序是至关重要的,而很多程序员也已经熟悉各种不同的日志库,如java.util.logging、Apache log4j、logback。但如果你还不知道SLF4J(Simple logging facade for Java)的话,那么是时候在你的项目中学习使用SLF4J了。

SLF4J不同于其他日志类库,与其它日志类库有很大的不同。SLF4J(Simple logging Facade for Java)不是一个真正的日志实现,而是一个抽象层( abstraction layer),它允许你在后台使用任意一个日志类库。如果是在编写供内外部都可以使用的API或者通用类库,那么你真不会希望使用你类库的客户端必须使用你选择的日志类库。

如果一个项目已经使用了log4j,而你加载了一个类库,比方说 Apache Active MQ——它依赖于于另外一个日志类库logback,那么你就需要把它也加载进去。但如果Apache Active MQ使用了SLF4J,你可以继续使用你的日志类库而无需忍受加载和维护一个新的日志框架的痛苦。

总的来说,SLF4J使你的代码独立于任意一个特定的日志API,这是对于API开发者的很好的思想。虽然抽象日志类库的思想已经不是新鲜的事物,而且Apache commons logging也已经在使用这种思想了,但SLF4J正迅速成为Java世界的日志标准。让我们再看几个使用SLF4J而不是log4j、logback或者java.util.logging的理由。

2 SLF4J对比Log4J,logback和java.util.Logging的优势

正如我之前说的,在你的代码中使用SLF4J写日志语句的主要出发点是使得你的程序独立于任何特定的日志类库,依赖于特定类库可能需要使用不同于你已有的配置,并且导致更多维护的麻烦。除此之外,还有一个SLF4J API的特性是使得我坚持使用SLF4J而抛弃我长期间钟爱的Log4j的理由,是被称为占位符(place holder),在代码中表示为“{}”的特性。占位符是一个非常类似于在Stringformat()方法中的%s,因为它会在运行时被某个提供的实际字符串所替换。这不仅降低了你代码中字符串连接次数,而且还节省了新建的String对象。通过使用SLF4J,你可以在运行时延迟字符串的建立,这意味着只有需要的String对象才被建立。而如果你已经使用log4j,那么你已经对于在if条件中使用debug语句这种变通方案十分熟悉了,但SLF4J的占位符就比这个好用得多。

这是你在Log4j中使用的方案,但这并不有趣,而且降低了代码可读性,因为它增加了不必要的繁琐重复代码(boiler-plate code):

if (logger.isDebugEnabled()) {
    logger.debug("Processing trade with id: " + id + " symbol: " + symbol);
}
·         1
·         2
·         3

另一方面,如果你使用SLF4J的话,你可以得到更简洁格式的结果,就像以下展示的一样:

logger.debug("Processing trade with id: {} and symbol : {} ", id, symbol);
·         1

在SLF4J,我们不需要字符串连接而且不会导致暂时不需要的字符串消耗。取而代之,我们在一个以占位符和参数传递实际值构成的模板格式下写日志信息。你可能会在想万一我有很多个参数怎么办?嗯,那么你可以选择使用变量参数版本的日志方法或者以Object数组传递。这是一个相当方便和高效方法的打日志方法。记住,在生产最终日志信息字符串之前,这个方法会检查一个特定的日志级别是不是打开了,这不仅降低了内存消耗而且预先降低了CPU去处理字符串连接命令的时间。这里是使用SLF4J日志方法的代码,来自于slf4j-log4j12-1.6.1.jar中的Log4j的适配器类Log4jLoggerAdapter。

public void debug(String format, Object arg1, Object arg2) {
    if (logger.isDebugEnabled()) {
        FormattingTuple ft = MessageFormatter.format(format, arg1, arg2);
        logger.log(FQCN, Level.DEBUG, ft.getMessage(), ft.getThrowable());
    }
}
·         同时,我们应该知道打日志是对应用程序性能有着很大影响,在生产环节上我们建议只进行必要的日志记录。

 

 

LoggerFactory.getLogger用法

 

使用指定类初始化日志对象

在日志输出的时候,可以打印出日志信息所在类
如:Logger logger = LoggerFactory.getLogger(com.Book.class);
       logger.debug("日志信息");
       将会打印出: com.Book : 日志信息

 

 

Map类提供了一个称为entrySet()的方法,这个方法返回一个Map.Entry实例化后的对象集。接着,Map.Entry类提供了一个getKey()方法和一个getValue()方法,因此,上面的代码可以被组织得更符合逻辑。举例如下: 
Map map = new HashMap(); 
Iterator iterator = map.entrySet().iterator(); 
while(iterator.hasNext()){ 
      Map.Entry entry = (Map.Entry)iterator.next(); 
      Object key = entry.getKey(); 
      Object value = entry.getValue(); 

 

for (Map.Entry<String, Object> entry : map.entrySet()) {
   if (entry.getValue() != null) {
      list.add(entry.getKey() + "=" + entry.getValue() + "&");
   }
}

 

 

BigDecimal

Java在java.math包中提供的API类BigDecimal,用来对超过16位有效位的数进行精确的运算。双精度浮点型变量double可以处理16位有效数。在实际应用中,需要对更大或者更小的数进行运算和处理。float和double只能用来做科学计算或者是工程计算,在商业计算中要用java.math.BigDecimal。BigDecimal所创建的是对象,我们不能使用传统的+、-、*、/等算术运算符直接对其对象进行数学运算,而必须调用其相对应的方法。方法中的参数也必须是BigDecimal的对象。构造器是类的特殊方法,专门用来创建对象,特别是带有参数的对象。[1] 

 

构造方法

编辑

BigDecimal一共有4个构造方法

BigDecimal(int) 创建一个具有参数所指定整数值的对象。

BigDecimal(double) 创建一个具有参数所指定双精度值的对象。

BigDecimal(long) 创建一个具有参数所指定长整数值的对象。

BigDecimal(String) 创建一个具有参数所指定以字符串表示的数值的对象。

BigDecimal 的运算方式 不支持 + - * / 这类的运算 它有自己的运算方法

BigDecimal add(BigDecimal augend) 加法运算

BigDecimal subtract(BigDecimal subtrahend) 减法运算

BigDecimal multiply(BigDecimal multiplicand) 乘法运算

BigDecimal divide(BigDecimal divisor) 除法运算

例子:

1

2

    BigDecimal volumn = new BigDecimal("1");

    volumn = volumn.add(new BigDecimal("2"));

输出结果:3

 

 

 

java.util.regex是一个用正则表达式所订制的模式来对字符串进行匹配工作的类库包。 
它包括两个类:Pattern和Matcher Pattern 一个Pattern是一个正则表达式经编译后的表现模式。 
Matcher 一个Matcher对象是一个状态机器,它依据Pattern对象做为匹配模式对字符串展开匹配检查。 
首先一个Pattern实例订制了一个所用语法与PERL的类似的正则表达式经编译后的模式,然后一个Matcher实例在这个给定的Pattern实例的模式控制下进行字符串的匹配工作。 
/**
 *
去掉字符串中的换行、回车、制表符
 
* @param str
 
* @return
 
*/
public static String replaceBlank(String str) {
       String dest = "";
       if (str!=null) {
           Pattern p = Pattern.compile("\\t|\\r|\\n");
           Matcher m = p.matcher(str);
           dest = m.replaceAll("");
       }
       return dest;
   }
 

Matcher类同时提供了四个将匹配子串替换成指定字符串的方法: 
replaceAll() 
replaceFirst() 
appendReplacement() 
appendTail() 

 

posted @ 2017-11-21 08:57  lttwjt  阅读(139)  评论(0编辑  收藏  举报