•内容提示:Alt + / •快速修复:Ctrl + 1 •导包:Ctrl + shift + O •格式化代码块:ctrl + shift + F •向前向后:Alt + 方向键 •添加注释 Ctrl+Shift+/ •除去注释 Ctrl+Shift+\
public class Demo4 { @Before public void before() { System.out.println("before"); } @Test public void testRun() { Person p = new Person(); p.run(); } @Test public void testEat() { Person p = new Person(); p.eat(); } @After public void after() { System.out.println("after"); } }
运行结果:
before
eating.
after
before
runing.
after
2、@BeforeClass、@Test、@AfterClass基本使用
public class Demo5 { @BeforeClass public void beforeClass() { System.out.println("beforeclass"); } @Test public void testRun() { Person p = new Person(); p.run(); } @Test public void testEat() { Person p = new Person(); p.eat(); } @AfterClass public void afterClass() { System.out.println("afterclass"); } }
运行结果:
before
eating.
runing.
after
1、静态导入,(了解即可,一般没人这么用)
import static java.lang.System.out; import static java.util.Arrays.sort; public class Demo1 { public static void main(String[] args) { out.print("main"); int[] a = new int[] { 6, 5, 3 }; sort(a); for (int i : a) out.print(i); } }
2、自动装箱/拆箱
public class Demo2 { public static void main(String[] args) { Integer i = 1;// 装箱 int j = i;// 拆箱 // 典型应用,list里只能装对象 List<Integer> list = new ArrayList<Integer>(); list.add(1);// 1被自动包装为Integer int k = list.get(0);// 自动拆箱 Iterator<Integer> it = list.iterator(); while (it.hasNext()) { int m = it.next();// 拆箱 } } }
3、增强for循环
Map for增强实例:
package cn.itcast.demo; import java.util.*; import java.util.Map.Entry; import org.junit.Test; public class Demo3 { @Test public void test3(){ Map map=new HashMap(); map.put("1", "aaa"); map.put("2", "bbb"); map.put("3", "ccc"); //传统方式1 Set set=map.keySet(); Iterator it=set.iterator(); while(it.hasNext()){ String key=(String)it.next(); String value=(String) map.get(key); System.out.println("key="+key+",value="+value); } //传统方式2 Set set2=map.entrySet(); Iterator it2=set2.iterator(); while(it2.hasNext()){ Map.Entry entry=(Entry)it2.next(); System.out.println("key="+entry.getKey()+",value="+entry.getValue()); } //增强for循环的1种方式,实际转为的set视图只存了key for(Object obj:map.keySet()){ String key2=(String)obj; String value2=(String)map.get(key2); System.out.println("key2="+key2+",value2="+value2); } //增强for循环的2种方式 for(Object obj:map.entrySet()){ Map.Entry entry3=(Entry) obj; String key3=(String) entry3.getKey(); String value3=(String) entry3.getValue(); System.out.println("key3="+key3+",value3="+value3); } //增强for循环需要注意的问题:只适合取数据,不适合更改 int arr[]={1,2,3}; for(int i: arr){ i=10; } System.out.println(arr[0]); // 1 List li=new ArrayList(); li.add("1"); for(Object obj : li){ obj="888"; } System.out.println(li.get(0));// 1 } }
4、可变参数
语法:
public void foo(int … args){}//三个点
public class Demo4 { @Test public void testSum(){ sum(1,2,3,4); int arr[]={5,6,7}; sum(arr); } public void sum(int ...nums){ int sum=0; for(int i:nums){ sum+=i; } System.out.println(sum); } //可变参数注意的问题 //public void aa(int ...nums,int s)//不可以,编译器晕逼了 //public void bb(int s ,int ...nums)//可以 @Test public void asListTest(){//api: public static <T> List<T> asList(T... a) List list=Arrays.asList("1","2","3"); System.out.println(list);//[1, 2, 3] String arr[]={"1","2","3","4"}; list=Arrays.asList(arr); System.out.println(list);//[1, 2, 3, 4] arr是对象数组 int nums[]={1,2,3,4,5}; list=Arrays.asList(nums); System.out.println(list);//[[I@120d62b],nums是一个对象 Integer nums2[]={1,2,3,4,5}; list=Arrays.asList(nums2); System.out.println(list);//[1, 2, 3, 4, 5] } }
5、枚举类
定义枚举的狗找函数、方法、字段:
/* * jdk5之前,只能这么定义 * class Grade{ * private Grade(){ } * public static final Grade A=new Grade(); * public static final Grade B=new Grade(); * public static final Grade C=new Grade(); * public static final Grade D=new Grade(); * public static final Grade E=new Grade(); * } */ enum Grade { A("100-90"), B("89-80"), C("79-70"), D("69-60"), E("59-0"); private String value; private Grade(String value){ this.value=value; } public String getValue(){ return this.value; } } public class Demo1 { @Test public void test() { print(Grade.B); } public void print(Grade g){ // A B C D E String value=g.getValue(); System.out.println(value); } }
带抽象方法的枚举:
enum Grade {// class A 100-90优 B 89-80良 C 79-70 一般D 69-60差 E 59-0不及格 //必须实现抽象方法 A("100-90"){ public String localeValue(){ return "优"; } }, B("89-80"){ public String localeValue(){ return "良"; } }, C("79-70"){ public String localeValue(){ return "一般"; } }; private String value; private Grade(String value){ this.value=value; } public String getValue(){ return this.value; } public abstract String localeValue(); } public class Demo1 { @Test public void test() { print(Grade.B); //89-80,良 } public void print(Grade g){ // A B C D E String value=g.getValue(); String value2=g.localeValue(); System.out.println(value+","+value2); } }
注意:
Java中声明的枚举类,均是java.lang.Enum类的孩子,它继承了Enum类的所有方法.常用方法:
•name() //返回此枚举常量的名称,有毛用
•ordinal() //返回枚举常量的序数
•values() 此方法虽然在JDK文档中查找不到,但每个枚举类都具有该方法,它遍历枚举类的所有枚举值非常方便.
6、反射
1、java反射机制是在运行状态中,对于任意一个类,都能知道这个类的所有属性和方法.简而言之,动态获取类中信息就是反射.
2、java反射应用在很多java软件和框架中,例Tomcat,提供了处理请求和应答的方式,因为具体的处理动作不同,所以对外提供了接口,由开发者来实现具体的请求和应答处理.这个接口就是 servlet,开发者只要实现servlet接口,并配置相应的配置文件,对Tomcat来说就是在web.xml中配置servletname也就是类名,这样tomcat就能通过所谓的反射来加载该类的class文件,并获取类中的所有信息,从而实现开发者自定义的请求和应答处理方式.
3、类用来描述对象共性的信息,用来描述字节码文件的共性的类是Class类,该类提供获取字节码文件中的内容,包括类名称,属性和函数.反射依靠该类来完成.
4、获取字节码文件对象的三种方式:
1.Object类的getClass()方法,必须实例化类
2.任何数据类型都具备一个class静态属性(Objcet类的属性)来获取对于的Class对象.
3.通过给定的类的字符串名称就可以获取该类Class对象,更易扩展,该方法是forName(). 一般使用这种
例:String name="cn.itcast.Person"; Class c = Class.forName(name);
5、反射构造函数
import java.lang.reflect.Constructor; class Person{ String name; int age; public Person(){ System.out.println("wu can"); } public Person(String name,int age){ System.out.println("you can"); } } public class TestPerson { public static void main(String[] args) throws Exception{ Person p = new Person(); //根据字符串的名称查找该类的字节码文件,加载进内存,创建该字节码文件对象,创建对应的Person对象. String name="com.czbk.faceObjcet.Person"; Class clazz = Class.forName(name); //只能调用无参构造函数 Person p1 =(Person)clazz.newInstance(); //调用有参构造函数,getDeclaredConstructor可获取私有构造函数 Constructor c = clazz.getConstructor(String.class,int.class); Object o=c.newInstance("ww",26); } }
6、反射字段
public class TestPerson { public static void main(String[] args) throws Exception{ String str="com.czbk.faceObjcet.Person"; Class clazz = Class.forName(str); Object o = clazz.newInstance(); Field f = clazz.getField("name"); //只能获取公有属性,可获取父类 Object obj = f.get(o); Field f1 = clazz.getDeclaredField("age");//可获取私有属性,只限本类 f1.setAccessible(true); //对私有字段的访问取消权限检查,暴力访问 System.out.println(f1.get(o)); f1.setInt(o,22); System.out.println(o); } }
7、反射方法
public class TestPerson { public static void main(String[] args) throws Exception{ String str="com.czbk.faceObjcet.Person"; Class clazz = Class.forName(str); Object o = clazz.newInstance(); //调用无参方法 Method method=clazz.getMethod("toString", null); method.invoke(o, null); //调用有参方法 Method method1=clazz.getMethod("toString1", String.class); method1.invoke(o, "sss"); } }
8、主板运行实例(接口+配置)
public interface PCI { void run(); void close(); } public class SoundCard implements PCI{ public void run() { System.out.println("SoundCard Run"); } public void close() { System.out.println("SoundCard Close"); } } public class NetCard implements PCI{ public void run() { System.out.println("NetCard run"); } public void close(){ System.out.println("NettCard clase"); } } public class MainBoard { /*public void run(PCI p){ p.run(); } public void clase(PCI p){ p.close(); }*/ public static void main(String[] args) throws Exception { //这种方式每次增加新硬件时都需要修改主板源代码 /*SoundCard sc = new SoundCard(); MainBoard mb = new MainBoard(); mb.run(sc); mb.clase(sc);*/ //增加硬件无需修改MainBoard源代码,只要在配置文件中添加 Properties pt = new Properties(); FileInputStream is = new FileInputStream(new File("PCI.properties")); pt.load(is); for(int x=0;x<pt.size();x++){ String PCIName=pt.getProperty("pci"+x); Class clazz = Class.forName(PCIName); PCI p=(PCI)clazz.newInstance(); Method method = clazz.getMethod("run", null); method.invoke(p, null); } } }
7、内省(Introspector)
public class Demo1 { //得到bean所有属性 @Test public void test1() throws IntrospectionException{ BeanInfo info=Introspector.getBeanInfo(Person.class); //去掉Object里的属性(也就是class属性) BeanInfo info2=Introspector.getBeanInfo(Person.class,Object.class); PropertyDescriptor[] pds=info.getPropertyDescriptors(); for(PropertyDescriptor pd:pds){ System.out.println(pd.getName()); //ab age class name password } } //操纵bean的指定属性:age @Test public void test2() throws Exception{ Person p=new Person(); PropertyDescriptor pd=new PropertyDescriptor("age", Person.class); //得到属性的写方法,为属性赋值 Method method=pd.getWriteMethod(); method.invoke(p, 45); System.out.println(p.getAge());//45 //获取属性的值 method=pd.getReadMethod(); System.out.println(method.invoke(p, null));//45 } //高级内容,获取当前操作的属性的类型 @Test public void test3() throws Exception{ Person p=new Person(); PropertyDescriptor pd=new PropertyDescriptor("age", Person.class); //得到属性的写方法,为属性赋值 Method method=pd.getWriteMethod(); System.out.println(pd.getPropertyType());//int method.invoke(p, 45); System.out.println(p.getAge());//45 //获取属性的值 method=pd.getReadMethod(); System.out.println(method.invoke(p, null));//45 } }
2、内省—beanutils工具包
//使用beanUtils操纵bean的属性 ( 第三方) public class Demo1 { @Test public void test1() throws Exception{ Person p=new Person(); BeanUtils.setProperty(p, "age", 456); System.out.println(p.getAge());//456 } @Test public void test2() throws Exception{ String name="aaaa"; String age="123"; String password="pw"; Person p=new Person(); //支持8种基本类型自动转换 BeanUtils.setProperty(p, "name", name); BeanUtils.setProperty(p, "age", age); BeanUtils.setProperty(p, "password", password); System.out.println(p.getName());//aaaa System.out.println(p.getAge());//123 System.out.println(p.getPassword());//pw } @Test public void test3() throws Exception{ String birthday="1983-12-1"; //为了让日期赋值到bean的birthday属性上,给beanUtils注册一个日期转换器 //ConvertUtils.register(converter, clazz); ConvertUtils.register(new Converter(){ public Object convert(Class type, Object value) { if(value==null) return null; if(!(value instanceof String)){ throw new ConversionException("只支持String类型的转换"); } String str=(String)value; if(str.trim().equals("")) return null; SimpleDateFormat df=new SimpleDateFormat("yyyy-MM-dd",Locale.US); try { return df.parse(str); } catch (ParseException e) { throw new RuntimeException(e); } } }, Date.class); Person p=new Person(); BeanUtils.setProperty(p, "birthday", birthday); System.out.println(p.getBirthday());//pw System.out.println("___"+BeanUtils.getProperty(p, "birthday")); } public void test5() throws Exception { Map map=new HashMap(); map.put("name", "aaa"); map.put("password", "123"); map.put("brithday", "1980-09-09"); ConvertUtils.register(new DateLocaleConverter(), Date.class); Person p=new Person(); //用map集合填充bean属性,map关键字和bean属性要一致 BeanUtils.populate(p, map); } }
8、泛型(Generic)
1、JDK5以前,对象保存到集合中就会失去其特性,取出时通常要程序员手工进行类型的强制转换,这样不可避免就会引发程序的一些安全性问题,例:
ArrayList list = new ArrayList(); list.add("abc"); Integer num = (Integer) list.get(0); //运行时会出错,但编码时发现不了
ArrayList<String> list = new ArrayList<Object>(); 错,左右必须完全一致 ArrayList<Object> list = new ArrayList<String>(); 错 ArrayList<String> list = new ArrayList (); 对,可以一边没有 ArrayList list = new ArrayList<String>(); 对
3、自定义泛形——泛型方法
public static <T> void doxx(T t);
public class Demo1 { // 编写一个泛形方法,接收一个任意数组,并颠倒数组中的所有元素. public <T> void reverse(T arr[]) { int startindex = 0; int endindex = arr.length - 1; while (true) { if (startindex >= endindex) break; T temp = arr[startindex]; arr[startindex] = arr[endindex]; arr[endindex] = temp; startindex++; endindex--; } } }
public static <K,V> V getValue(K key) { return map.get(key);}
public class GenericDao<T> { private T field1; public void save(T obj) {} public T getId(int id) {} }
//单例 public class ServiceFactory { private Properties serviceConfig = new Properties(); //单例的构造函数也只执行一次 private ServiceFactory(){ InputStream in = DaoFactory.class.getClassLoader().getResourceAsStream("service.properties"); try { serviceConfig.load(in); } catch (IOException e) { throw new RuntimeException(e); } } private static ServiceFactory instance = new ServiceFactory(); public static ServiceFactory getInstance(){ return instance; } public <T> T createService(Class<T> clazz){ //clazz.getName()拿到的带包名 String name = clazz.getSimpleName(); String className = serviceConfig.getProperty(name); try { T service = (T) Class.forName(className).newInstance(); return service; } catch (Exception e) { throw new RuntimeException(e); } } }
6、泛型的高级应用——通配符 略
9、Annotation(注解)
•@Override: 限定重写父类方法, 该注解只能用于方法
•@Deprecated: 用于表示某个程序元素(类, 方法等)已过时
•@SuppressWarnings: 抑制编译器警告.
@Target(value={ElementType.METHOD,ElementType.FIELD}) @Retention(RetentionPolicy.RUNTIME) public @interface MyAnnotation1 { String name() default "zxx"; String password() default "123"; int age() default 12; Gender gender() default Gender.男;//枚举 MyAnnotation2 my2() default @MyAnnotation2(name="llll"); Class clazz() default String.class; String[] ss() default {"aa","bbb"}; int[] i() default {1,2}; }
6、提取 Annotation 信息
public class CategoryDao { private ComboPooledDataSource combods; @Injectpublic void setCombods(ComboPooledDataSource combods) { this.combods = combods; } }
@Retention(RetentionPolicy.RUNTIME) public @interface Inject { String driverClass() default "com.mysql.jdbc.Driver"; String jdbcUrl() default "jdbc:mysql://localhost:3306/bookstore"; String user() default "root"; String password() default "root"; }
7、注解在servlet 3.0中的使用案例,替代了在web.xml中的配置:
@WebFilter( urlPatterns = { "/ServletDemo1" }, initParams = { @WebInitParam(name = "charset", value = "UTF-8", description = "编码") }) public class FilterDemo1 implements Filter { FilterConfig fConfig=null; public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) { String charset = fConfig.getInitParameter("charset"); HttpServletRequest req = (HttpServletRequest)request; req.setCharacterEncoding(charset); chain.doFilter(request, response); } public void init(FilterConfig fConfig) { this.fConfig = fConfig; } public void destroy() { System.out.println("FilterDemo1 destroy!"); } }
10、动态代理
代理对象存在的价值:主要用于拦截对真实业务对象的访问
1、jdbc数据库连接池中使用动态代理拦截close方法,将连接放入连接池而不是关闭:
public synchronized Connection getConnection() throws SQLException { if(list.size()<=0){ throw new RuntimeException("数据库忙,请稍会再来!!"); } Connection conn = list.removeFirst(); //list.get()不行 return new MyConnectionHandler(conn,this).getWarpConn(); } class MyConnectionHandler implements InvocationHandler { private Connection realConnection; private Connection warpedConnection; private MyDataSource dataSource; private int maxUseCount = 5; private int currentUserCount = 0; MyConnectionHandler(Connection conn,MyDataSource dataSource) { this.realConnection=conn; this.dataSource = dataSource; } Connection getWarpConn() { warpedConnection = (Connection) Proxy.newProxyInstance(this .getClass().getClassLoader(), new Class[] { Connection.class },this); return warpedConnection; } //proxy:把代理对象自身传递进来 method:代表当前调用的方法 args:调用方法的参数 public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { if ("close".equals(method.getName())) { currentUserCount++; if (currentUserCount < maxUseCount) dataSource.connectionsPool.addLast(warpedConnection); else { realConnection.close(); dataSource.currentCount--; } } return method.invoke(realConnection, args); } }
2、动态代理改写之前的解决全站乱码拦截器 *经典
public class CharacterEncodingFilter implements Filter { public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) throws IOException, ServletException { final HttpServletRequest request = (HttpServletRequest) req; HttpServletResponse response = (HttpServletResponse) resp; request.setCharacterEncoding("UTF-8"); // 解决post乱码 chain.doFilter((ServletRequest) Proxy.newProxyInstance( CharacterEncodingFilter.class.getClassLoader(), request.getClass().getInterfaces(), new InvocationHandler() { public Object invoke(Object proxy, Method method, Object[] args) { if (!method.getName().equals("getParameter")) { return method.invoke(request, args); } if (!request.getMethod().equalsIgnoreCase("get")) { return method.invoke(request, args); } String value = (String) method.invoke(request, args); if (value == null) { return null; } return new String(value.getBytes("iso8859-1"), "UTF-8"); } }), response); } public void destroy() { } public void init(FilterConfig filterConfig) throws ServletException { } }
3、动态代理改写之前的压缩输出拦截器
public class GzipFilter implements Filter { public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) throws IOException, ServletException { final HttpServletRequest request = (HttpServletRequest) req; final HttpServletResponse response = (HttpServletResponse) resp; ResponseProxy proxy = new ResponseProxy(response); chain.doFilter(request, proxy.createProxy()); byte[] out = proxy.getBuffer(); // 得到目标资源的输出 System.out.println(new String(out, "UTF-8")); } class ResponseProxy { private ByteArrayOutputStream bout = new ByteArrayOutputStream(); private PrintWriter pw = null; public byte[] getBuffer() { if (pw != null) { pw.close(); } return bout.toByteArray(); } private HttpServletResponse response; public ResponseProxy(HttpServletResponse response) { this.response = response; } public HttpServletResponse createProxy() { return (HttpServletResponse) Proxy.newProxyInstance(GzipFilter.class.getClassLoader(), response.getClass().getInterfaces(), new InvocationHandler() { public Object invoke(Object proxy, Method method, Object[] args){ if (!method.getName().equals("getWriter")&& !method.getName().equals("getOutputStream")) { method.invoke(response, args); } if (method.getName().equals("getWriter")) {//PrintWriter.write("中国"); pw = new PrintWriter(new OutputStreamWriter(bout, "UTF-8")); return pw; } if (method.getName().equals("getOutputStream")) { return new ServletOutputStream() { @Override public void write(int b) throws IOException { bout.write(b); } }; } return null; } }); } } public void destroy() { } public void init(FilterConfig filterConfig) throws ServletException { } }
4、动态代理+注解,实现权限管理
//service方法中,权限可精确到具体的方法 @Permission("添加分类") public void addCategory(Category c){ cdao.add(c); } @Permission("查看分类") public Category findCategory(String id){ return cdao.find(id); } public class ServiceFactory { private ServiceFactory(){} private static ServiceFactory instance = new ServiceFactory(); public static ServiceFactory getInstance(){ return instance; } public BusinessService createService(final User user){ final BusinessService service = new BusinessServiceImpl(); return (BusinessService) Proxy.newProxyInstance(ServiceFactory.class.getClassLoader(), service.getClass().getInterfaces(), new InvocationHandler(){ public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { //得到web层调用的方法 String methodName = method.getName(); //addCategory //反射出真实对象上相应的方法,检查真实对象方法上有没有权限注解 Method realMethod = service.getClass().getMethod(methodName, method.getParameterTypes()); Permission permission = realMethod.getAnnotation(Permission.class); if(permission==null){ return method.invoke(service, args); } //真实对象相应的方法上有权限注解,则得到访问该方法需要的权限 Privilege p = new Privilege(permission.value());//得到方法需要的权限 //检查用户是否有权限 //AppContext ThreadLocal //得到用户所有权限 if(user==null){ throw new SecurityException("您没有登陆"); } List<Privilege> list = service.getUserAllPrivilege(user); if(list.contains(p)){ return method.invoke(service, args); } throw new SecurityException("你没有权限"); } }); } } public class CategoryServlet extends HttpServlet { public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { String method = request.getParameter("method"); if("add".equals(method)){ add(request,response); } if("getAll".equals(method)){ getAll(request,response); } } private void getAll(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { BusinessService service = ServiceFactory.getInstance(). createService((User)request.getSession().getAttribute("user")); try{ List list = service.getAllCategory(); request.setAttribute("categories", list); request.getRequestDispatcher("/manager/listcategory.jsp").forward(request, response); }catch (Exception e) { if(e.getCause() instanceof SecurityException){ request.setAttribute("message", e.getCause().getMessage()); } } } private void add(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { BusinessService service = ServiceFactory.getInstance(). createService((User)request.getSession().getAttribute("user")); try { Category c = WebUtils.request2Bean(request, Category.class); c.setId(UUID.randomUUID().toString()); service.addCategory(c); request.setAttribute("message", "添加成功"); } catch (Exception e) { if(e.getCause() instanceof SecurityException){ request.setAttribute("message", e.getCause().getMessage()); }else{ e.printStackTrace(); request.setAttribute("message", "添加失败"); } } request.getRequestDispatcher("/message.jsp").forward(request, response); } public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { doGet(request, response); } }