JAVA

advertisement
COMMON JAVA
JAVA数据结构与常用类库简介
Bingoo
JAVA类加载
Java Classloading
•
Why do we care?
– Because if we’re gonna write code at runtime, we’d better know
how to load and use it…
– Because we don’t really understand classes
•
So… what identifies a class?
– Its name
– Its package
– Its classloader
•
It means that
– We can have multiple instances of a class loaded at the same time
– Two instances of the same class from different classloaders are not compatible and not
assignable
– Static variables are static only in the context of a classloader, not globally as we’re
always told
Java Classloading
•
So what is this classloader?
– A Java class (subclass of java.lang.ClassLoader),
responsible for loading other classes used by the JVM
– Classloaders are arranged as a tree
•
Bootstrap classloader
– Loads the Java system
•
•
•
•
•
•
•
jre/lib/resources.jar – series of resource files
jre/lib/rt.jar – the java.*, javax.*, etc packages
jre/lib/sunrsasign.jar
jre/lib/jsse.jar – secure socket extension
jre/lib/jce.jar – Java cryptography extension
jre/lib/charsets.jar
jre/classes
– The important stuff is in rt.jar – the base Java classes
Java Classloading
Commandline Java App
Tomcat (6)
Bootstrap
classloader
Loads only
bootstrap.jar and
tomcat-juli.jar
Ext
classloader
Loads Tomcat
commons library jars
Application
/ System
classloader
Loads the Application Jars
from the classpath
Application
/ System
classloader
Common
classloader
Loads jars in the
webapp lib directory
WAR 1
classloader
WAR 2
classloader
自定义类加载器加载一个类的步骤
ClassNotFoundException and
NoClassDefFoundError
• ClassNotFoundException comes when JVM tries
to load a class at runtime dynamically means you
give the name of class at runtime and then JVM
tries to load it and if that class is not found in
classpath it throws ClassNotFoundException
• While in case of NoClassDefFoundError the
problematic class was present during Compile
time and that's why program was successfully
compile but not available during runtime by any
reason.
aopalliance-1.0.jar
asm-3.3.jar
asm-commons-3.3.jar
asm-tree-3.3.jar
axis-1.4.jar
bcprov-jdk16-1.45.jar
cglib-nodep-2.2.jar
commons-beanutils-1.8.3.jar
commons-codec-1.5.jar
commons-collections-3.2.jar
commons-discovery-0.4.jar
commons-fileupload-1.2.2.jar
commons-httpclient-3.1.jar
commons-io-2.0.1.jar
commons-lang-2.1.jar
commons-logging-1.1.1.jar
commons-net-2.2.jar
commons-pool-1.6.jar
commons-ssh-1.5.1.jar
dom4j-1.6.1.jar
ems-consumer-0.0.1-SNAPSHOT.jar
fastjson-1.1.17.jar
freemarker-2.3.18.jar
guava-12.0.jar
hadoop-core-0.20-append-r1056497.jar
hbase-0.90.4.jar
hessian-3.1.6.jar
ibatis-sqlmap-2.3.4.726.M01.jar
javassist-3.11.0.GA.jar
jline-0.9.94.jar
jmockit-0.999.4.jar
jsch-0.1.46.jar
jsr305-1.3.9.jar
junit-4.8.2.jar
kafka-0.7.0.jar
Linkage-EcsCommon-0.0.1.jar
log4j-1.2.16.jar
ntfPlat-mailsend-0.0.1.jar spring-context-support-2.5.6.ja
ntfplat-send-0.0.1.jar
spring-core-2.5.6.jar
ognl-3.0.4.jar
spring-web-2.5.6.jar
PageSecurity-0.0.2.jar
spring-webmvc-2.5.6.jar
phw-all-0.1.0.jar
spymemcached-2.8.0.jar
ProxyForEcsSms-1.0.jar struts2-convention-plugin-2.3.
scala-library-2.8.0.jar
struts2-core-2.3.1.2.jar
slf4j-api-1.6.2.jar
struts2-json-plugin-2.3.1.2.jar
slf4j-log4j12-1.6.2.jar
wsdl4j-1.6.2.jar
solr-solrj-3.4.0.jar
xerces-2.6.2.jar
spring-2.5.6.jar
xwork-core-2.3.1.2.jar
spring-beans-2.5.6.jar
zkclient-0.1.jar
spring-context-2.5.6.jar zookeeper-3.3.3.jar
JAVA Exception
几种设计异常的最佳实践
(Best Practises for Designing the API)
•
•
•
•
•
•
选择Checked还是Unchecked的几个经典依据
Exception的封装问题
如无必要不要创建自己的Exception
不要用Exception来作流程控制
不要轻易的忽略捕获的Exception
不要简单地捕获顶层的Exception
三种”情景”导致异常的抛出
• 编程错误导致(Exception due Programming errors)
– 这种情景下,异常往往处于编程错误(如:
NullPointerException 或者 IllegalArgumentException),这时异
常一旦抛出,客户端将变得无能为力。
• 客户端代码错误导致(Exception due client code errors)
– 客户端试图调用API不允许的操作
• 资源失败导致(Exception due to resource failures)
– 如内存不足或网络连接失败导致出现异常等。这些
异常的出现客户端可以采取相应的措施来恢复应用
程序的继续运行。
Java中异常的类型 Checked and
Unchecked Exceptions

A checked exception is one that will be checked by
the compiler for a surrounding try/catch block if
that method have a throws clause

An unchecked exception, also called a
RuntimeException, does not require programmer
intervention with a try/catch block
 Either there is nothing we can do with this type of
problem (sun)
 Or, this type of problem can be remedied by fixing code
○ For example, an ArrayIndexOutOfBounds
Checked or Unchecked exception
• 问自己一个问题,“如果这种异常一旦抛
出,客户端会做怎样的补救?”
– 如果客户端可以通过其他的方法恢复异常,那
么这种异常就是checked exception;
– 如果客户端对出现的这种异常无能为力,那么
这种异常就是Unchecked exception;
– 尽量使用unchecked exception来处理编程错误;
譬如:NullPointerException ,
IllegalArgumentException 和 IllegalStateException
保护封装性(Preserve encapsulation)
• 不要让你要抛出的checked exception升级到
较高的层次。
– 例如,不要让SQLException延伸到业务层。业务
层并不需要(不关心?)SQLException。
– 转变SQLException为另外一个checked exception,
如果客户端并不需要恢复这种异常的话;
– 转变SQLException为一个unchecked exception,
如果客户端对这种异常无能为力的话(多数情
况);
使用异常最佳实践
• 总是要做一些清理工作(Always clean up after yourself)
– 如果使用一些资源例如数据库连接或者网络连接,请记住要做一些清理
工作(如关闭数据库连接或者网络连接)
– 要用try-finally来做必要的清理工作
• 不要使用异常来控制流程(Never use exceptions for flow control)
• 不要忽略异常
– 当有异常被抛出的时候,如果你不想恢复它,那么你要毫不犹豫的将其
转换为unchecked exception,而不是用一个空的catch块或者什么也不做来
忽略它,以至于从表面来看象是什么也没有发生一样。
• 不要捕获顶层的Exception
– unchecked exception都是RuntimeException的子类,RuntimeException又继
承Exception,因此,如果单纯的捕获Exception,那么你同样也捕获了
RuntimeException,它将忽略所有的异常,包括unchecked exception.
•
Log exceptions just once
– Logging the same exception stack trace more than once can confuse the
programmer examining the stack trace about the original source of exception.
So just log it once.
Add Java Exception Breakpoint
Guava Throwables
try {
someMethodThatCouldThrowAnything();
} catch (IKnowWhatToDoWithThisException e) {
handle(e);
} catch (Throwable t) {
Throwables.propagateIfInstanceOf(t, IOException.class);
Throwables.propagateIfInstanceOf(t, SQLException.class);
throw Throwables.propagate(t);
}
@Annotations
Annotation Definition

Structured Data
 Comparable to records in OCaml
@interface MyAnnotation {
String value();
// member
int
i() default 123; // member w. default value
}
@interface MarkerAnnotation {
// annotation without any members
}
Annotation Usage
@MyAnnotation(value="text", i=456)
void method() { … }
// default value for i: 123
@MyAnnotation(value="text")
void method2() { … }
// special case for members called "value"
@MyAnnotation("text")
void method3() { … }
// parenthesis can be omitted if no members
@MarkerAnnotation
void method4() { … }
Annotation Members
@interface MyAnnotation {
int
String
Class
SomeEnum
intMember();
stringMember();
classMember();
enumMember();
//
//
//
//
primitives
strings
class literals
enums
// annotions
OnlyThreadWithName annotMember();
// arrays of the above
OnlyThreadWithName[] arrayMember();
}
Annotation Targets in Java 5
@A package some.package.name;
@B class MyClass {
@C Object field;
@D MyClass(@E Object param) {
field = param;
}
@F Object method() {
@G Object localVar = field;
return localVar;
}
}
The Target annotation
@Target(ElementType.TYPE)
—can be applied to any element of a class
@Target(ElementType.FIELD)
—can be applied to a field or property
@Target(ElementType.METHOD)
—can be applied to a method level annotation
@Target(ElementType.PARAMETER)
—can be applied to the parameters of a method
@Target(ElementType.CONSTRUCTOR)
—can be applied to constructors
@Target(ElementType.LOCAL_VARIABLE)
—can be applied to local variables
@Target(ElementType.ANNOTATION_TYPE)
—indicates that the declared type itself is an
告知程序如何处理@Retention
java.lang.reflect.AnnotatedElement接口
public Annotation getAnnotation(Class annotationType);
public Annotation[] getAnnotations();
public Annotation[] getDeclaredAnnotations();
public boolean isAnnotationPresent(Class annotationType);
Class、Constructor、Field、Method、Package等类别,都实现了
AnnotatedElement接口
Java Logging
Logging use-cases
•
•
•
•
•
debugging the software during development
help diagnose bugs during production
trace access for security purposes
create data for statistical use
etc
History
• System.out.println()
• System.err.println()
• e.printStackTrace()
Components
Level/ Priority
Aplicaction
Logger
1..*
Filter
Appender
Layout
Logger Named Hierarchy
A logger is said to be an ancestor of another logger
if its name followed by a dot is the prefix part in the
descendant logger name.
PS: 大小写敏感
root
com.site.software
com.site.software.model
com.site.software.model.dao
com.site.software.model.dao.PersonDAOImpl
com.site.software.view
com.site.software is an ancestor logger of the descendant
com.site.software.model.dao
●com.site.software is the parent logger of the child
com.site.software.model
●
Levels
A logger may be assigned to a level.
●
●
●
●
Properties configuration file
log4j.rootLogger=ERROR
log4j.logger.com.site.software=INFO
XML configuration file
Java configuration file
Logger.getRootLogger().setLevel(Level.ERROR);
Logger.getLogger(“com.site.software”).setLevel(Level.INFO);
levels are ordered
TRACE < DEBUG < INFO < WARN < ERROR < FATAL
Level/ Priority
• FATAL: Displays messages of situations that probably will abort the
application.
• ERROR: Displays error messages that are unwanted but not interrupt
the application.
• WARN: Displays messages from dangerous regions for the application,
or certain operations use not recommended.
• INFO: Displays information messages about the execution of the
application, or important events.
• DEBUG: Shows debug messages for the application. (Used in
development time)
• ALL: Show all posts
• OFF: Disables all messages.
Level Inheritance
The inherited level for a given logger L, is equal to
the first non-null level in the logger named hierarchy,
starting at L and proceeding upwards in the
hierarchy towards the root logger.
Logger Name
root
com.site.software
com.site.software.model
com.site.software.model.dao
com.site.software.model.dao.PersonDAOImpl
com.site.software.view
Assigned Inherited
Level
level
ERROR
WARN
INFO
null
null
null
ERROR
WARN
INFO
INFO
INFO
WARN
Level继承1
Logger name
Assigned level
Effective level
root
DEBUG
DEBUG
X
none
DEBUG
X.Y
none
DEBUG
X.Y.Z
none
DEBUG
Logger name
Assigned level
Effective level
root
ERROR
ERROR
X
INFO
INFO
X.Y
DEBUG
DEBUG
X.Y.Z
WARN
WARN
Level继承2
Logger name
Assigned level
Effective level
root
DEBUG
DEBUG
X
INFO
INFO
X.Y
none
INFO
X.Y.Z
ERROR
ERROR
Logger name
Assigned level
Effective level
root
DEBUG
DEBUG
X
INFO
INFO
X.Y
none
INFO
X.Y.Z
none
INFO
Logging Request
A log request of level p in a logger configured (either
assigned or inherited, whichever is appropriate) with
level q, is enabled if p >= q.
import org.apache.log4j.Logger;
public class PersonDAOImpl {
private final Logger LOG = Logger.getLogger(PersonDAOImpl.class);
public PersonDAOImpl() {
LOG.debug("You can't see me in the log because debug < INFO");
LOG.info("You will see me in the log because info = INFO");
LOG.warn("You will see me in the log because warn > INFO");
Appenders
A logger may be assigned to an appender: a named
output destination your log messages are forwarded
to.
# The root logger logs to the console
log4j.rootLogger=ERROR, con
# The com.site.software logger logs to a file
log4j.logger.com.site.software=INFO, FileApp
# The con appender will log in the console
log4j.appender.con=org.apache.log4j.ConsoleAppender
#The FileApp appender will log in a file
log4j.appender.FileApp=org.apache.log4j.FileAppender
Appenders
Appender Additivity
Each enabled logging request for a given logger L
will be forwarded to all the appenders in that logger
LA as well as all the appenders higher HA in the
logger named hierarchy
.
Logger Name
root
com.site.software
com.site.software.model
com.site.software.model.dao
com.site.software.view
LA
con
null
FileApp, c
d
e
HA
con
con
FileApp, c, con
con
Additivity Flag
Logger
Name
Attached
Appenders
Additivi
Output Targets
ty Flag
Comment
root
A1
not
applica A1
ble
Since the root logger stands at the
top of the logger hierarchy, the
additivity flag does not apply to it.
x
x.y
A-x1, A-x2 true
none
true
A1, A-x1, A-x2
A1, A-x1, A-x2
x.y.z
A-xyz1
A1, A-x1, A-x2, A-xyz1
Appenders of "x.y.z", "x" and of
root.
A-sec
No appender accumulation since
the additivity flag is set to false.
Only appender A-sec will be used.
A-sec
Only appenders of "security"
because the additivity flag in
"security" is set to false.
security A-sec
security.
none
access
true
false
true
Appenders of "x" and of root.
Appenders of "x" and of root.
Layout Conversion Pattern
Each appender has a layout component responsible
for formatting log messages accordingly to
conversion patterns.
log4j.appender.con=org.apache.log4j.ConsoleAppender
log4j.appender.con.layout=org.apache.log4j.PatternLayout
log4j.appender.con.layout.ConversionPattern=%d [%t] %-5p %m (%c:%L)%
Produced logs:
2010-05-14 19:29:11,996 [main] INFO You will see me in the log because
info = INFO (com.site.software.model.dao.PersonDAOImpl:10)
2010-05-14 19:29:11,997 [main] WARNYou will see me in the log because
warn > INFO (com.site.software.model.dao.PersonDAOImpl:11)
A lot of Appenders and Layouts
Appenders
● ConsoleAppender appends log events to System.out or System.err
● FileAppender appends log events to a file
● RollingFileAppender extends FileAppender to backup the log files when
they reach a certain size
● DailyRollingFileAppender extends FileAppender so that the underlying
is rolled over at a user chosen frequency
● SMTPAppender sends an e-mail when a specific logging event occurs
● JMSAppender publishes log events to a JMS Topic
● JDBCAppender provides for sending log events to a database
Layouts
● PatternLayout configurable string pattern in a printf C function style
● XMLLayout appends log events as a series of log4j:event (log4j.dtd)
● HTMLLayout outputs events in a HTML table
The API
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class Wombat {
private final Logger logger = LoggerFactory.getLogger(Wombat.class);
Integer t;
Integer oldT;
public void setTemperature(Integer temperature) {
oldT = t;
t = temperature;
logger.debug("Temperature set to {}. Old temperature was {}.", t, oldT);
if(temperature.intValue() > 50) {
logger.info("Temperature has risen above 50 degrees.");
}
}
}
SLF4J & Logback
logback的前世今生
•
•
slf4j由log4j作者Ceki开发,逐步取代apahce
commons logging。
logback由log4j作者Ceki开发,逐步取代
log4j。
logback相比较log4j的优势
•
slf4j支持参数化
–
–
•
logger.error(“帐号ID:{}不存在”, userId);
告别了if(logger.isDebugEnable()) 时代
另外logback的整体性能比log4j也较佳,
hibernate等项目已经采用了slf4j。
SLF4J and Logback : Dream Dates!
•
•
•
•
Logback implements SLF4J natively
No computational and memory overhead
Fully compliant to SLF4J
Faster they say! 10 times!! Smaller Blue
Print
• Core, classic and access modules
Why Logback
• Conditional Processing
– Good For Dev/Prod switch
Is It Worth A Use?
Why Logback
Stack Traces Pointing jar files
logback.xml
ConsoleAppender
RollingFileAppender
rollover daily or whenever the
file size reaches 100MB
Parameterized logging
inefficient syle
logger.debug("Hello "+name);
old style:
if(logger.isDebugEnabled()) {
logger.debug("Hello "+name);
}
new style:
logger.debug("Hello {}", name);
SiftingAppender or the appender-making
appender
• Sift logging according to runtime attributes
• E.g. separate logs according to user
sessions, so that the log file generated by
every user go into distinct log files, one log
file per user.
• Works with any appender, not just
FileAppender
SiftingAppender (continued)
<appender name="SIFT"
class="ch.qos.logback.classic.sift.SiftingAppender">
<discriminator>
<Key>userid</Key>
<DefaultValue>unknown</DefaultValue>
</discriminator>
<sift>
<appender name="FILE-${userid}"
class="ch.qos.logback.core.FileAppender">
<File>${userid}.log</File>s
<Append>false</Append>
<layout>
<Pattern>%d %level %mdc %logger - %msg%n</Pattern>
</layout>
</appender>
</sift>
</appender>
Mapped Diagnostic Context(MDC)
• 线程映射表
• 日志框架维护的 map,日志框架通过提供
了的键值对向其中插入日志信息。
映射诊断环境(Mapped Diagnostic Context)
Logback的设计目标之一是审查和调试复杂的分布式应用程序。真实世界的多
数分布式系统需要同时处理多个客户端。在一个典型的多线程方式实现的分
布式系统里,不同的线程处理不同的客户端。区分不同客户端的记录输出的
一个可行的但不好的方法是为每个客户端都创建新的、独立的logger。这种
技术使logger的数量增多且大大增加了管理开销。
一个轻量的技术是为客户端的每个记录请求添加唯一戳(uniquely stamp)
Logback在SLJ4J里使用了这种技术的一种变体:映射诊断环境(MDC)
为了给每个请求添加唯一戳,用户把环境(context)信息放进MDContext)
MDC
• MDC : Map Diagnostic Context
– Helps to uniquely stamp requests
– Similar to NDC : Nested Diagnostic Context
– Correlating the logs effectively
• The MDC manages contextual information
on a per thread basis(and its children)
@Override
public void processMsg(EmsMessage emsMessage) {
EopLogBean msg = (EopLogBean) emsMessage.getMsg();
MDC.put(“userid", getActionFromTxid(msg.getTrxid()));
log.info(msg.toString());
}
MDC Use Case: User Based Logging
public class UserServletFilter implements Filter {
private final String USER_KEY = "username";
public void doFilter(ServletRequest request, ServletResponse response,
FilterChain chain) throws IOException, ServletException {
HttpServletRequest req = (HttpServletRequest) request;
Principal principal = req.getUserPrincipal();
if (principal != null) {
String username = principal.getName();
MDC.put(USER_KEY, username);
}
try {
chain.doFilter(request, response);
} finally {
MDC.remove(USER_KEY);
}
}
}
MDC Use Case: User Based Logging
<appender name="CONSOLE“ class="ch.qos.logback.core.ConsoleAppender">
<layout class="ch.qos.logback.classic.PatternLayout">
<Pattern>%-4r [%thread] %-5level C:%X{username} - %msg%n</Pattern>
</layout>
</appender>
MDC Use Case: InsertingServletFilter
• %X{req.remoteHost}
• %X{req.requestURI}%n%d - %m%n
Package versions in stack traces
java.lang.NullPointerException
at com.xyz.Wombat(Wombat.java:57) ~[wombat-1.3.jar:1.3]
at com.xyz.Wombat(Wombat.java:76) ~[wombat-1.3.jar:1.3]
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native) ~[na:1.5.0_06]
at java.lang.reflect.Method.invoke(Method.java:585) ~[na:1.5.0_06]
at junit.runners.TestMethod.invoke(TestMethod.java:59) [junit-4.4.jar:na]
etc..
60
JAVA String
String
StringUtils
空白: defaultIfBlank defaultIfEmpty defaultString deleteWhitespace normalizeSpace
trim
判断: isAllLowerCase isAlpha isAlphanumeric isAlphanumericSpace isAlphaSpace
isAsciiPrintable isNumeric isNumericSpace isWhitespace
isBlank isEmpty isNotBlank isNotEmpty
合分: join split
结束: endsWith endsWithAny endsWithIgnoreCase
比较: difference equals equalsIgnoreCase getCommonPrefix getLevenshteinDistance
overlay
查找: indexOf indexOfAny indexOfAnyBut indexOfDifference indexOfIgnoreCase
lastIndexOf lastIndexOfAny lastIndexOfIgnoreCase lastOrdinalIndexOf ordinalIndexOf
删除: remove removeEnd removeEndIgnoreCase removeStart removeStartIgnoreCase
替换: replace replaceChars replaceEach replaceEachRepeatedly replaceOnce
反转: reverse reverseDelimited
子串: countMatches left mid right substring…
补充: leftPad repeat rightPad
大小写: capitalize lowerCase uncapitalize upperCase swapCase
缩略: abbreviate abbreviateMiddle
补充: center
裁剪: chomp chop strip…
包含:contains containsAny containsIgnoreCase containsNone containsOnly containsWhitespac
GuavaSplitter
JDK has splitter
‣ regular expression
‣ result as an array
‣ its way of handling empty pieces
Mini-puzzler
",a,,b,".split(",") returns...
(a) "","a","","b",""
(b) null,"a",null,"b",null
(c) "a",null,"b"
(d) "a","b"
(e) None of the above
(which is very strange)
Splitter
Breaks strings into substrings
by recognizing a separator (delimiter), one of:
a single character: Splitter.on('\n')
a literal string: Splitter.on(", ")
a regex: Splitter.onPattern(",\\s*")
any CharMatcher (remember that?)
or using a fixed substring length
Splitter.fixedLength(8)
Iterable<String> pieces =
Splitter.on(',').split("trivial,example")
returns "trivial" and "example" in order.
The default behavior is simplistic:
//yields [" foo", " ", "bar", " quux", ""]
Splitter.on(',').split(" foo, ,bar, quux,");
If you want extra features,
ask for them!
//yields ["foo", "bar", "quux"]
Splitter.on(',')
.trimResults()
.omitEmptyStrings()
.split(" foo, ,bar, quux,");
Guava Joiner
Bizarrely Missing From The JDK Class Libraries:
joining pieces of text with a separator.
String s = Joiner.on(", ").join(episodesOnDisc);
Joiner is configurable:
StringBuilder sb = ...;
Joiner.on("|").skipNulls().appendTo(sb, attrs);
It can even handle maps:
static final MapJoiner MAP_JOINER = Joiner.on("; ")
.useForNull("NODATA")
.withKeyValueSeparator(":");
String到基本数据类型的转换
• public static int parseInt(String s, int radix)
throws NumberFormatException
• public static int parseInt(String s)
• public static byte parseByte(String s)
• public static short parseShort(String s)
• public static long parseLong(String s)
• public static float parseFloat(String s)
• public static double parseDouble(String s)
对象的字符串表示方法
• Object类 public String toString()
• String类
–
–
–
–
–
public static String valueOf(char c)
public static String valueOf(int i)
public static String valueOf(long l)
public static String valueOf(float f)
public static String valueOf(double d)
BASE64
01
02
03
04
05
06
07
08
09
10
11
12
import static javax.xml.bind.DatatypeConverter.parseBase64Binary;
import static javax.xml.bind.DatatypeConverter.printBase64Binary;
@Test
public void testBase64() {
String s1 = "我是黄进兵!";
String base64 = printBase64Binary(s1.getBytes(UTF_8));
assertEquals("5oiR5piv6buE6L+b5YW1IQ==", base64);
byte[] bytes = parseBase64Binary(base64);
String s2 = new String(bytes, UTF_8);
assertEquals(s1, s2);
}
JAVA IO
Java Characters
• A Java character has two bytes
• Java supports Unicode character set standard
– ASCII
• Java uses UTF-16 encoding
• Other unicode encodings:
– UTF-8
– UTF-16
• Other non-unicode encodings
– Windows-1256
Stream Concept
Java I/O Classes
• Text I/O
– Stream of characters (Unicode format)
– Support provided by Reader and Writer
• Binary I/O
– Stream of bytes (raw format)
– Support provided by InputStream and OutputStream
– An InputStream reads raw octet (8 bit) data (byte).
Reader和InputStream区别
• Reader和InputStream分别是I/O库提供的两套平行独立的等级机构
• InputStream、OutputStream是用来处理8位元的流,Reader、Writer是
用来处理16位元的流。
• InputStream、OutputStream是用来处理8位元的流,Reader、Writer是
用来处理16位元的流。所以在处理中文的时候需要用Reader和Writer。
• InputStreamReader、OutputStreamWriter负责进行InputStream到
Reader的适配和由OutputStream到Writer的适配。
• int copy(InputStream input, OutputStream output)
• void copy(InputStream input, Writer output, String
encoding)
• void copy(Reader input, OutputStream output, String
encoding)
• int copy(Reader input, Writer output)
Reader <-> InputStream
Writer <->WriterOutputStream
•
•
•
•
•
•
Reader->InputStream commons-io :ReaderInputStream
Writer->OutputStream commons-io :WriterOutputStream
InputStream->Reader jdk:InputStreamReader
OutputStream->Writer jdk:OutputStreamWriter
InputStream->OutputStream?
Reader->Writer?
Closeable
•
•
•
•
Reader何时关闭?
Writer何时关闭?
InputStream 何时关闭?
OutputStream何时关闭?
FileUtils
Guava
common.io
Typically:
InputSupplier<InputStream>,
OutputSupplier<Writer>,etc.
2 key interfaces
public interface InputSupplier<T> {
T getInput() throws IOException;
}
public interface OutputSupplier<T> {
T getOutput() throws IOException;
}
This lets all Guava’s utilities be useful for many kinds of I/O.
Terminology
‣ byte stream means "InputStream or OutputStream"
ByteStreams utilities class
‣ char stream means "Reader orWriter."
CharStreams utilities class
common.io: ByteStreams
byte[] toByteArray(InputStream)
byte[] toByteArray(InputSupplier)
void readFully(InputStream, byte[])
void write(byte[], OutputSupplier)
long copy(InputStream, OutputStream)
long copy(InputSupplier, OutputSupplier)
long length(InputSupplier)
boolean equal(InputSupplier, InputSupplier)
InputSupplier slice(InputSupplier, long, long)
InputSupplier join(InputSupplier...)
CharStreams is similar, but deals in Reader, Writer, String and
CharSequence (often requiring you to specify a Charset).
common.io: Files
The Files class works one level higher than ByteStreams and
CharStreams, and has a few other tricks.
byte[] toByteArray(File)
String toString(File, Charset)
void write(byte[], File)
void write(CharSequence, File, Charset)
long copy(File, File)
long copy(InputSupplier, File)
long copy(File, OutputSupplier)
long copy(File, Charset, Appendable)
long move(File, File)
boolean equal(File, File)
List<String> readLines(File, Charset)
More about Files
File createTempDir()
void deleteDirectoryContents(File)
void deleteRecursively(File)
long getChecksum(File,Checksum)
byte[] getDigest(File,MessageDigest)
String readFirstLine(File,Charset)
List<String> readLines(File,Charset)
T readLines(File,Charset, LineProcessor<T>)
String toString(File,Charset)
Flushables and Closeablesb
Flushables.flushQuietly(Flushable flushable)
Flushables.flush(
Flushable flushable,
boolean swallowIOException) throws IOException
Closeables.closeQuietly(Closeable closeable)
Closeables.close(
Closeable closeable,
boolean swallowIOException) throws IOException
Very usefull in finally blocks
(avoid nesting try/catch)
Java Collections
Java array and collections
JAVA Collections
Java Collection Interfaces
4种基本形式,前三种的父接口是Collection。
1:List 关注对象的索引列表
2:Set 关注对象的唯一性
3:Queue 关注对象被处理时的顺序
4:Map 关注映射和键值的唯一性
Collection Utilities
List具体实现类
Map具体实现类
Set具体实现类
Queue具体实现类
Multiset
Multimap
ListMultimap & SetMultimap
Map<String, List<T>> & Map<String, Set<T>>
Operations: put(K, V), putAll(K, Iterable<V>),
remove(K, V), removeAll(K, Iterable<V>),
replaceValues(K, Iterable<V>)
Multimap Implementations
BiMap
BiMap<K, V> is Map<K,V> with unique values
Operations: all Map, inverse(), values() as Set
Throws an IllegalArgumentException if you
attempt to map a key to an already-present
value
BiMap Implementations
Table
Copy!
Lists.newArrayList()
Lists.newLinkedList()
Sets.newHashSet()
Sets.newLinkedHashSet()
Sets.newTreeSet()
or make it immutable..
ImmutableList.copyOf()
ImmutableSet.copyOf()
不同集合类型有不同的时间复杂度
Operation
Obtain size
Add element
Remove given element
Remove by index
Get element by index
Find out if contains
ArrayList
LinkedList
HashSet
TreeSet
Constant
Constant
Linear
Linear
Constant
Linear
Constant
Constant
Linear
Linear
Linear
Linear
Constant
Constant
Constant
–
–
Constant
Constant
Log
Log
–
–
Log
Depending on the size,
different types of collections
may behave better that
others
how to choose correct java collection class
(When to use which collection in java )
泛型练习
• 泛型改造MyStack
• 增加方法: pushAll
• 增加方法: popAll
@Test
public void testStack() {
MyStack<Number> numberStack = new MyStack<Number>();
Collection<Integer> integers = new ArrayList<Integer>();
integers.add(1);
numberStack.pushAll(integers);
Collection<Object> objects = new ArrayList<Object>();
numberStack.popAll(objects);
}
The Get and Put Principle
public static <T> void copy(List<? super T> dest, List<? extends T> src)
use an extends wildcard when you only get values out of a structure,
use a super wildcard when you only put values into a structure,
and don't use a wildcard when you both get and put.
A Mnemonic for Wildcard Usage
• PECS—Producer extends, Consumer super
– use Foo<? extends T> for a T producer
– use Foo<? super T> for a T consumer
• Only applies to input parameters
– Don’t use wildcard types as return types
Misc.
• Tuples
• The of-Operator
• ULong, UInt, UShort
Java Reflections
Metadata

Java stores metadata in classes
-
-

Metadata for a class:
Metadata for a constructor:
Metadata for a field:
Metadata for a method:
java.lang.Class
java.lang.reflect.Constructor
java.lang.reflect.Field
java.lang.reflect.Method
Two ways to access a Class object for a class:
Class c1 = Class.forName(“java.util.Properties”);
Object obj = ...;
Class c2 = obj.getClass();

Reflection classes are inter-dependent
-
Examples are shown on the next slide
Examples of inter-relatedness of
reflection classes
class Class {
Constructor[]
Field
Field[]
Method[]
...
getConstructors();
getDeclaredField(String name);
getDeclaredFields();
getDeclaredMethods();
}
class Field {
Class getType();
...
}
class Method {
Class[] getParameterTypes();
Class
getReturnType();
...
}
Metadata for primitive types and arrays
Java associates a Class instance with each primitive type:
Class c1 = int.class;
Class c2 = boolean.class;
Class c3 = void.class;
Might be returned by
Method.getReturnType()
Use Class.forName() to access the Class object for an array
Class
Class
Class
Class
c4
c5
c6
c7
=
=
=
=
byte.class;
// byte
Class.forName(“[B”); // byte[]
Class.forName(“[[B”); // byte[][]
Class.forName(“[Ljava.util.Properties”);
Encoding scheme used by Class.forName()
B  byte; C  char; D  double; F  float; I  int; J  long;
Lclass-name  class-name[]; S  short; Z  boolean
Use as many “[”s as there are dimensions in the array
Miscellaneous Class methods
Here are some useful methods defined in Class
class Class {
public String getName(); // fully-qualified name
public boolean isArray();
public boolean isInterface();
public boolean isPrimitive();
public Class getComponentType(); // only for arrays
...
}
Invoking a default constructor
Use Class.newInstance() to call the default constructor
Example:
abstract class Foo {
public static Foo create() throws Exception {
String className = System.getProperty(
“foo.implementation.class”,
“com.example.myproject.FooImpl”);
Class c = Class.forName(className);
return (Foo)c.newInstance();
}
abstract void op1(...);
abstract void op2(...);
}
...
Foo obj = Foo.create();
obj.op1(...);
A plug-in architecture
Use a properties file to store a mapping for
plugin name  class name
Many tools support plugins: Ant, Maven, Eclipse, …
abstract class Plugin {
abstract void op1(...);
abstract void op1(...);
}
abstract class PluginManager {
public static Plugin load(String name)
throws Exception {
String className = props.getProperty(name);
Class c = Class.forName(className);
return (Plugin)c.newInstance();
}
}
...
Plugin obj = PluginManager.load(“...”);
Invoking a non-default constructor
Slightly more complex than invoking the default constructor:
-Use Class.getConstructor(Class[] parameterTypes)
-Then call Constructor.newInstance(Object[] parameters)
abstract class PluginManager {
public static Plugin load(String name)
throws Exception {
String className = props.getProperty(name);
Class c = Class.forName(className);
Constructor cons = c.getConstructor(
new Class[]{String.class, String.class});
return (Plugin)cons.newInstance(
new Object[]{“x”, “y”});
}
}
...
Plugin obj = PluginManager.load(“...”);
Passing primitive types as parameters
If you want to pass a primitive type as a parameter:
Wrap the primitive value in an object wrapper
Then use the object wrapper as the parameter
Object wrappers for primitive types:
-
boolean
byte
char
int
...




java.lang.Boolean
java.lang.Byte
java.lang.Character
java.lang.Integer
Invoking a method
Broadly similar to invoking a non-default constructor:
Use Class.getMethod(String name,
Class[]parameterTypes)
Then call Method.invoke(Object target,
Object[] parameters)
Object obj = ...
Class c = obj.getClass();
Method m = c.getMethod(“doWork”,
new Class[]{String.class, String.class});
Object result= m.invoke(obj, new Object[]{“x”,“y”});
Looking up methods
The API for looking up methods is fragmented:
-
You can lookup a public method in a class or its ancestor classes
Or, lookup a public or non-public method declared in the specified class
A better name
would have been
getPublicMethod()
class Class {
public Method getMethod(String name,
Class[] parameterTypes);
public Method[] getMethods();
public Method getDeclaredMethod(String name,
Class[] parameterTypes);
public Method[] getDeclaredMethods();
...
}
Finding an inherited method
This code searches up a class hierarchy for a method
-Works for both public and non-public methods
Method findMethod(Class cls, String methodName,
Class[] paramTypes)
{
Method method = null;
while (cls != null) {
try {
method = cls.getDeclaredMethod(methodName,
paramTypes);
break;
} catch (NoSuchMethodException ex) {
cls = cls.getSuperclass();
}
}
return method;
}
Accessing a field
There are two ways to access a field:
-
By invoking get- and set-style methods (if the class defines them)
By using the code shown below
Object obj = ...
Class c = obj.getClass();
Field f = c.getField(“firstName”);
f.set(obj, “John”);
Object value = f.get(obj);
Looking up fields
The API for looking up fields is fragmented:
-
You can lookup a public field in a class or its ancestor classes
Or, lookup a public or non-public field declared in the specified class
A better name
would
wouldhave
havebeen
been
getPublicField()
getPublicField()
class Class {
public Field
public Field[]
public Field
public Field[]
...
}
getField(String name);
getFields();
getDeclaredField(String name);
getDeclaredFields();
Finding an inherited field
This code searches up a class hierarchy for a field
-
Works for both public and non-public fields
Field findField(Class cls, String fieldName)
{
Field field = null;
while (cls != null) {
try {
field = cls.getDeclaredField(fieldName);
break;
} catch (NoSuchFieldException ex) {
cls = cls.getSuperclass();
}
}
return field;
}
Java modifiers

Java defines 11 modifiers:
-

Some of the modifiers can be applied to a class, method or
field:
-

abstract, final, native, private, protected, public, static,
strictfp, synchronized, transient and volatile
Set of modifiers is represented as bit-fields in an integer
Access set of modifiers by calling int getModifiers()
Useful static methods on java.lang.reflect.Modifier:
static
static
static
static
...
boolean
boolean
boolean
boolean
isAbstract(int modifier);
isFinal(int modifier);
isNative(int modifier);
isPrivate(int modifier);
Accessing non-public fields and methods

Both Field and Method define the following methods
(inherited from java.lang.reflect.AccessibleObject):
boolean isAccessible();
void setAccessible(boolean flag);
static void setAccessible(AccessibleObject[] array,
boolean flag);

Better terminology might have been
“SuppressSecurityChecks” instead of “Accessible”

Example of use:
if (!Modifier.isPublic(field.getModifiers()) {
field.setAccessible(true);
Hibernate uses this technique
so it can serialize non-public
JOOR
A fluent reflection API for Java
jOOR stands for Java Object Oriented Reflection.
It is a simple wrapper for the java.lang.reflect package.
String world = on("java.lang.String") // Like Class.forName()
.create("Hello World") // Call the most specific matching constructor
.call("substring", 6) // Call the most specific matching substring() method
.call("toString")
// Call toString()
.get();
// Get the wrapped object, in this case a String
Performance
// Method reflection with ReflectASM:
SomeClass someObject = ...
MethodAccess access = MethodAccess.get(SomeClass.class);
access.invoke(someObject, "setName", "Awesome McLovin");
String name = (String)access.invoke(someObject, "getName");
Comparison with standard
java.lang.reflect
Employee[] employees =
on(department).call("getEmployees").get();
jOOR code:
for (Employee employee : employees) {
Street street =
on(employee).call("getAddress").call("getStreet").get();
System.out.println(street);
}
try {
Method m1 = department.getClass().getMethod("getEmployees");
Employee employees = (Employee[]) m1.invoke(department);
The same
example
with normal
reflection in
Java:
for (Employee employee : employees) {
Method m2 = employee.getClass().getMethod("getAddress");
Address address = (Address) m2.invoke(employee);
Method m3 = address.getClass().getMethod("getStreet");
Street street = (Street) m3.invoke(address);
System.out.println(street);
}
}
// There are many checked exceptions that you are likely to ignore anyway
catch (Exception ignore) {
// ... or maybe just wrap in your preferred runtime exception:
throw new RuntimeException(e);
}
JavaScript Object Notation
Eclipse json editor
{
hotelList:[
{name:"Beijing",address:"Haidian Road
{name:"Beijing",address:"Haidian Road
{name:"Beijing",address:"Haidian Road
{name:"Beijing",address:"Haidian Road
{name:"Beijing",address:"Haidian Road
{name:"Beijing",address:"Haidian Road
{name:"Beijing",address:"Haidian Road
],
timeStamp:"Wed Oct 08 10:25:10 CST 2008"
}
NO:1",price:110.0},
NO:2",price:120.0},
NO:3",price:130.0},
NO:4",price:140.0},
NO:5",price:150.0},
NO:6",price:160.0},
NO:7",price:170.0}
JSON Form View
What is JSON?
• Lightweight data-interchange format
> Compared to XML
• Simple format
> Easy for humans to read and write
> Easy for machines to parse and generate
• JSON is a text format
> Programming language independent
> Uses conventions that are familiar to programmers of the C-
family of languages, including C, C++, C#, Java, JavaScript,
Perl, Python
Why Use JSON over XML
• Lighter and faster than XML as on-the-wire data
format
• JSON objects are typed while XML data is typeless
> JSON types: string, number, array, boolean,
> XML data are all string
• Native data form for JavaScript code
> Data is readily accessible as JSON objects in your JavaScript
code vs. XML data needed to be parsed and assigned to
variables through tedious DOM APIs
> Retrieving values is as easy as reading from an object
property in your JavaScript code
JSON Tools for Java Developer
• Parser
> Parse JSON text files and convert these to a Java model
• Renderer
> Render a Java representation into text
• Serializer
> Serialize plain POJO clusters to a JSON representation
• Validator
> Validate the contents of a JSON file using a JSON schema
Alibaba FastJSON
基本序列化
Object o = ...;
String text = JSON.toJSONString(o);
反序列化
String text = ...; // {"r":255,"g":0,"b":0,"alpha":255}
Color color = JSON.parseObject(text, Color.class);
JSON Schema
{
"$schema" : "http://json-schema.org/draft-03/schema#",
"id" : "http://json-schema.org/draft-03/schema#",
"type" : "object",
"properties" : {
"type" : {
"type" : ["string", "array"],
"items" : {
"type" : ["string", {"$ref" : "#"}]
},
"uniqueItems" : true,
"default" : "any"
},
"properties" : {
"type" : "object",
"additionalProperties" : {"$ref" : "#"},
"default" : {}
},
XML tools
http://code.google.com/p/xmltool/
XMLTag tag = XMLDoc.newDocument(false)
.addDefaultNamespace("http://www.w3.org/2002/06/xhtml2/")
.addNamespace("wicket", "http://wicket.sourceforge.net/wicket-1.0")
.addRoot("html")
.addTag("wicket:border")
.gotoRoot().addTag("head")
.addNamespace("other", "http://other-ns.com")
.gotoRoot().addTag("other:foo");
System.out.println(tag.toString());
XML tools Features
• Create new XML documents from external sources or new
document from scrash
• Manage namespaces
• Manipulating nodes (add, remove, rename)
• Manipulating data (add, remove text or CDATA)
• Navigate into the document with shortcuts and XPath (note:
XPath supports namespaces)
• Tranform an XMlDoc instance to a String or a Document
• Validate your document against schemas
• Executin callbacks on a hierarchy
• Remove all namspaces (namespace ignoring)
• ... and a lot of other features !
jOOX-Java Object Oriented XML
// Find the order at index for and add an element "paid"
$(document).find("orders").children().eq(4).append("<paid>true</paid>");
// Find those orders that are paid and flag them as "settled"
$(document).find("orders").children().find("paid").after("<settled>true</s
ettled>");
// Add a complex element
$(document).find("orders").append(
$("order", $("date", "2011-08-14"),
$("amount", "155"),
$("paid", "false"),
$("settled", "false")).attr("id", "13");
JOOQ
SELECT * FROM BOOK
create.selectFrom(BOOK)
WHERE PUBLISHED_IN = 201
.where(PUBLISHED_IN.equal(2011))
1
.orderBy(TITLE)
ORDER BY TITLE
SELECT FIRST_NAME, LAST_NAME, COU
NT(*)
FROM AUTHOR
JOIN BOOK ON AUTHOR.ID = BOOK.AUTH
OR_ID
WHERE LANGUAGE = 'DE'
AND PUBLISHED > '2008-01-01'
GROUP BY FIRST_NAME, LAST_NAME
HAVING COUNT(*) > 5
ORDER BY LAST_NAME ASC NULLS FIRS
T
LIMIT 2 OFFSET 1
FOR UPDATE
OF FIRST_NAME, LAST_NAME
create.select(FIRST_NAME, LAST_NAME, count())
.from(AUTHOR)
.join(BOOK)
.on(Author.ID.equal(Book.AUTHOR_ID))
.where(LANGUAGE.equal("DE"))
.and(PUBLISHED.greaterThan(parseDate("2008-01-01")))
.groupBy(FIRST_NAME, LAST_NAME)
.having(count().greaterThan(5))
.orderBy(LAST_NAME.asc()
.nullsFirst())
.limit(2).offset(1)
.forUpdate()
.of(FIRST_NAME, LAST_NAME)
JOOQ + H2
01 import org.jooq.util.h2.H2Factory;
02 import cn.bingoo.h2.domain.Tables;
03 import cn.bingoo.h2.domain.tables.records.VouchercardRecord;
04
05 @Test
06 public void testJooq() throws Exception {
07 DriverManager.registerDriver(new org.h2.Driver());
08 Connection conn = DriverManager.getConnection("jdbc:h2:~/bingoo-handy", "sa", "");
09 Factory factory = new H2Factory(conn);
10
11 VouchercardRecord newRecord = factory.newRecord(Tables.VOUCHERCARD);
12 newRecord.setCode("mycode"); newRecord.setPass("mypass"); newRecord.setHmac("mymac");
13 newRecord.store();
14
15 VouchercardRecord fetchOne = factory.selectFrom(Tables.VOUCHERCARD)
16
.where(Tables.VOUCHERCARD.CODE.equal("mycode")).fetchOne();
17
18 assertEquals(newRecord, fetchOne);
19
20 conn.close();
21 }
Regular Expression正则表达式
• 文本处理的利器(grep, perl, ruby, lua内嵌)
• Perl,ruby,javascript 写法 /[a-z]+/
– Eg. name = “Dave”; name =~ /[a-z]/; 找到ave
• JDK1.4 java.util.regex
• 一些简单例子:
[a-z]+
abc
[abc]
[^abc]
匹配一个或多个小写字母
exactly this sequence of three letters
any one of the letters a, b, or c
any character except one of the letters a, b, or c
(immediately within an open bracket, ^ means “not,”
but anywhere else it just means the character ^)
[a-z]
[a-zA-Z0-9]
abc|xyz
[A-Za-z]+[0-9]
any one character from a through z, inclusive
any one letter or digit
match either abc or xyz
match one or more letters immediately followed by one digit
REGEX
Regular Expressions Anchors(锚定符)
^
Start of string, or start of line in
multi-line pattern
\A Start of string
$ End of string, or end of line in multiline pattern
\Z End of string
\b Word boundary
\B Not word boundary
\< Start of word
\> End of word
Quantifiers(限定符)
X*
0 or more
X+
1 or more
X?
0 or 1
X{3}
Exactly 3
X{3,}
3 or more
X{3,5}
3, 4 or 5
Add a ? to a quantifier to make it ungreedy.
Groups and Ranges(分组和范围)
.
Any character except new line (\n)
(a|b)
a or b
(...)
Group
(?:...)
Passive (non-capturing) group
[abc]
Range (a or b or c)
[^abc] Not a or b or c
[a-q]
Letter from a to q
[A-Q]
Upper case letter from A to Q
[0-7]
Digit from 0 to 7
\n
nth group/subpattern
Ranges are inclusive.
Character Classes(字符分类)
\c
\s
\S
\d
\D
\w
\W
\x
\O
Control character 控制字符
White space 空白字符
Not white space 非空白
Digit 数字
Not digit 非数字
Word 单词
Not word 非单词
Hexadecimal digit 16进制
Octal digit 8进制
限定符类型Types of quantifiers
• A greedy quantifier will match as much as it can, and back
off if it needs to
– We’ll do examples in a moment
• A reluctant quantifier will match as little as possible, then
take more if it needs to
– You make a quantifier reluctant by appending a ?:
X?? X*? X+? X{n}? X{n,}? X{n,m}?
• A possessive quantifier will match as much as it can, and
never let go
– You make a quantifier possessive by appending a +:
X?+ X*+ X++ X{n}+ X{n,}+ X{n,m}+
限定符示例
• Suppose your text is aardvark
– Using the pattern a*ardvark (a* is greedy):
• The a* will first match aa, but then ardvark won’t match
• The a* then “backs off” and matches only a single a,
allowing the rest of the pattern (ardvark) to succeed
– Using the pattern a*?ardvark (a*? is reluctant):
• The a*? will first match zero characters (the null string),
but then ardvark won’t match
• The a*? then extends and matches the first a, allowing
the rest of the pattern (ardvark) to succeed
– Using the pattern a*+ardvark (a*+ is possessive):
• The a*+ will match the aa, and will not back off, so
ardvark never matches and the pattern match fails
JAVA中的Regex
01 import java.util.regex.Matcher;
02 import java.util.regex.Pattern;
03
04 @Test
05 public void testRegex() {
06 Pattern p = Pattern.compile(“[a-z]+”);
07 String text = “Hello world”;
08 Matcher m = p.matcher(text);
09 assertTrue(m.find());
10 assertEquals("ello", text.substring(m.start(), m.end()));
11 assertTrue(m.find());
12 assertEquals("world", text.substring(m.start(), m.end()));
13 assertFalse(m.find());
14 }
分组Capturing groups
• In regex, parentheses are used for grouping, but they also
capture (keep for later use) anything matched by that part of the
pattern
– Example: ([a-zA-Z]*)([0-9]*) matches any number of letters followed by
any number of digits
– If the match succeeds, \1 holds the matched letters and \2 holds the
matched digits
– In addition, \0 holds everything matched by the entire pattern
• Capturing groups are numbered by counting their opening
parentheses from left to right:
– ((A)(B(C)))
12 3 4
\0 = \1 = ((A)(B(C))),
\2 = (A),
\3 = (B(C)),
\4 = (C)
• Example: ([a-zA-Z])\1 will match a double letter, such as letter
JAVA中的regex group和replace
01 @Test
02 public void testBasicGroup() {
03 Pattern p = Pattern.compile("((\\d+)\\s+(boys|girls))");
04
05 String text = "There are total 15 boys and 12 girls in class 1.";
06 Matcher m = p.matcher(text);
07 assertTrue(m.find());
08 assertEquals("15 boys", m.group(1));
09 assertEquals("15", m.group(2));
10 assertEquals("boys", m.group(3));
11 assertTrue(m.find());
12 assertEquals("12 girls", m.group(1));
13 assertEquals("12", m.group(2));
14 assertEquals("girls", m.group(3));
15 assertFalse(m.find());
16 }
17
18 @Test
19 public void testReplace() {
20 String text = "There are total 15 boys and 12 girls in class 1.";
21 String replacedText = text.replaceAll("(\\d+)\\s+boys", "$1 men");
22 assertEquals("There are total 15 men and 12 girls in class 1.", replacedText);
String类中的正则
–
–
–
–
–
public boolean matches(String regex)
public String replaceFirst(String regex, String replacement)
public String replaceAll(String regex, String replacement)
public String[ ] split(String regex)
public String[ ] split(String regex, int limit)
• If the limit n is greater than zero then the pattern will be applied at most n
- 1 times, the array's length will be no greater than n, and the array's last
entry will contain all input beyond the last matched delimiter.
• If n is non-positive then the pattern will be applied as many times as
possible
Matcher类中的方法
• If m is a matcher, then
– m.replaceFirst(replacement) returns a new String where the first
substring matched by the pattern has been replaced by replacement
– m.replaceAll(replacement) returns a new String where every
substring matched by the pattern has been replaced by replacement
– m.find(startIndex) looks for the next pattern match, starting at the
specified index
– m.reset() resets this matcher
– m.reset(newText) resets this matcher and gives it new text to examine
(which may be a String, StringBuffer, or CharBuffer)
REGEX cont.
Special Characters
\n
New line
\r
Carriage return
\t
Tab
\v
Vertical tab
\f
Form feed
\xxx Octal character xxx
\xhh Hex character hh
Pattern Modifiers
g
Global match
i
Case-insensitive
m
Multiple lines
s
Treat string as single line
x
Allow comments and white space in pattern
e
Evaluate replacement
U
Ungreedy pattern
Assertions
String Replacement(有的实现使用\替代$)
?=
Lookahead assertion
$n
nth non-passive group
?!
?<=
Negative lookahead
Lookbehind assertion
$2
"xyz" in /^(abc(xyz))$/
$1
$`
$'
"xyz" in /^(?:abc)(xyz)$/
Before matched string
After matched string
$+
$&
Last matched string
Entire matched string
?!= or ?<! Negative lookbehind
?>
?()
?()|
Once-only Subexpression
Condition [if then]
Condition [if then else]
?#
Comment
RegexBuddy
练习
1) 匹配字母,数字和减号
Letters, digits and hyphens
2) 匹配日期 yyyy-mm-dd
3) jpg, gif或png图片文件名
4) Email地址
5) Html tags
6) 至少包括一个大写字母、小写
字母和数字(密码强度)
Scalable language
Pragmatic
runs on the JVM
Martin Odersky
Since
Seamless Java
interoperability
Statically typed
2003
Production
Hybrid
ready
“I can honestly say if someone had shown me the Programming Scala book
by Martin Odersky, Lex Spoon & Bill Venners back in 2003 I'd probably have
never created Groovy.“
James Strachan, creator of Groovy
“If I were to pick a language to use
today other than Java, it would be
Scala.”
James Gosling
Who uses Scala already
一切值都是对象的实例
•
JVM中的原生类型是对象的实例
•
函数也是值,从而也是对象的实例
•
123.toByte
"1".toInt
true.toString
val compare = (x: Int, y: Int) => x > y
compare(1, 2) // result: Boolean = false
Java的static方法和域再没有存在的理由,因为它们的所有者
也必须是对象的实例(值),所以有了Scala中的单例object
object Dog {
val whatever = "dog" // static field in Java
}
class Dog {
def callWhatever = Dog.whatever
}
函数作为值
•
可以当作参数传递
•
不管它是实例的方法
•
•
val compare = (x: Int, y: Int) => x > y
list sortWith compare
class AComparator {
def compare(x: Int, y: Int) = x > y
}
list sortWith (new AComparator).compare
还是匿名子句
object annonymous extends scala.Function2[Int, Int, Boolean] {
override def apply(x: Int, y: Int) = x > y
}
list sortWith annonymous
没有了sta&c域,一切函数,包括object的方法调用现在都是
值(实例)的方法
一切操作都是函数调用(1)
•
只有一个参数或零个参数的方法在调用时可以省略”.”和”()”
•
参数也可以是一系列操作 {...}
•
•
1.+(1)
1 + 1
1.>(0)
1 > 0
(1 > 0).&(2 > 1)
(1 > 0) & 2 > 1
stack.push(10)
stack push 10
stack.pop
stack pop
stack push {
val a = 1
val b = 2
a +b
}
更多的符号需要用作方法名
def !@#%^&*\-<=>?|~:/ = println("noop")
def √(x: Double) = Math.sqrt(x)
val Π = Math.Pi
val r = √(9*Π)
‘<’, ‘>’更适合作方法名,所以用’[’和‘]’来表示类型参数
一切操作都是函数调用(2)
•
for语句是函数调用
for (i <- List(1, 2)) {
println(i)
}
List(1, 2) foreach {i => println(i)}
for (i <- List(1, 2)) yield {
i + 10
}
List(1, 2) map {i => i + 10}
•
更多的例子
•
额外的好处:自左向右顺序书写语句
// synchronized is function call instead of keyword
def check = synchronized {
// isInstanceOf is function call instead of keyword
100.isInstanceOf[String]
}
stack.pop.asInstanceOf[Int] // (Integer) stack.pop() in Java
一切操作都返回值
•
默认返回最后一条语句的值,也可以用return显式返回
val r1 = { // return 3
val a = 1
val b = 2
a + b
}
val r2 = if (true) 1 else 2
val r3 = // return (): Unit
for (i <- List(1, 2)) {
println(i)
}
val r4 = // return List(11, 12)
for (i <- List(1, 2)) yield {
i + 10
}
val r5 =
try {
val f
f
} catch
case
}
// return java.io.File
= new File("afile")
{
ex: IOException => null
Higher Level
// Java – Check if string has uppercase character
boolean hasUpperCase = false;
for(int i = 0; i < name.length(); i++) {
if(Character.isUpperCase(name.charAt(i))) {
hasUpperCase = true;
break;
}
}
// Scala
val hasUpperCase = name.exists(_.isUpperCase)
Declaring classes
…concisely
// Scala
class Person(
var name: String,
var age: Int
)
// Java
public class Person {
private String name;
private int age;
public Person(String name, int age) {
this.name = name;
this.age = age;
}
public String getName() {
return name;
}
public int getAge() {
return age;
}
public void setName(String name) {
this.name = name;
}
public void setAge(int age) {
this.age = age;
}
}
Scala – Pattern
Matching
Java – working
with Person
Object x = new Person("Bill Clinton", 64);
var x: Any = Person("Lukasz", 28);
if(x instanceof Person) {
x match {
Person p = (Person)x;
case Person(name, age) =>
System.out.println(„Person name: "+p.getName());
println("Person name: "+name);
} else {
case _ => println("Not a person")
System.out.println("Not a person");
}
}
x = "Lukasz Kuczera"
x = "Lukasz Kuczera";
x match {
if(x instanceof Person) {
case Person(name, age) =>
Person p = (Person)x;
println("Person name: "+name)
System.out.println("hello "+p.getName());
case "Bill Clinton" => println("hello Bill")
} else if(x instanceof String) {
case s: String => println("hello "+s)
String s = (String)x;
if(s.equals("Bill Clinton"))
case _ => "err, ???"
}
System.out.println("Hello Bill");
else System.out.println("hello: "+s);
} else System.out.println("err, ???");
Person name: Lukasz
hello Lukasz Kuczera
Pattern matching
…is concise
// Scala
reactions += {
case m: MouseEntered =>
println(“I see it!”)
case m: MouseExited =>
println(“Lost it.”)
case m: MouseClicked =>
println(“Poked!”)
}
// Java
button.addMouseListener(new MouseAdapter() {
public void mousePressed(MouseEvent e) {}
public void mouseReleased(MouseEvent e) {}
public void mouseEntered(MouseEvent e) {}
public void mouseEntered(MouseEvent e) {
System.out.println(“I see it!”);
}
public void mouseExited(MouseEvent e) {
System.out.println(“Lost it.”);
}
public void mouseClicked(MouseEvent e) {
System.out.println(“Poked!”);
}
}
// ...alternative - isinstanceof
Working with arrays
// Java
public class Partition {
Person[] all;
Person[] adults;
Person[] minors;
{
ArrayList<Person> minorsList = new ArrayList<Person>();
ArrayList<Person> adultsList = new ArrayList<Person>();
for(int i=0; i<all.length; i++ ) {
(all[i].age<18 ? adultsList: minorsList).add(all[i]);
}
minors = (Person[]) minorsList.toArray();
adults = (Person[]) adultsList.toArray();
}
}
// Scala
val all: Array[Person]
val (minors, adults) = all.partition(_.age<18)
Duck Typing
class Duck {
def quack = "呱...呱..."
}
def doQuack(d: {def quack: String}) {
println(d.quack)
}
doQuack(new Duck)
Nice to know
Scala:
Java:
Console.println(“Hello”)
println(“Hello”)
System.out.println(“Hello”);
val line = Console.readLine()
val line = readLine()
BufferedReader r = new BufferedReader(new
InputStreamRead(System.in)
String line = r.readLine();
error(“Bad”)
throw new RuntimeException(“Bad”)
1+1
1 .+(1)
new Integer(1).toInt() + new Integer(1).toInt();
1 == new Object
1 eq new Object
new Integer(1).equals(new Object());
new Integer(1) == new Object();
"""A\sregex""".r
java.util.regex.Pattern.compile(“A\\sregex”);
“A little learning is a dangerous thing;
drink deep, or taste not the Pierian spring:
there shallow draughts intoxicate the brain,
and drinking largely sobers us again.”
--Alexander Pope
学识浅薄是件危险的事情;
要么酣饮,不然就尝不到知识源泉的甘霖。
在那里浅斟薄饮使头脑醉昏,
大量畅饮会使我们清醒。
--亚历山大·蒲柏
Download