class="p0">内部类(定义在一个类的内部的类,称为内部类;包装内部类的类,称为外部类,或包装类)
内部类编译成class文件的名称为:?<外部类名称>$<内部类名称>.class
内部类的好处:可以访问外部类的任意成员变量和成员方法。
何时使用内部类:该类不允许或不需要其他类进行访问时。
?
?
Java反射机制(Reflection)
?
java.lang.ClassLoader
java.lang.Class<T>
?
java.lang.Class类是类的类,用来描述类本身的信息(包含哪些属性,哪些方法等);
?
得到Class对象的方法如下(以java.lang.String类为例):
String?s?=?new?String("abc");
//方法一,使用getClass()方法得到类对象
Class?c1?=?s.getClass();
//方法二,使用类名.class得到类对象
Class??c2?=?String.class;
//方法三,通过Class类的forName(String?s)方法得到类对象
Class?c3?=?Class.forName("java.lang.String");
?
以上三种方法的区别:
Class?A?{
//当类在加载时会自动调用static静态块的代码
static?{
System.out.println("A");
}
}
?
//延时加载(不会打印静态块的代码);加载类时,不是立即加载,只有当new出这个类的对象时才会加载
Class?c1?=?A.class;
c1.newInstance();
?
//即时加载(会马上打印静态块的代码)
Class?c2?=?Class.forName("A");
?
对于基础类和包装类
Class?c1?=?Integer.class;
System.out.println(c1.getName());?//java.lang.Integer
?
Class?c2?=?int.class;
System.out.println(c2.getName());?//int
?
//在jdk1.5版本之后
Class?c3?=?Integer.TYPE;
System.out.println(c3.getName());?//int
?
?
?
类的加载机制(java.lang.ClassLoader)
1、并非一次性加载,在需要的时候加载(动态加载机制);
2、static语句块在加载后执行一次;
3、dynamic语句块在每次new新的对象时都会执行(等同于构造方法,用的较少);
程序运行对话框里,Arguments?-->?VM?arguments?添加?-verbose:class?可以观察类的具体加载过程,如下图:
?
?
?
测试代码如下:
public?class?ClassLoader?{
public?static?void?main(String[]?args)?{
new?A();
System.out.println("*********************");
new?B();
?
new?C();
new?C();
?
new?D();
new?D();
}
}
?
class?A?{?}
?
class?B?{?}
?
class?C?{
C(){?System.out.println("CCC111");?}
?
static?{?System.out.println("CCCCCCCCCCCCCCCCCCCCCC");?}
}
?
class?D?{
D(){?System.out.println("DDDD111");?}
?
/**
?*?动态语句块无条件的加在了每一个构造方法的前面,
?*?可以定义一个方法替换动态语句块;
?*?因此动态语句块不常使用.
?*/
{?System.out.println("DDDDDDDDDDDDDDDDDDDDDD");?}
}
==========================
打印结果如下:
[Loaded?com.reflect.ClassLoader?from?file:/D:/Workspaces4MyEclipse8.6/Test/bin/]
[Loaded?com.reflect.A?from?file:/D:/Workspaces4MyEclipse8.6/Test/bin/]
*********************
[Loaded?com.reflect.B?from?file:/D:/Workspaces4MyEclipse8.6/Test/bin/]
[Loaded?com.reflect.C?from?file:/D:/Workspaces4MyEclipse8.6/Test/bin/]
CCCCCCCCCCCCCCCCCCCCCC
CCC111
CCC111
[Loaded?com.reflect.D?from?file:/D:/Workspaces4MyEclipse8.6/Test/bin/]
DDDDDDDDDDDDDDDDDDDDDD
DDDD111
DDDDDDDDDDDDDDDDDDDDDD
DDDD111
?
?
Class?Loader的分类,?JDK中内置的?Class?Loader
bootstrap?class?loader:
implemented?by?native?language;
load?the?core?classes?of?jdk;
extesion?class?loader:
loader?the?class?from?jre/lib/ext;
application?class?loader:
load?user-define?classes;
ClassLoader.getSystemClassLoader();
other?class?loader:
...
?
测试代码如下:
public?class?TestClassLoader?{
public?static?void?main(String[]?args)?{
System.out.println(String.class.getClassLoader());
System.out.println(com.sun.crypto.provider.AESCipher.class
.getClassLoader().getClass().getName());
System.out.println(TestClassLoader.class.getClassLoader().getClass().getName());
System.out.println(ClassLoader.getSystemClassLoader().getClass().getName());
}
}
====================
结果如下:
null
sun.misc.Launcher$ExtClassLoader
sun.misc.Launcher$AppClassLoader
sun.misc.Launcher$AppClassLoader
?
?
JDK?Class?Loader的层次关系
?
?
class?loader?在加载class的时候,首先找上一层class?loader是否已经加载过class了,如果class已经加载过了,就不会再次加载class。
?
这种设计的好处:
安全性好!自己写的String.class代码永远不会执行(破坏性的代码)。
?
?
反射机制讲解(java.lang.reflect包)?
Struts、Spring等框架都是使用反射机制进行配置的。
?
java.lang.reflect.Field[属性]
java.lang.reflect.Method[方法]
java.lang.reflect.Constructor[构造方法]
?
查看API,了解各个类中的各种方法。
?
练习代码如下:
package?com.reflect;
import?java.lang.reflect.Method;
?
public?class?TestReflect?{
public?static?void?main(String[]?args)?throws?Exception?{
?
//此处字符串模拟从配置文件中读取?key,value(为具体的类名)
String?str?=?"com.reflect.Student";
?
//加载Class
Class?clazz?=?Class.forName(str);
//创建对象
Object?obj?=?clazz.newInstance();
//得到对象的方法
Method?[]?ms?=?clazz.getMethods();
for?(Method?m?:?ms)?{
System.out.println(m.getName());
if("getName".equals(m.getName())){
m.invoke(obj);
}
}
}
}
?
class?Student?{
public?int?id;
public?String?name;
?
static?{
System.out.println("class?Student?is?loaded....");
}
?
public?Student()?{
System.out.println("constructor?is?invoked");
}
?
public?String?getName()?{
System.out.println("getName?method?is?invoked....");
return?this.name;
}
?
public?void?setId(int?id)?{
this.id?=?id;
System.out.println("id="?+?this.id);
System.out.println("setId?method?is?invoked....");
}
}
?
?
?
Java正则表达式(Regular?Expression):字符串处理利器
java.lang.String(里面有很多和正则表达式相关的方法)
java.util.regex.Matcher
java.util.regex.Pattern
?
用途:
字符串匹配(字符匹配);
字符串查找;
字符串替换;
Demo:
检验IP地址是否正确;
检查email地址是否合法;
从网页中抓取email地址、页面链接等;
自动发垃圾邮件;
?
查看API文档中?java.util.regex.Pattern类,里面有正则表达式完整的介绍,学习文档
学习代码如下:
package?com;
import?java.util.regex.Matcher;
import?java.util.regex.Pattern;
?
public?class?TestRegexExprission?{
public?static?void?p(Object?obj)?{
System.out.println(obj);
}
?
public?static?void?main(String[]?args)?{
/**
?*?初步认识正则表达式
?*/
p("abc".matches("..."));?//true
p("a123a".replaceAll("\\d",?"-"));?//a---a
System.out.println("---------------------------------");
?
/**
?*?初步认识?Pattern、Matcher
?*/
//编译正则表达式
Pattern?ptn?=?Pattern.compile("[a-z]{3}");
//进行匹配操作,将结果保存在Matcher中
Matcher?matcher?=?ptn.matcher("fgh");
p(matcher.matches());?//true
System.out.println("---------------------------------");
?
/**
?*?初步认识?.?*?+??
?*?.??任意一个字符
?*?X*?X出现0次或多次
?*?X+?X出现1次或多次
?*?X??X出现0次或1次
?*/
p("a".matches("."));?//true
p("aaaa".matches("a*"));?//true
p("aaa".matches("a+"));?//true
p("".matches("a*"));?//true
p("".matches("a?"));?//true
p("aaa".matches("a?"));?//false
p("a".matches("a?"));?//true
System.out.println("---------------------------------");
?
/**
?*?X{n,m}?X出现的次数为?大于等于n次,小于等于m次
?*?X{n,}?X出现的次数为?大于等于n次
?*/
p("79527".matches("\\d{3}"));?//false
p("79527".matches("\\d{3,10}"));?//true
p("79527".matches("\\d{3,}"));?//true
p("192.168.0.aaa".matches("\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}"));?//false
System.out.println("---------------------------------");
?
/**
?*?[]?范围,其中之一;?^排除;?-范围;?|或者;?&&并且
?*/
p("a".matches("[abc]"));?//true
p("a".matches("[^abc]"));?//false
p("A".matches("[a-zA-Z]"));?//true
p("A".matches("[a-z]|[A-Z]"));?//true
p("A".matches("[a-z[A-Z]]"));?//true
p("R".matches("[A-Z&&[RFG]]"));?//true
p("192".matches("[0-2][0-9][0-9]"));?//true
System.out.println("---------------------------------");
?
/**
?*?认识?\d?\D?\s?\S?\w?\W?\
?*?\d:[0-9];?\D:[^0-9];
?*?\s:空白字符;?\S:[^\s],非空白字符;
?*?\w:单词字符,[a-zA-Z_0-9];?\W:非单词字符,[^\w];
?*/
p("?\n\r\t".matches("\\s{4}"));?//true
p("?".matches("\\S"));?//false
p("a_8".matches("\\w{3}"));?//true
p("abc888&^%".matches("[a-z]{1,3}\\d+[&^#%]+"));?//true
//p("\\".matches("\\"));?//此语句报错
p("\\".matches("\\\\"));?//true
System.out.println("---------------------------------");
?
/**
?*?POSIX?Style?另外一种正则表达式表示方法;
?*?不推荐使用,能看懂即可(用到时查看API文档)
?*/
p("a".matches("\\p{Lower}"));?//true
System.out.println("---------------------------------");
?
/**
?*?boundary?边界匹配(开头、结尾)
?*?^:字符的起始位置
?*?$:字符的结尾位置
?*/
p("hello?sir".matches("^h.*"));?//true
p("hello?sir".matches(".*ir$"));?//true
p("hello?sir".matches("^h[a-z]{1,3}o\\b.*"));?//true
p("hellosir".matches("^h[a-z]{1,3}o\\b.*"));?//false
//whilte?lines(空白行)
p("?\n".matches("^[\\s&&[^\\n]]*\\n$"));?//true
System.out.println("---------------------------------");
?
/**
?*?匹配email地址
?*/
p("asdfas-df.safsf@dsdfsdf.com".matches("[\\w[.-]]+@[\\w[.-]]+\\.[\\w]+"));?//true
System.out.println("---------------------------------");
?
/**
?*?matches:匹配整个字符串
?*?reset:重置
?*?find:查找匹配子串
?*?lookingAt:每次都从起始位置开始查找匹配
?*?start:匹配子串的起始位置
?*?end:匹配子串的结束位置
?*/
Pattern?p1?=?Pattern.compile("\\d{3,5}");
String?s1?=?"123-34345-234-00";
Matcher?m1?=?p1.matcher(s1);
?
p(m1.matches());
m1.reset();?//重置
?
p(m1.find());
p(m1.find());
p(m1.find());
p(m1.find());
?
p(m1.lookingAt());
p(m1.lookingAt());
p(m1.lookingAt());
p(m1.lookingAt());
?
p(m1.find());
p(m1.start()?+?"-"?+?m1.end());
p(m1.find());
p(m1.start()?+?"-"?+?m1.end());
p(m1.find());
//p(m1.start()?+?"-"?+?m1.end());?//此语句报错,只有明确找到子串,才能打印起始位置和结束位置
System.out.println("---------------------------------");
?
/**
?*?Replacement(字符串替换)
?*/
Pattern?p2?=?Pattern.compile("java",?Pattern.CASE_INSENSITIVE);
Matcher?m2?=?p2.matcher("java?Java?JAVa?JaVa?IloveJAVA?you?hateJava?afasdfasdf");
StringBuffer?buf?=?new?StringBuffer();
int?i=0;
while(m2.find())?{
i++;
if(i%2?==?0)?{
m2.appendReplacement(buf,?"java");
}?else?{
m2.appendReplacement(buf,?"JAVA");
}
}
m2.appendTail(buf);
p(buf);
System.out.println("---------------------------------");
?
/**
?*?group?"()"构成分组,有几对小括号,就是分几组(组号从1开始,数左括号,第几个左括号便是第几组)
?*/
Pattern?p3?=?Pattern.compile("\\d{3,5}[a-z]{2}");
String?s3?=?"123aa-34345bb-234cc-00";
Matcher?m3?=?p3.matcher(s3);
while(m3.find())?{
p(m3.group());
}
?
Pattern?p4?=?Pattern.compile("(\\d{3,5})([a-z]{2})");
String?s4?=?"123aa-34345bb-234cc-00";
Matcher?m4?=?p4.matcher(s4);
while(m4.find())?{
p(m4.group(1)?+?"--"?+?m4.group(2));
}
System.out.println("----------以上为基础知识,须掌握!-----------------------");
?
System.out.println("----------以下知识,用时再看-----------------------");
/**
?*?qualifiers?限定词
?*/
Pattern?p5?=?Pattern.compile(".{3,10}+[0-9]");
String?s5?=?"aaaa5bbbb68";
Matcher?m5?=?p5.matcher(s5);
if(m5.find())?{
p(m5.start()?+?"-"?+?m5.end());
}?else?{
p("not?match!");
}?
System.out.println("---------------------------------");
?
/**
?*?non-capturing?groups?非捕获组
?*/
Pattern?p6?=?Pattern.compile(".{3}(?=a)");
String?s6?=?"444a66b";
Matcher?m6?=?p6.matcher(s6);
while(m6.find())?{
p(m6.group());
}
System.out.println("---------------------------------");
?
//back?refenrences
/*
Pattern?p?=?Pattern.compile("(\\d(\\d))\\2");
String?s?=?"122";
Matcher?m?=?p.matcher(s);
p(m.matches());
*/
System.out.println("---------------------------------");
?
//flags的简写
//Pattern?p?=?Pattern.compile("java",?Pattern.CASE_INSENSITIVE);
//p("Java".matches("(?i)(java)"));
System.out.println("---------------------------------");
}
}
?
?
代码统计工具Demo:
package?com;
?
import?java.io.BufferedReader;
import?java.io.File;
import?java.io.FileNotFoundException;
import?java.io.FileReader;
import?java.io.IOException;
?
public?class?CodeCount?{
static?long?normalLines?=?0;?//正常行
static?long?commentLines?=?0;?//注释行
static?long?whiteLines?=?0;?//空白行
?
public?static?void?main(String[]?args)?{
//需要统计的文件夹
File?f?=?new?File("D:\\share\\JavaProjects\\TankWar1.9.11\\src");
?
File[]?codeFiles?=?f.listFiles();
for?(File?child?:?codeFiles)?{
if?(child.getName().matches(".*\\.java$"))?{
parse(child);
}
}
?
System.out.println("normalLines:"?+?normalLines);
System.out.println("commentLines:"?+?commentLines);
System.out.println("whiteLines:"?+?whiteLines);
}
?
//解析文件,统计数据
private?static?void?parse(File?file)?{
BufferedReader?br?=?null;
boolean?comment?=?false;?//多行注释标识
try?{
br?=?new?BufferedReader(new?FileReader(file));
String?line?=?"";
while?((line?=?br.readLine())?!=?null)?{
line?=?line.trim();
if?(line.matches("^[\\s&&[^\\n]]*$"))?{
whiteLines++;
}?else?if?(line.startsWith("/*")?&&?!line.endsWith("*/"))?{
commentLines++;
comment?=?true;
}?else?if?(line.startsWith("/*")?&&?line.endsWith("*/"))?{
commentLines++;
}?else?if?(true?==?comment)?{
commentLines++;
if?(line.endsWith("*/"))?{
comment?=?false;
}
}?else?if?(line.startsWith("//"))?{
commentLines++;
}?else?{
normalLines++;
}
}
}?catch?(FileNotFoundException?e)?{
e.printStackTrace();
}?catch?(IOException?e)?{
e.printStackTrace();
}?finally?{
if?(br?!=?null)?{
try?{
br.close();
br?=?null;
}?catch?(IOException?e)?{
e.printStackTrace();
}
}
}
}
}
?
?
日期处理
java.util.Date
|--java.sql.Date(仅包含日期部分)
|--java.sql.Time(仅包含时间部分)
|--java.sql.Timestamp(时间戳,包含日期和时间)
?
java.text.Format
|--java.text.DateFormat
????|--java.text.SimpleDateFormat
|--java.text.NumberFormat
?
java.text.DateFormat?类专门用于对日期的格式化,但是此类是抽象类,需要用其子类SimpleDateFormat类对日期进行格式化操作。
?
java.util.Calendar?日历类,对日期的各个部分进行存取改等操作;getInstance()得到实例,setTime(Date?date)?方法设置时间;
?
?
?