├── .gitignore ├── HotAgent ├── readme.txt └── src │ ├── Bean1.java │ ├── MANIFEST.MF │ ├── META-INF │ └── MANIFEST.MF │ ├── Test.java │ ├── com │ └── wp │ │ ├── ClassTransform.java │ │ ├── HotAgent.java │ │ └── ReloadTask.java │ └── hotAgent.jar ├── README.md ├── jdbc ├── pom.xml └── src │ └── main │ └── java │ └── com │ └── wp │ └── jdbc │ ├── App.java │ └── ResultSet中的方法.java ├── lib ├── commons-beanutils-1.9.3.jar ├── commons-logging-1.2.jar ├── guava-23.0.jar └── tools.jar ├── servlet ├── pom.xml └── src │ └── main │ ├── java │ └── com │ │ └── wp │ │ └── servlet │ │ ├── demo1 │ │ └── AServlet.java │ │ ├── demo2 │ │ └── BServlet.java │ │ ├── demo3 │ │ └── CServlet.java │ │ ├── demo4 │ │ └── DServlet.java │ │ ├── demo5 │ │ └── EServlet.java │ │ ├── demo6 │ │ └── FServlet.java │ │ ├── demo7 │ │ └── GServlet.java │ │ └── filter │ │ └── LogFilter.java │ ├── resources │ └── 1.jpg │ └── webapp │ ├── WEB-INF │ ├── 1.jpg │ └── web.xml │ └── index.jsp ├── socket └── src │ └── wp │ ├── Main.java │ ├── aio │ ├── Client.java │ ├── Server.java │ └── ServerCompletionHandler.java │ ├── bio │ ├── Client.java │ ├── Server.java │ └── ServerHandler.java │ ├── bio2 │ ├── Client.java │ ├── HandlerExecutorPool.java │ ├── Server.java │ └── ServerHandler.java │ ├── nio │ ├── Client.java │ ├── Server.java │ └── test │ │ └── TestBuffer.java │ └── udp │ ├── UDPReceiver.java │ └── UDPSender.java ├── springIOC简单实现 ├── pom.xml └── src │ └── main │ ├── java │ └── com.wp │ │ ├── dao │ │ ├── UserDao.java │ │ └── impl │ │ │ └── UserDaoImpl.java │ │ ├── ioc │ │ ├── BeanFactory.java │ │ ├── ClassPathXmlApplicationContext.java │ │ ├── Demo.java │ │ └── beans.xml │ │ └── service │ │ ├── UserService.java │ │ └── impl │ │ └── UserServiceImpl.java │ └── resources │ └── beans.xml ├── src └── com │ └── wp │ ├── ArrayList与HashSet比较及Hashcode分析 │ ├── Demo.java │ ├── HashTest.java │ ├── Reflect.java │ ├── Slave.java │ └── config.properties │ ├── IntegerWrapper.java │ ├── nio │ └── channel │ │ ├── ServerSocketChannelDemo.java │ │ └── SocketChannelDemo.java │ ├── string │ └── TestString.java │ ├── 内省操作javabean │ ├── Person.java │ ├── TestBean.java │ ├── TestBeanUtils.java │ └── TestIntrospector.java │ ├── 可变参数 │ └── VariableParameter.java │ ├── 回调 │ ├── callback │ │ ├── CSCallBack.java │ │ ├── CallBackTest.java │ │ ├── Client.java │ │ └── Server.java │ └── callback2 │ │ ├── GuavaFuture.java │ │ ├── JavaFuture.java │ │ └── JavaPromise.java │ ├── 枚举 │ ├── EnumTest.java │ ├── WeekDate.java │ └── WeekDateEnum.java │ ├── 泛型 │ └── 泛型擦除 │ │ ├── 反射观察泛型擦除.java │ │ └── 比较字节码.java │ ├── 类加载器 │ ├── FileSystemClassLoader.java │ ├── Main.java │ └── PrintClassLoader.java │ ├── 编码 │ └── Encoding.java │ ├── 自动装箱和拆箱 │ └── Box.java │ └── 静态导入 │ └── StaticImport.java ├── 动态代理 ├── pom.xml └── src │ ├── main │ └── java │ │ ├── aop │ │ ├── chain │ │ │ ├── CglibProxyChain.java │ │ │ └── DefaultProxyChain.java │ │ ├── creator │ │ │ ├── CglibCreator.java │ │ │ ├── JdkCreator.java │ │ │ └── ProxyCreator.java │ │ ├── factory │ │ │ ├── AbstractProxyFactory.java │ │ │ ├── CglibProxyFactory.java │ │ │ └── JdkProxyFactory.java │ │ └── interceptor │ │ │ ├── AbstractProxyInterceptor.java │ │ │ └── ProxyInterceptor.java │ │ └── proxy │ │ ├── InvocationImpl.java │ │ ├── Main.java │ │ ├── ProxyInvocationImpl.java │ │ ├── Student.java │ │ └── Study.java │ └── test │ └── java │ └── aop │ ├── Dao.java │ ├── TestAop.java │ ├── TimeMonitorProxy.java │ └── UserDao.java ├── 反射 ├── src │ └── reflect │ │ ├── 之前的代码 │ │ ├── application │ │ │ ├── ReplaceChar.java │ │ │ └── RunOtherZMain.java │ │ ├── reflect │ │ │ └── Main.java │ │ ├── reflectArray │ │ │ ├── Demo.java │ │ │ └── Demo2.java │ │ └── 反射的扩展性 │ │ │ ├── Dundi.java │ │ │ ├── Fly.java │ │ │ ├── MainTest.java │ │ │ ├── Person.java │ │ │ ├── Special.java │ │ │ └── special.properties │ │ ├── 了解反射 │ │ ├── HiddenImplementation.java │ │ ├── interfacea │ │ │ └── A.java │ │ └── packageaccess │ │ │ └── HiddenC.java │ │ ├── 泛型擦除 │ │ ├── Cat.java │ │ ├── Dog.java │ │ ├── EgyptianMau.java │ │ ├── Individual.java │ │ ├── LiteralPetCreator.java │ │ ├── Mutt.java │ │ ├── Pet.java │ │ ├── PetCreator.java │ │ └── TypeCounter.java │ │ └── 结合注解 │ │ ├── PasswordUtils.java │ │ ├── UseCaseTracker.java │ │ └── UserCase.java └── 反射总结.txt ├── 多线程 └── src │ ├── concurrent │ └── atomic │ │ ├── LongAccumulatorDemo.java │ │ └── LongAdderDemo.java │ └── thread │ └── MyThread3.java ├── 数据结构 └── src │ └── queue │ └── threadSafe │ └── TwoLockLinkQueue.java └── 缓存 ├── cache.markdown └── src └── cache ├── lru ├── LRUCacheWithHashMap.java └── LRUCacheWithLinkedHashMap.java └── simple ├── Cache.java ├── CacheManager.java └── SimpleCache.java /.gitignore: -------------------------------------------------------------------------------- 1 | .idea/ 2 | *.iml 3 | 4 | *.class 5 | 6 | out/ -------------------------------------------------------------------------------- /HotAgent/readme.txt: -------------------------------------------------------------------------------- 1 | 1.将ClassTransform,HotAgent,ReloadTask三个类进行编译 2 | 2.使用jar cvfm hotAgent.jar manifest.mf * 将上述得到的三个class文件按照MANIFEST.MF打成jar包。 3 | 3.使用命令java –javaagent:hotAgent.jar Test运行测试类。 4 | 4.修改Bean1类,编译此类将class替换以前的class文件。 5 | 5.可以看见动态编译的效果。 6 | 7 | 8 | 9 | 参考博文:https://my.oschina.net/xianggao/blog/364068 10 | 11 | 12 | 原理是通过代理修改内存中的字节码。 -------------------------------------------------------------------------------- /HotAgent/src/Bean1.java: -------------------------------------------------------------------------------- 1 | public class Bean1 { 2 | public void test1(){ 3 | 4 | System.out.println("wanwanpp"); 5 | } 6 | } -------------------------------------------------------------------------------- /HotAgent/src/MANIFEST.MF: -------------------------------------------------------------------------------- 1 | Can-Redefine-Classes: true 2 | Premain-Class: com.wp.HotAgent 3 | -------------------------------------------------------------------------------- /HotAgent/src/META-INF/MANIFEST.MF: -------------------------------------------------------------------------------- 1 | Can-Redefine-Classes: true 2 | Premain-Class: com.wp.HotAgent 3 | -------------------------------------------------------------------------------- /HotAgent/src/Test.java: -------------------------------------------------------------------------------- 1 | public class Test { 2 | public static void main(String[] args)throws InterruptedException { 3 | Bean1 c1=new Bean1(); 4 | while(true){ 5 | c1.test1(); 6 | 7 | Thread.sleep(5000); 8 | } 9 | } 10 | } -------------------------------------------------------------------------------- /HotAgent/src/com/wp/ClassTransform.java: -------------------------------------------------------------------------------- 1 | package com.wp; 2 | 3 | import java.lang.instrument.ClassFileTransformer; 4 | import java.lang.instrument.IllegalClassFormatException; 5 | import java.lang.instrument.Instrumentation; 6 | import java.security.ProtectionDomain; 7 | 8 | public class ClassTransform implements ClassFileTransformer { 9 | 10 | private Instrumentation inst; 11 | 12 | protected ClassTransform(Instrumentation inst) { 13 | this.inst = inst; 14 | } 15 | public byte[] transform(ClassLoader loader, String className, 16 | Class classBeingRedefined, ProtectionDomain protectionDomain, 17 | byte[] classfileBuffer) throws IllegalClassFormatException { 18 | byte[] transformed = null; 19 | HotAgent.clsnames.add(className); 20 | return null; 21 | } 22 | } -------------------------------------------------------------------------------- /HotAgent/src/com/wp/HotAgent.java: -------------------------------------------------------------------------------- 1 | package com.wp; 2 | 3 | import java.lang.instrument.ClassFileTransformer; 4 | import java.lang.instrument.Instrumentation; 5 | import java.util.Set; 6 | import java.util.Timer; 7 | import java.util.TreeSet; 8 | 9 | public class HotAgent { 10 | 11 | protected static Set clsnames = new TreeSet(); 12 | 13 | public static void premain(String agentArgs, Instrumentation inst) throws Exception { 14 | ClassFileTransformer transformer = new ClassTransform(inst); 15 | inst.addTransformer(transformer); 16 | System.out.println("是否支持类的重定义:" + inst.isRedefineClassesSupported()); 17 | Timer timer = new Timer(); 18 | timer.schedule(new ReloadTask(inst), 2000, 2000); 19 | } 20 | } -------------------------------------------------------------------------------- /HotAgent/src/com/wp/ReloadTask.java: -------------------------------------------------------------------------------- 1 | package com.wp; 2 | 3 | import java.io.InputStream; 4 | import java.lang.instrument.ClassDefinition; 5 | import java.lang.instrument.Instrumentation; 6 | import java.util.TimerTask; 7 | 8 | public class ReloadTask extends TimerTask { 9 | 10 | private Instrumentation inst; 11 | 12 | protected ReloadTask(Instrumentation inst) { 13 | this.inst = inst; 14 | } 15 | 16 | @Override 17 | public void run() { 18 | try { 19 | ClassDefinition[] cd = new ClassDefinition[1]; 20 | Class[] classes = inst.getAllLoadedClasses(); //获取加载过的所有Class对象。 21 | for (Class cls : classes) { 22 | if (cls.getClassLoader() == null || !cls.getClassLoader().getClass().getName().equals("sun.misc.Launcher$AppClassLoader")) 23 | continue; 24 | String name = cls.getName().replaceAll("\\.", "/"); 25 | //第一个参数为需要替换的对象的Class对象,第二个参数为新加载的class文件。 26 | cd[0] = new ClassDefinition(cls, loadClassBytes(cls, name + ".class")); 27 | inst.redefineClasses(cd); //执行替换JVM中class对象的操作,具体操作是一个netive方法。 28 | } 29 | 30 | } catch (Exception ex) { 31 | ex.printStackTrace(); 32 | } 33 | } 34 | 35 | private byte[] loadClassBytes(Class cls, String clsname) throws Exception { 36 | System.out.println(clsname + ":" + cls); 37 | InputStream is = cls.getClassLoader().getSystemClassLoader().getResourceAsStream(clsname); 38 | if (is == null) return null; 39 | byte[] bt = new byte[is.available()]; 40 | is.read(bt); 41 | is.close(); 42 | return bt; 43 | } 44 | } -------------------------------------------------------------------------------- /HotAgent/src/hotAgent.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wanwanpp/java-plus/56b5795dad68c27706e177ffbc7e7281c2c0426d/HotAgent/src/hotAgent.jar -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # java-plus 2 | java基础进阶。包括:socket,多线程,反射,servlet,动态代理等高级知识。 3 | -------------------------------------------------------------------------------- /jdbc/pom.xml: -------------------------------------------------------------------------------- 1 | 3 | 4.0.0 4 | 5 | com.wp 6 | jdbc 7 | 1.0-SNAPSHOT 8 | jar 9 | 10 | jdbc 11 | http://maven.apache.org 12 | 13 | 14 | UTF-8 15 | 16 | 17 | 18 | 19 | 20 | mysql 21 | mysql-connector-java 22 | 5.1.21 23 | 24 | 25 | junit 26 | junit 27 | 4.12 28 | 29 | 30 | 31 | -------------------------------------------------------------------------------- /jdbc/src/main/java/com/wp/jdbc/App.java: -------------------------------------------------------------------------------- 1 | package com.wp.jdbc; 2 | 3 | import org.junit.After; 4 | import org.junit.Before; 5 | import org.junit.Test; 6 | 7 | import java.sql.*; 8 | 9 | public class App { 10 | 11 | Connection connection = null; 12 | Statement statement = null; 13 | ResultSet resultSet = null; 14 | PreparedStatement preparedStatement = null; 15 | 16 | @Before 17 | public void getConnection() { 18 | try { 19 | Class.forName("com.mysql.jdbc.Driver"); 20 | } catch (ClassNotFoundException e) { 21 | System.out.println("找不到MySQL驱动"); 22 | } 23 | 24 | String url = "jdbc:mysql://localhost:3306/jdbc"; 25 | String username = "root"; 26 | String password = "980325"; 27 | 28 | try { 29 | connection = DriverManager.getConnection(url, username, password); 30 | } catch (SQLException e) { 31 | System.out.println("数据库连接失败"); 32 | e.printStackTrace(); 33 | } 34 | System.out.println("数据库连接成功"); 35 | } 36 | 37 | @Test 38 | public void statement() { 39 | try { 40 | //创建指针可以自由移动结果集ResultSet 41 | statement = connection.createStatement(ResultSet.TYPE_SCROLL_SENSITIVE, ResultSet.CONCUR_UPDATABLE); 42 | } catch (SQLException e) { 43 | e.printStackTrace(); 44 | } 45 | 46 | try { 47 | resultSet = statement.executeQuery("SELECT * FROM users"); 48 | // statement.executeUpdate(sql) 49 | 50 | //resultSet.getMetaData可以获取结果集的元信息。 51 | System.out.println("列数为:" + resultSet.getMetaData().getColumnCount()); 52 | 53 | //将指针移到最后一行,然后打印最后一行的行号,即得到了行数. 54 | resultSet.last(); 55 | System.out.println("行数为:" + resultSet.getRow()); 56 | //将结果集的指针移到第一行 57 | resultSet.beforeFirst(); 58 | 59 | //resultSet.first();//此时指针在第一行,遍历时会从第二行开始 60 | while (resultSet.next()) { 61 | //列索引从1开始 62 | System.out.println("id:" + resultSet.getInt(1) + " " + 63 | "name:" + resultSet.getString(2) + " " + 64 | "sex:" + resultSet.getString(3) + " " + 65 | "birthday:" + resultSet.getTimestamp(4)); 66 | if (resultSet.getRow() == 2) { 67 | //这个方法并不执行数据库操作,需要执行insertRow()方法或者updateRow()方法以后,记录集和数据库中的数据才能够真正更新 68 | resultSet.updateString(2, "wanwanpp"); 69 | resultSet.updateRow();//这里有数据库更新操作 70 | // System.out.println("ROW is " + resultSet.getRow());//返回当前的行号 71 | } 72 | } 73 | } catch (SQLException e) { 74 | e.printStackTrace(); 75 | } 76 | } 77 | 78 | @Test 79 | public void prepareStatement() throws SQLException { 80 | try { 81 | preparedStatement = connection.prepareStatement("SELECT * FROM users WHERE name=?",ResultSet.TYPE_SCROLL_SENSITIVE,ResultSet.CONCUR_UPDATABLE); 82 | } catch (SQLException e) { 83 | System.out.println("无法获取prepareStatement"); 84 | e.printStackTrace(); 85 | } 86 | 87 | preparedStatement.setString(1, "王萍"); 88 | resultSet = preparedStatement.executeQuery(); 89 | while (resultSet.next()) { 90 | System.out.println("id:" + resultSet.getInt(1) + " " + 91 | "name:" + resultSet.getString(2) + " " + 92 | "sex:" + resultSet.getString(3) + " " + 93 | "birthday:" + resultSet.getTimestamp(4)); 94 | if (resultSet.getRow() == 2) { 95 | 96 | System.out.println("ROW is " + resultSet.getRow());//返回当前的行号 97 | } 98 | } 99 | 100 | 101 | } 102 | 103 | @After 104 | public void close() { 105 | if (resultSet != null) { 106 | try { 107 | resultSet.close(); 108 | } catch (SQLException e) { 109 | System.out.println("resultSet关闭失败"); 110 | e.printStackTrace(); 111 | } 112 | } 113 | if (statement != null) { 114 | try { 115 | statement.close(); 116 | } catch (SQLException e) { 117 | System.out.println("statement关闭失败"); 118 | e.printStackTrace(); 119 | } 120 | } 121 | if (preparedStatement != null) { 122 | try { 123 | preparedStatement.close(); 124 | } catch (SQLException e) { 125 | System.out.println("PreparedStatement关闭失败"); 126 | e.printStackTrace(); 127 | } 128 | } 129 | if (connection != null) { 130 | try { 131 | connection.close(); 132 | } catch (SQLException e) { 133 | System.out.println("connection关闭失败"); 134 | e.printStackTrace(); 135 | } 136 | } 137 | } 138 | } 139 | -------------------------------------------------------------------------------- /jdbc/src/main/java/com/wp/jdbc/ResultSet中的方法.java: -------------------------------------------------------------------------------- 1 | package com.wp.jdbc;//package com.wp.jdbc; 2 | // 3 | //import javax.naming.InitialContext; 4 | //import java.sql.*; 5 | // 6 | ///** 7 | // * Created by 王萍 on 2017/6/28 0028. 8 | // */ 9 | //public class ResultSet中的方法 { 10 | // 1 新定义了若干个常数 11 | // 12 | // 这些常数用于指定ResultSet 的类型游标移动的方向等性质,如下所示: 13 | // public static final int FETCH_FORWARD; 该常数的作用是指定处理记录集中行的顺序,是由前到后即从第一行开始处理一直到最后一行; 14 | // public static final int FETCH_REVERSE; 该常数的作用是指定处理记录集中行的顺序,是由后到前即从最后一行开始处理一直到第一行; 15 | // public static final int FETCH_UNKNOWN; 该常数的作用是不指定处理记录集中行的顺序,由JDBC 驱动程序和数据库系统决定; 16 | // public static final int TYPE_FORWARD_ONLY; 该常数的作用是指定数据库游标的移动方向是向前,不允许向后移动即只能使用ResultSet 接口的next()方法而不能使用previous()方法否则会产生错误; 17 | // public static final int TYPE_SCROLL_INSENSITIVE; 该常数的作用是指定数据库游标可以在记录集中前后移动,并且当前数据库用户获取的记录集对其他用户的操作不敏感;就是说,当前用户正在浏览记录集中的数据,与此同时,其他用户更新了数据库中的数据,但是当前用户所获取的记录集中的数据不会受到任何影响。 18 | // public static final int TYPE_SCROLL_SENSITIVE; 该常数的作用是指定数据库游标可以在记录集中前后移动,并且当前数据库用户获取的记录集对其他用户的操作敏感,就是说,当前用户正在浏览记录集,但是其它用户的操作使数据库中的数据发生了变化,当前用户所获取的记录集中的数据也会同步发生变化,这样有可能会导致非常严重的错误产生建议慎重使用该常数。 19 | // public static final int CONCUR_READ_ONLY; 该常数的作用是指定当前记录集的协作方式(concurrencymode),为只读;一旦使用了这个常数,那么用户就不可以更新记录集中的数据。 20 | // public static final int CONCUR_UPDATABLE; 该常数的作用是指定当前记录集的协作方式(concurrencymode),为可以更新;一旦使用了这个常数,那么用户就可以使用updateXXX()等方法更新记。 21 | // 22 | // 2 ResultSet 接口提供了一整套的定位方法 23 | // 这些可以在记录集中定位到任意一行: 24 | // public boolean absolute(int row); 该方法的作用是将记录集中的某一行设定为当前行,亦即将数据库游标移动到指定的行,参数row 指定了目标行的行号,这是绝对的行号,由记录集的第一行开始计算不是相对的行号。 25 | // public boolean relative(int rows); 该方法的作用也是将记录集中的某一行设定为当前行,但是它的参数rows 表示目标行相对于当前行的行号。 26 | // public boolean first(); 该方法的作用是将当前行定位到数据库记录集的第一行。 27 | // public boolean last(); 该方法的作用刚好和first()方法相反。 28 | // public boolean isFirst(); 29 | // public boolean isFirst(); 该方法的作用是检查当前行是否记录集的第一行,如果是返回true, 否则返回false。 30 | // public boolean isLast(); 该方法的作用是检查当前行是否记录集的最后一行,如果是返回true ,否则返回false。 31 | // public void afterLast(); 该方法的作用是将数据库游标移到记录集的最后,位于记录集最后一行的后面,如果该记录集不包含任何的行该方法不产生作用。 32 | // public void beforeFirst(); 该方法的作用是将数据库游标移到记录集的最前面,位于记录集第一行的前面,如果记录集不包含任何的行该方法不产生作用。 33 | // public boolean isAfterLast(); 该方法检查数据库游标是否处于记录集的最后面,如果是返回true ,否则返回false。 34 | // public boolean isBeforeFirst(); 该方法检查数据库游标是否处于记录集的最前面,如果是返回true ,否则返回false。 35 | // public boolean next(); 该方法的作用是将数据库游标向前移动一位,使得下一行成为当前行,当刚刚打开记录集对象时,数据库游标的位置在记录集的最前面,第一次使用next()方法将会使数据库游标定位到记录集的第一行,第二次使用next()方法将会使数据库游标定位到记录集的第二行,以此类推。 36 | // public boolean previous(); 该方法的作用是将数据库游标向后移动一位,使得上一行成为当前行。 37 | // 38 | // 3 ResultSet 接口添加了对行操作的支持(最令人心动之处) 39 | // 40 | // 修改了的记录集接口(ResultSet 接口)的方法,使它支持可以滚动的记录集,即数据库游标可以在返回的记录集对象中自由地向前或向后滚动,或者定位到某个特殊的行。利用ResultSet 接口中定义的新方法,JSP/Servlet 程序员可以用Java 语言来更新记录集,比如插入记录,更新某行的数据,而不是靠执行SQL 语句,这样就大大方便了程序员的开发工作,享受Java 编程的乐趣了。 41 | // ResultSet 接口中新添加的部分方法如下所示: 42 | // public boolean rowDeleted(); 如果当前记录集的某行被删除了,那么记录集中将会留出一个空位;调用rowDeleted()方法,如果探测到空位的存在,那么就返回true; 如果没有探测到空位的存在,就返回false 值。 43 | // public boolean rowInserted(); 如果当前记录集中插入了一个新行,该方法将返回true ,否则返回false。 44 | // public boolean rowUpdated(); 如果当前记录集的当前行的数据被更新,该方法返回true ,否则返回false。 45 | // public void insertRow(); 该方法将执行插入一个新行到当前记录集的操作。 46 | // public void updateRow(); 该方法将更新当前记录集当前行的数据。 47 | // public void deleteRow(); 该方法将删除当前记录集的当前行。 48 | // public void updateString(int columnIndex String x); 该方法更新当前记录集当前行某列的值,该列的数据类型是String(指Java 数据类型是String ,与之对应的JDBC 数据类型是VARCHAR 或NVARCHAR 等数据类型) 。该方法的参数columnIndex 指定所要更新的列的列索引,第一列的列索引是1 ,以此类推,第二个参数x 代表新的值,这个方法并不执行数据库操作,需要执行insertRow()方法或者updateRow()方法以后,记录集和数据库中的数据才能够真正更新。 49 | // public void updateString(String columnName String x); 该方法和上面介绍的同名方法差不多,不过该方法的第一个参数是columnName ,代表需要更新的列的列名,而不是columnIndex。 50 | // 51 | // 往数据库当前记录集插入新行的操作流程如下: 52 | // 1 调用moveToInsertRow()方法; 53 | // 2 调用updateXXX()方法指定插入行各列的值; 54 | // 3 调用insertRow()方法往数据库中插入新的行。 55 | // 56 | // 更新数据库中某个记录的值(某行的值)的方法是: 57 | // 1 定位到需要修改的行(使用absolute() relative()等方法定位); 58 | // 2 使用相应updateXXX()方法设定某行某列的新值;XXX 所代表的Java 数据类型,必须可以映射为某列的JDBC 数据类型,如果希望rollback 该项操作,请在调用updateRow()方法以前,使用cancelRowUpdates()方法,这个方法可以将某行某列的值复原; 59 | // 3 使用updateRow()方法完成UPDATE 的操作。 60 | // 61 | // 删除记录集中某行(亦即删除某个记录)的方法: 62 | // 1 定位到需要修改的行(使用absolute() relative()等方法定位); 63 | // 2 使用deleteRow() 64 | // 删除记录集中某行(亦即删除某个记录)的方法: 65 | // 1 定位到需要修改的行(使用absolute() relative()等方法定位); 66 | // 2 使用deleteRow()方法。 67 | // 68 | // JDBC API 3.0 中还在ResultSet 接口中添加了updateArray() updateBlob() updateClob() updateRef()等方法 69 | // 70 | // 71 | // 72 | //1、java数据库操作基本流程 73 | // 74 | //  2、几个常用的重要技巧: 75 | // 76 | //   可滚动、更新的记录集 77 | // 78 | //  批量更新 79 | // 80 | //  事务处理 81 | // 82 | //  java数据库操作基本流程:取得数据库连接 - 执行sql语句 - 处理执行结果 - 释放数据库连接 83 | // 84 | //  1、取得数据库连接 85 | // 86 | //  1)用DriverManager取数据库连接 87 | // 88 | //  例子: 89 | // 90 | // String className,url,uid,pwd; 91 | // className = "oracle.jdbc.driver.OracleDriver"; 92 | ////MySQL:className = "com.mysql.jdbc.Driver"; 93 | ////SQLServer:className = "com.microsoft.sqlserver.jdbc.SQLServerDriver"; 94 | // url = "jdbc:oracle:thin:@127.0.0.1:1521:orasvr"; 95 | ////MySQL:url = "jdbc:mysql://127.0.0.1:3306/数据库名"; 96 | ////SQLServer:url = "jdbc:sqlserver://127.0.0.1:1433;DatabaseName=数据库名"; 97 | // uid = "system"; 98 | // pwd = "manager"; 99 | //Class.forName(className); 100 | // Connection cn = DriverManager.getConnection(url,uid,pwd); 101 | // 102 | //  2)用jndi(java的命名和目录服务)方式 103 | // 104 | //  例子 105 | // 106 | // String jndi = "jdbc/db"; 107 | // Context ctx = (Context) new InitialContext().lookup("java:comp/env"); 108 | // DataSource ds = (DataSource) ctx.lookup(jndi); 109 | // Connection cn = ds.getConnection(); 110 | // 111 | //  多用于jsp中 112 | // 113 | //  2、执行sql语句 114 | // 115 | //  1)用Statement来执行sql语句 116 | // 117 | // String sql; 118 | // Statement sm = cn.createStatement(); 119 | //sm.executeQuery(sql); // 执行数据查询语句(select) 120 | //sm.executeUpdate(sql); // 执行数据更新语句(delete、update、insert、drop等)statement.close(); 121 | // 122 | //  2)用PreparedStatement来执行sql语句 123 | // 124 | // String sql; 125 | // sql = "insert into user (id,name) values (?,?)"; 126 | // PreparedStatement ps = cn.prepareStatement(sql); 127 | //ps.setInt(1,xxx); 128 | //ps.setString(2,xxx); 129 | //... 130 | // ResultSet rs = ps.executeQuery(); // 查询 131 | // int c = ps.executeUpdate(); // 更新 132 | // 133 | //  3、处理执行结果 134 | // 135 | //  查询语句,返回记录集ResultSet。 136 | // 137 | //   更新语句,返回数字,表示该更新影响的记录数。 138 | // 139 | //   ResultSet的方法: 140 | // 141 | //   1、next(),将游标往后移动一行,如果成功返回true;否则返回false。 142 | // 143 | //   2、getInt("id")或getSting("name"),返回当前游标下某个字段的值。 144 | // 145 | //   3、释放连接。 146 | // 147 | // cn.close(); 148 | // 149 | //  一般,先关闭ResultSet,然后关闭Statement(或者PreparedStatement);最后关闭Connection 150 | // 151 | //  可滚动、更新的记录集 152 | // 153 | //  1、创建可滚动、更新的Statement 154 | // 155 | // Statement sm = cn.createStatement(ResultSet.TYPE_SCROLL_ENSITIVE,ResultSet.CONCUR_READ_ONLY); 156 | // 157 | //  该Statement取得的ResultSet就是可滚动的 158 | // 159 | //  2、创建PreparedStatement时指定参数 160 | // 161 | // PreparedStatemet ps = cn.prepareStatement(sql,ResultSet.TYPE_SCROLL_INSENSITIVE,ResultSet.CONCUR_READ_ONLY); 162 | // 163 | //ResultSet.absolute(9000); 164 | // 165 | //  批量更新 166 | // 167 | //  1、Statement 168 | // 169 | // Statement sm = cn.createStatement(); 170 | //sm.addBatch(sql1); 171 | //sm.addBatch(sql2); 172 | //... 173 | // sm.executeBatch() 174 | // 175 | //   一个Statement对象,可以执行多个sql语句以后,批量更新。这多个语句可以是delete、update、insert等或兼有 176 | // 177 | //  2、PreparedStatement 178 | // 179 | // PreparedStatement ps = cn.preparedStatement(sql); 180 | // { 181 | // ps.setXXX(1,xxx); 182 | // ... 183 | // ps.addBatch(); 184 | // } 185 | //ps.executeBatch(); 186 | // 187 | //  一个PreparedStatement,可以把一个sql语句,变换参数多次执行,一次更新。 188 | // 189 | //   事务的处理 190 | // 191 | //  1、关闭Connection的自动提交 192 | // 193 | //cn.setAutoCommit(false); 194 | // 195 | //  2、执行一系列sql语句 196 | // 197 | //  要点:执行每一个新的sql语句前,上一次执行sql语句的Statement(或者PreparedStatemet)必须先close 198 | // 199 | // Statement sm ; 200 | // sm = cn.createStatement("insert into user..."); 201 | //sm.executeUpdate(); 202 | //sm.close(); 203 | // 204 | // sm = cn.createStatement("insert into corp..."); 205 | //sm.executeUpdate(); 206 | //sm.close(); 207 | // 208 | //  3、提交 209 | // 210 | //cn.commit(); 211 | // 212 | //  4、如果发生异常,那么回滚 213 | // 214 | //cn.rollback(); 215 | //} 216 | -------------------------------------------------------------------------------- /lib/commons-beanutils-1.9.3.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wanwanpp/java-plus/56b5795dad68c27706e177ffbc7e7281c2c0426d/lib/commons-beanutils-1.9.3.jar -------------------------------------------------------------------------------- /lib/commons-logging-1.2.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wanwanpp/java-plus/56b5795dad68c27706e177ffbc7e7281c2c0426d/lib/commons-logging-1.2.jar -------------------------------------------------------------------------------- /lib/guava-23.0.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wanwanpp/java-plus/56b5795dad68c27706e177ffbc7e7281c2c0426d/lib/guava-23.0.jar -------------------------------------------------------------------------------- /lib/tools.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wanwanpp/java-plus/56b5795dad68c27706e177ffbc7e7281c2c0426d/lib/tools.jar -------------------------------------------------------------------------------- /servlet/pom.xml: -------------------------------------------------------------------------------- 1 | 3 | 4.0.0 4 | com.wp 5 | servlet 6 | war 7 | 1.0-SNAPSHOT 8 | servlet Maven Webapp 9 | http://maven.apache.org 10 | 11 | 12 | 13 | junit 14 | junit 15 | 3.8.1 16 | test 17 | 18 | 19 | 20 | org.apache.tomcat 21 | tomcat-catalina 22 | 8.0.37 23 | 24 | 25 | 26 | 27 | servlet 28 | 29 | 30 | -------------------------------------------------------------------------------- /servlet/src/main/java/com/wp/servlet/demo1/AServlet.java: -------------------------------------------------------------------------------- 1 | package com.wp.servlet.demo1; 2 | 3 | import javax.servlet.ServletException; 4 | import javax.servlet.http.HttpServlet; 5 | import javax.servlet.http.HttpServletRequest; 6 | import javax.servlet.http.HttpServletResponse; 7 | import java.io.IOException; 8 | 9 | public class AServlet extends HttpServlet { 10 | 11 | public void doGet(HttpServletRequest request, HttpServletResponse response) 12 | throws ServletException, IOException { 13 | System.out.println("进入了AServlet"); 14 | //设置状态码 15 | response.sendError(404, "找到也不告诉你!"); 16 | } 17 | 18 | public void doPost(HttpServletRequest request, HttpServletResponse response) 19 | throws ServletException, IOException { 20 | 21 | } 22 | 23 | } 24 | -------------------------------------------------------------------------------- /servlet/src/main/java/com/wp/servlet/demo2/BServlet.java: -------------------------------------------------------------------------------- 1 | package com.wp.servlet.demo2; 2 | 3 | import javax.servlet.ServletException; 4 | import javax.servlet.http.HttpServlet; 5 | import javax.servlet.http.HttpServletRequest; 6 | import javax.servlet.http.HttpServletResponse; 7 | import java.io.IOException; 8 | 9 | public class BServlet extends HttpServlet { 10 | 11 | //重定向 12 | public void doGet(HttpServletRequest request, HttpServletResponse response) 13 | throws ServletException, IOException { 14 | //重定向 15 | /* 16 | //1 返回状态码为302 17 | response.setStatus(302); 18 | //2 告诉浏览器去哪找新的地址 发送一个响应头: Location : http://www.baidu.com 19 | //response.setHeader("Location", "http://www.baidu.com"); 20 | response.setHeader("Location", "/Day08-response/AServlet"); 21 | */ 22 | //----------------------------------------------------------------- 23 | response.sendRedirect("/AServlet"); 24 | } 25 | 26 | public void doPost(HttpServletRequest request, HttpServletResponse response) 27 | throws ServletException, IOException { 28 | 29 | } 30 | 31 | } 32 | -------------------------------------------------------------------------------- /servlet/src/main/java/com/wp/servlet/demo3/CServlet.java: -------------------------------------------------------------------------------- 1 | package com.wp.servlet.demo3; 2 | 3 | import javax.servlet.ServletException; 4 | import javax.servlet.http.HttpServlet; 5 | import javax.servlet.http.HttpServletRequest; 6 | import javax.servlet.http.HttpServletResponse; 7 | import java.io.IOException; 8 | 9 | public class CServlet extends HttpServlet { 10 | 11 | public void doGet(HttpServletRequest request, HttpServletResponse response) 12 | throws ServletException, IOException { 13 | //解决乱码 14 | response.setContentType("text/html;charset=utf-8"); 15 | //1.设置响应头 为Refresh:5;url=/Day08-response/AServlet 16 | response.setHeader("Refresh", "5;url=/AServlet"); 17 | //2.使用字符流发送提示,5秒后跳转 18 | response.getWriter().print("您将在秒后跳转到AServlet!" + 19 | ""); 31 | } 32 | 33 | public void doPost(HttpServletRequest request, HttpServletResponse response) 34 | throws ServletException, IOException { 35 | 36 | } 37 | 38 | } 39 | -------------------------------------------------------------------------------- /servlet/src/main/java/com/wp/servlet/demo4/DServlet.java: -------------------------------------------------------------------------------- 1 | package com.wp.servlet.demo4; 2 | 3 | import javax.servlet.ServletException; 4 | import javax.servlet.http.HttpServlet; 5 | import javax.servlet.http.HttpServletRequest; 6 | import javax.servlet.http.HttpServletResponse; 7 | import java.io.IOException; 8 | import java.io.OutputStream; 9 | 10 | public class DServlet extends HttpServlet { 11 | 12 | public void doGet(HttpServletRequest request, HttpServletResponse response) 13 | throws ServletException, IOException { 14 | //1 获得输出字节流 15 | OutputStream os = response.getOutputStream(); 16 | //2 输出中文 17 | os.write("你好 世界!".getBytes("UTF-8")); 18 | //3告诉浏览器使用GBK解码 ==> 乱码 19 | //os.write("".getBytes()); 20 | response.setHeader("Content-Type", "text/html;charset=utf-8"); 21 | } 22 | 23 | public void doPost(HttpServletRequest request, HttpServletResponse response) 24 | throws ServletException, IOException { 25 | 26 | } 27 | 28 | } 29 | -------------------------------------------------------------------------------- /servlet/src/main/java/com/wp/servlet/demo5/EServlet.java: -------------------------------------------------------------------------------- 1 | package com.wp.servlet.demo5; 2 | 3 | import javax.servlet.ServletException; 4 | import javax.servlet.http.HttpServlet; 5 | import javax.servlet.http.HttpServletRequest; 6 | import javax.servlet.http.HttpServletResponse; 7 | import java.io.IOException; 8 | import java.io.PrintWriter; 9 | 10 | public class EServlet extends HttpServlet { 11 | 12 | public void doGet(HttpServletRequest request, HttpServletResponse response) 13 | throws ServletException, IOException { 14 | /*//控制字符流使用的编码,往上放.在获得字符流的时候,会来取这个编码.如果在取完之后设置,没有效果. 15 | response.setCharacterEncoding("UTF-8"); 16 | //告诉浏览器使用什么码表解码 17 | response.setHeader("Content-Type", "text/html;charset=utf-8");*/ 18 | //JAVAEE提供了一个方法,这个方法同时可以做 以上两件事. 19 | response.setContentType("text/html;charset=utf-8"); 20 | 21 | System.out.println("在EServlet中"); 22 | //1 获得字符流 23 | PrintWriter pw = response.getWriter(); 24 | //2 发送中文 25 | pw.print("你好 世界!"); 26 | 27 | //问题: 同时使用两种流 会出现问题 28 | // response.getOutputStream().write("haha".getBytes()); 29 | 30 | } 31 | 32 | public void doPost(HttpServletRequest request, HttpServletResponse response) 33 | throws ServletException, IOException { 34 | 35 | } 36 | 37 | } 38 | -------------------------------------------------------------------------------- /servlet/src/main/java/com/wp/servlet/demo6/FServlet.java: -------------------------------------------------------------------------------- 1 | package com.wp.servlet.demo6; 2 | 3 | import javax.servlet.ServletException; 4 | import javax.servlet.http.HttpServlet; 5 | import javax.servlet.http.HttpServletRequest; 6 | import javax.servlet.http.HttpServletResponse; 7 | import java.io.IOException; 8 | import java.io.InputStream; 9 | import java.io.OutputStream; 10 | 11 | public class FServlet extends HttpServlet { 12 | 13 | public void doGet(HttpServletRequest request, HttpServletResponse response) 14 | throws ServletException, IOException { 15 | //0告诉浏览器 发给你的流的MIME类型. 16 | response.setContentType("image/jpeg"); 17 | //1 通过servlet上下文获得图片的输入流 18 | InputStream in = getServletContext().getResourceAsStream("/WEB-INF/001.jpg"); 19 | //2 通过response获得输出字节流 20 | OutputStream out = response.getOutputStream(); 21 | //3 两个对接 22 | byte[] buffer = new byte[1024]; 23 | int len = 0; 24 | while((len=in.read(buffer))>0){ 25 | out.write(buffer, 0, len); 26 | out.flush(); 27 | } 28 | in.close(); 29 | } 30 | 31 | public void doPost(HttpServletRequest request, HttpServletResponse response) 32 | throws ServletException, IOException { 33 | 34 | } 35 | 36 | } 37 | -------------------------------------------------------------------------------- /servlet/src/main/java/com/wp/servlet/demo7/GServlet.java: -------------------------------------------------------------------------------- 1 | package com.wp.servlet.demo7; 2 | 3 | import javax.servlet.ServletException; 4 | import javax.servlet.http.HttpServlet; 5 | import javax.servlet.http.HttpServletRequest; 6 | import javax.servlet.http.HttpServletResponse; 7 | import java.io.IOException; 8 | import java.io.InputStream; 9 | import java.io.OutputStream; 10 | 11 | public class GServlet extends HttpServlet { 12 | 13 | public void doGet(HttpServletRequest request, HttpServletResponse response) 14 | throws ServletException, IOException { 15 | //0 告诉浏览器是什么东西 16 | //getServletContext().getMimeType(".jar") Context对象根据 后缀名去web.xml查找mime类型. 17 | response.setContentType(getServletContext().getMimeType(".jar")); 18 | //告诉浏览器推荐用户使用什么名称下载 19 | response.setHeader("Content-Disposition", "attachment;filename=ValidateCode.jar"); 20 | //1 获得图片的输入流 21 | InputStream in = getServletContext().getResourceAsStream("/WEB-INF/ValidateCode.jar"); 22 | //2 通过response获得输出字节流 23 | OutputStream out = response.getOutputStream(); 24 | //3 两个对接 25 | byte[] buffer = new byte[1024]; 26 | int len = 0; 27 | while ((len = in.read(buffer)) > 0) { 28 | out.write(buffer, 0, len); 29 | out.flush(); 30 | } 31 | in.close(); 32 | } 33 | 34 | public void doPost(HttpServletRequest request, HttpServletResponse response) 35 | throws ServletException, IOException { 36 | 37 | } 38 | 39 | } 40 | -------------------------------------------------------------------------------- /servlet/src/main/java/com/wp/servlet/filter/LogFilter.java: -------------------------------------------------------------------------------- 1 | package com.wp.servlet.filter; 2 | 3 | import javax.servlet.*; 4 | import javax.servlet.http.HttpServletRequest; 5 | import java.io.IOException; 6 | 7 | public class LogFilter implements Filter { 8 | FilterConfig config; 9 | 10 | public void destroy() { 11 | this.config = null; 12 | } 13 | 14 | public void doFilter(ServletRequest req, ServletResponse res, 15 | FilterChain chain) throws IOException, ServletException { 16 | 17 | // 获取ServletContext 对象,用于记录日志 18 | ServletContext context = this.config.getServletContext(); 19 | //long before = System.currentTimeMillis(); 20 | System.out.println("before the log filter!"); 21 | //context.log("开始过滤"); 22 | // 将请求转换成HttpServletRequest 请求 23 | HttpServletRequest hreq = (HttpServletRequest) req; 24 | // 记录日志 25 | System.out.println("Log Filter已经截获到用户的请求的地址:" + hreq.getServletPath()); 26 | // context.log("Filter已经截获到用户的请求的地址: " + hreq.getServletPath()); 27 | try { 28 | // Filter 只是链式处理,请求依然转发到目的地址。 29 | chain.doFilter(req, res); 30 | } catch (Exception e) { 31 | e.printStackTrace(); 32 | } 33 | System.out.println("after the log filter!"); 34 | //long after = System.currentTimeMillis(); 35 | // 记录日志 36 | //context.log("过滤结束"); 37 | // 再次记录日志 38 | //context.log(" 请求被定位到" + ((HttpServletRequest) req).getRequestURI() 39 | // + "所花的时间为: " + (after - before)); 40 | } 41 | 42 | public void init(FilterConfig config) throws ServletException { 43 | System.out.println("begin do the log filter!"); 44 | this.config = config; 45 | } 46 | 47 | } -------------------------------------------------------------------------------- /servlet/src/main/resources/1.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wanwanpp/java-plus/56b5795dad68c27706e177ffbc7e7281c2c0426d/servlet/src/main/resources/1.jpg -------------------------------------------------------------------------------- /servlet/src/main/webapp/WEB-INF/1.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wanwanpp/java-plus/56b5795dad68c27706e177ffbc7e7281c2c0426d/servlet/src/main/webapp/WEB-INF/1.jpg -------------------------------------------------------------------------------- /servlet/src/main/webapp/WEB-INF/web.xml: -------------------------------------------------------------------------------- 1 | 2 | 7 | 8 | 9 | AServlet 10 | com.wp.servlet.demo1.AServlet 11 | 12 | 13 | BServlet 14 | com.wp.servlet.demo2.BServlet 15 | 16 | 17 | CServlet 18 | com.wp.servlet.demo3.CServlet 19 | 20 | 21 | DServlet 22 | com.wp.servlet.demo4.DServlet 23 | 24 | 25 | EServlet 26 | com.wp.servlet.demo5.EServlet 27 | 28 | 29 | FServlet 30 | com.wp.servlet.demo6.FServlet 31 | 32 | 33 | GServlet 34 | com.wp.servlet.demo7.GServlet 35 | 36 | 37 | 38 | AServlet 39 | /AServlet 40 | 41 | 42 | BServlet 43 | /BServlet 44 | 45 | 46 | CServlet 47 | /CServlet 48 | 49 | 50 | DServlet 51 | /DServlet 52 | 53 | 54 | EServlet 55 | /EServlet 56 | 57 | 58 | FServlet 59 | /FServlet 60 | 61 | 62 | GServlet 63 | /GServlet 64 | 65 | 66 | 67 | 68 | index.jsp 69 | 70 | 71 | 72 | logFilter 73 | com.wp.servlet.filter.LogFilter 74 | 75 | 76 | logFilter 77 | /* 78 | 79 | 80 | -------------------------------------------------------------------------------- /servlet/src/main/webapp/index.jsp: -------------------------------------------------------------------------------- 1 | <%@ page language="java" import="java.util.*" pageEncoding="ISO-8859-1" %> 2 | <% 3 | String path = request.getContextPath(); 4 | String basePath = request.getScheme() + "://" + request.getServerName() + ":" + request.getServerPort() + path + "/"; 5 | %> 6 | 7 | 8 | 9 | 10 | 11 | 12 | My JSP 'index.jsp' starting page 13 | 14 | 15 | 16 | 17 | 18 | 29 | 32 | 33 | 34 | 35 | This is my JSP page.
36 | 37 | 38 | -------------------------------------------------------------------------------- /socket/src/wp/Main.java: -------------------------------------------------------------------------------- 1 | package wp; 2 | 3 | import java.sql.Timestamp; 4 | 5 | /** 6 | * Created by 王萍 on 2017/8/8 0008. 7 | */ 8 | public class Main { 9 | public static void main(String[] args) { 10 | // List dateLinkedList = new ArrayList<>(100000000); 11 | // List dateLinkedList = new LinkedList<>(); 12 | Timestamp[] dateLinkedList = new Timestamp[100000000]; 13 | // HashSet dateLinkedList = new HashSet<>(100000000); 14 | long before = System.currentTimeMillis(); 15 | Timestamp timestamp = new Timestamp(System.currentTimeMillis()); 16 | 17 | for (int i = 0; i < 100000000; i++) { 18 | //[List] 19 | // dateLinkedList.add(timestamp); 20 | // timestamp=new Timestamp(System.currentTimeMillis()); 21 | // dateLinkedList.add(new Timestamp(System.currentTimeMillis())); 22 | 23 | //[Array] 24 | dateLinkedList[i] = timestamp; 25 | timestamp = new Timestamp(System.currentTimeMillis()); 26 | 27 | //[HashSet] 28 | // dateLinkedList.add(new Timestamp(System.currentTimeMillis())); 29 | } 30 | 31 | System.out.println(System.currentTimeMillis() - before); 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /socket/src/wp/aio/Client.java: -------------------------------------------------------------------------------- 1 | package wp.aio; 2 | 3 | import java.io.UnsupportedEncodingException; 4 | import java.net.InetSocketAddress; 5 | import java.nio.ByteBuffer; 6 | import java.nio.channels.AsynchronousSocketChannel; 7 | import java.util.concurrent.ExecutionException; 8 | 9 | public class Client implements Runnable { 10 | 11 | private AsynchronousSocketChannel asc; 12 | 13 | public Client() throws Exception { 14 | asc = AsynchronousSocketChannel.open(); 15 | } 16 | 17 | public void connect() { 18 | asc.connect(new InetSocketAddress("127.0.0.1", 8765)); 19 | } 20 | 21 | public void write(String request) { 22 | try { 23 | asc.write(ByteBuffer.wrap(request.getBytes())).get(); 24 | read(); 25 | } catch (Exception e) { 26 | e.printStackTrace(); 27 | } 28 | } 29 | 30 | private void read() { 31 | ByteBuffer buf = ByteBuffer.allocate(1024); 32 | try { 33 | asc.read(buf).get(); 34 | buf.flip(); 35 | byte[] respByte = new byte[buf.remaining()]; 36 | buf.get(respByte); 37 | System.out.println(new String(respByte, "utf-8").trim()); 38 | } catch (InterruptedException e) { 39 | e.printStackTrace(); 40 | } catch (ExecutionException e) { 41 | e.printStackTrace(); 42 | } catch (UnsupportedEncodingException e) { 43 | e.printStackTrace(); 44 | } 45 | } 46 | 47 | @Override 48 | public void run() { 49 | while (true) { 50 | 51 | } 52 | } 53 | 54 | public static void main(String[] args) throws Exception { 55 | Client c1 = new Client(); 56 | c1.connect(); 57 | 58 | Client c2 = new Client(); 59 | c2.connect(); 60 | 61 | Client c3 = new Client(); 62 | c3.connect(); 63 | 64 | new Thread(c1, "c1").start(); 65 | new Thread(c2, "c2").start(); 66 | new Thread(c3, "c3").start(); 67 | 68 | Thread.sleep(1000); 69 | 70 | c1.write("c1 aaa"); 71 | c2.write("c2 bbbb"); 72 | c3.write("c3 ccccc"); 73 | } 74 | 75 | } 76 | -------------------------------------------------------------------------------- /socket/src/wp/aio/Server.java: -------------------------------------------------------------------------------- 1 | package wp.aio; 2 | 3 | import java.net.InetSocketAddress; 4 | import java.nio.channels.AsynchronousChannelGroup; 5 | import java.nio.channels.AsynchronousServerSocketChannel; 6 | import java.util.concurrent.ExecutorService; 7 | import java.util.concurrent.Executors; 8 | 9 | public class Server { 10 | //线程池 11 | private ExecutorService executorService; 12 | //线程组 13 | private AsynchronousChannelGroup threadGroup; 14 | //服务器通道 15 | public AsynchronousServerSocketChannel assc; 16 | 17 | public Server(int port){ 18 | try { 19 | //创建一个缓存池 20 | executorService = Executors.newCachedThreadPool(); 21 | //创建线程组 22 | threadGroup = AsynchronousChannelGroup.withCachedThreadPool(executorService, 1); 23 | //创建服务器通道 24 | assc = AsynchronousServerSocketChannel.open(threadGroup); 25 | //进行绑定 26 | assc.bind(new InetSocketAddress(port)); 27 | 28 | System.out.println("server start , port : " + port); 29 | //进行阻塞 30 | assc.accept(this, new ServerCompletionHandler()); 31 | //一直阻塞 不让服务器停止 32 | Thread.sleep(Integer.MAX_VALUE); 33 | 34 | } catch (Exception e) { 35 | e.printStackTrace(); 36 | } 37 | } 38 | 39 | public static void main(String[] args) { 40 | Server server = new Server(8765); 41 | } 42 | 43 | } 44 | -------------------------------------------------------------------------------- /socket/src/wp/aio/ServerCompletionHandler.java: -------------------------------------------------------------------------------- 1 | package wp.aio; 2 | 3 | import java.nio.ByteBuffer; 4 | import java.nio.channels.AsynchronousSocketChannel; 5 | import java.nio.channels.CompletionHandler; 6 | import java.util.concurrent.ExecutionException; 7 | 8 | public class ServerCompletionHandler implements CompletionHandler { 9 | 10 | @Override 11 | public void completed(AsynchronousSocketChannel asc, Server attachment) { 12 | //当有下一个客户端接入的时候 直接调用Server的accept方法,这样反复执行下去,保证多个客户端都可以阻塞 13 | attachment.assc.accept(attachment, this); 14 | read(asc); 15 | } 16 | 17 | private void read(final AsynchronousSocketChannel asc) { 18 | //读取数据 19 | ByteBuffer buf = ByteBuffer.allocate(1024); 20 | asc.read(buf, buf, new CompletionHandler() { 21 | @Override 22 | public void completed(Integer resultSize, ByteBuffer attachment) { 23 | //进行读取之后,重置标识位 24 | attachment.flip(); 25 | //获得读取的字节数 26 | System.out.println("Server -> " + "收到客户端的数据长度为:" + resultSize); 27 | //获取读取的数据 28 | String resultData = new String(attachment.array()).trim(); 29 | System.out.println("Server -> " + "收到客户端的数据信息为:" + resultData); 30 | String response = "服务器响应, 收到了客户端发来的数据: " + resultData; 31 | write(asc, response); 32 | } 33 | @Override 34 | public void failed(Throwable exc, ByteBuffer attachment) { 35 | exc.printStackTrace(); 36 | } 37 | }); 38 | } 39 | 40 | private void write(AsynchronousSocketChannel asc, String response) { 41 | try { 42 | ByteBuffer buf = ByteBuffer.allocate(1024); 43 | buf.put(response.getBytes()); 44 | buf.flip(); 45 | asc.write(buf).get(); 46 | } catch (InterruptedException e) { 47 | e.printStackTrace(); 48 | } catch (ExecutionException e) { 49 | e.printStackTrace(); 50 | } 51 | } 52 | 53 | @Override 54 | public void failed(Throwable exc, Server attachment) { 55 | exc.printStackTrace(); 56 | } 57 | 58 | } 59 | -------------------------------------------------------------------------------- /socket/src/wp/bio/Client.java: -------------------------------------------------------------------------------- 1 | package wp.bio; 2 | 3 | import java.io.BufferedReader; 4 | import java.io.IOException; 5 | import java.io.InputStreamReader; 6 | import java.io.PrintWriter; 7 | import java.net.Socket; 8 | import java.util.Scanner; 9 | 10 | public class Client { 11 | 12 | final static String ADDRESS = "127.0.0.1"; 13 | final static int PORT = 8765; 14 | 15 | public static void main(String[] args) { 16 | 17 | Socket socket = null; 18 | BufferedReader in = null; 19 | PrintWriter out = null; 20 | try { 21 | socket = new Socket(ADDRESS, PORT); 22 | in = new BufferedReader(new InputStreamReader(socket.getInputStream())); 23 | out = new PrintWriter(socket.getOutputStream(), true); 24 | 25 | String userinfo = ""; 26 | Scanner scanner = new Scanner(System.in); 27 | 28 | System.out.println("请输入用户名:"); 29 | userinfo += scanner.next(); 30 | userinfo += ":"; 31 | System.out.println("请输入密码:"); 32 | userinfo += scanner.next(); 33 | 34 | out.println(userinfo); 35 | //向服务器端发送数据 36 | //每进行一次out.println,就会收到一次服务器的响应。 37 | // out.println("接收到客户端的请求数据..."); 38 | // System.out.println("Client: " + in.readLine()); 39 | // 40 | // out.println("接收到客户端的请求数据1111..."); 41 | // System.out.println("Client: " + in.readLine()); 42 | // 43 | // Thread.sleep(3000); 44 | // out.println("接收到客户端的请求数据..."); 45 | // out.println("接收到客户端的请求数据1111..."); 46 | 47 | String response = in.readLine(); 48 | System.out.println("Client: " + response); 49 | 50 | } catch (Exception e) { 51 | e.printStackTrace(); 52 | } finally { 53 | if (in != null) { 54 | try { 55 | in.close(); 56 | } catch (IOException e) { 57 | e.printStackTrace(); 58 | } 59 | } 60 | if (out != null) { 61 | try { 62 | out.close(); 63 | } catch (Exception e) { 64 | e.printStackTrace(); 65 | } 66 | } 67 | if (socket != null) { 68 | try { 69 | socket.close(); 70 | } catch (IOException e) { 71 | e.printStackTrace(); 72 | } 73 | } 74 | socket = null; 75 | } 76 | } 77 | } 78 | -------------------------------------------------------------------------------- /socket/src/wp/bio/Server.java: -------------------------------------------------------------------------------- 1 | package wp.bio; 2 | 3 | import java.io.IOException; 4 | import java.net.ServerSocket; 5 | import java.net.Socket; 6 | 7 | 8 | public class Server { 9 | 10 | final static int PROT = 8765; 11 | 12 | public static void main(String[] args) { 13 | 14 | ServerSocket server = null; 15 | try { 16 | server = new ServerSocket(PROT); 17 | System.out.println(" server start .. "); 18 | //进行阻塞 19 | while (true) {//这里应该循环,使得可以接受多个客户端的请求。 20 | Socket socket = server.accept(); 21 | //新建一个线程执行客户端的任务 22 | new Thread(new ServerHandler(socket)).start(); 23 | } 24 | } catch (Exception e) { 25 | e.printStackTrace(); 26 | } finally { 27 | if (server != null) { 28 | try { 29 | server.close(); 30 | } catch (IOException e) { 31 | e.printStackTrace(); 32 | } 33 | } 34 | server = null; 35 | } 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /socket/src/wp/bio/ServerHandler.java: -------------------------------------------------------------------------------- 1 | package wp.bio; 2 | 3 | import java.io.BufferedReader; 4 | import java.io.IOException; 5 | import java.io.InputStreamReader; 6 | import java.io.PrintWriter; 7 | import java.net.Socket; 8 | import java.util.HashMap; 9 | 10 | public class ServerHandler implements Runnable { 11 | 12 | private Socket socket; 13 | 14 | public ServerHandler(Socket socket) { 15 | this.socket = socket; 16 | } 17 | 18 | HashMap users = new HashMap<>(); 19 | 20 | { 21 | users.put("wanwanpp", "980325"); 22 | } 23 | 24 | @Override 25 | public void run() { 26 | BufferedReader in = null; 27 | PrintWriter out = null; 28 | try { 29 | in = new BufferedReader(new InputStreamReader(this.socket.getInputStream())); 30 | out = new PrintWriter(this.socket.getOutputStream(), true); 31 | String body = in.readLine(); 32 | // wanwanpp:980325 33 | String[] nameAndPwd = body.split(":"); 34 | String user = nameAndPwd[0]; 35 | String pwd = nameAndPwd[1]; 36 | boolean hasUser = users.containsKey(user); 37 | if (!hasUser) { 38 | out.println("服务器:认证失败,不存在用户名为“" + user + "“的用户。"); 39 | } else { 40 | String pwdFromDb = users.get(user); 41 | if (pwdFromDb.equals(pwd)) { 42 | out.println("服务器:认证成功。"); 43 | } else { 44 | out.println("服务器:您的密码输入错误。"); 45 | } 46 | } 47 | System.out.println("完成认证,用户名为:" + user + ",密码为:" + pwd); 48 | // while (true) { 49 | // body = in.readLine(); 50 | // if (body == null) break; 51 | // System.out.println("Server :" + body); 52 | // out.println("服务器端回送响的应数据."); 53 | // } 54 | 55 | } catch (Exception e) { 56 | e.printStackTrace(); 57 | } finally { 58 | if (in != null) { 59 | try { 60 | in.close(); 61 | } catch (IOException e) { 62 | e.printStackTrace(); 63 | } 64 | } 65 | if (out != null) { 66 | try { 67 | out.close(); 68 | } catch (Exception e) { 69 | e.printStackTrace(); 70 | } 71 | } 72 | if (socket != null) { 73 | try { 74 | socket.close(); 75 | } catch (IOException e) { 76 | e.printStackTrace(); 77 | } 78 | } 79 | socket = null; 80 | } 81 | } 82 | } 83 | -------------------------------------------------------------------------------- /socket/src/wp/bio2/Client.java: -------------------------------------------------------------------------------- 1 | package wp.bio2; 2 | 3 | import java.io.BufferedReader; 4 | import java.io.InputStreamReader; 5 | import java.io.PrintWriter; 6 | import java.net.Socket; 7 | 8 | public class Client { 9 | 10 | final static String ADDRESS = "127.0.0.1"; 11 | final static int PORT =8765; 12 | 13 | public static void main(String[] args) { 14 | Socket socket = null; 15 | BufferedReader in = null; 16 | PrintWriter out = null; 17 | try { 18 | socket = new Socket(ADDRESS, PORT); 19 | in = new BufferedReader(new InputStreamReader(socket.getInputStream())); 20 | out = new PrintWriter(socket.getOutputStream(), true); 21 | out.println("Client request"); 22 | 23 | String response = in.readLine(); 24 | System.out.println("Client:" + response); 25 | } catch (Exception e) { 26 | e.printStackTrace(); 27 | } finally { 28 | if(in != null){ 29 | try { 30 | in.close(); 31 | } catch (Exception e1) { 32 | e1.printStackTrace(); 33 | } 34 | } 35 | if(out != null){ 36 | try { 37 | out.close(); 38 | } catch (Exception e2) { 39 | e2.printStackTrace(); 40 | } 41 | } 42 | if(socket != null){ 43 | try { 44 | socket.close(); 45 | } catch (Exception e3) { 46 | e3.printStackTrace(); 47 | } 48 | } 49 | socket = null; 50 | } 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /socket/src/wp/bio2/HandlerExecutorPool.java: -------------------------------------------------------------------------------- 1 | package wp.bio2; 2 | 3 | import java.util.concurrent.ArrayBlockingQueue; 4 | import java.util.concurrent.ExecutorService; 5 | import java.util.concurrent.ThreadPoolExecutor; 6 | import java.util.concurrent.TimeUnit; 7 | 8 | public class HandlerExecutorPool { 9 | 10 | private ExecutorService executor; 11 | public HandlerExecutorPool(int maxPoolSize, int queueSize){ 12 | this.executor = new ThreadPoolExecutor( 13 | Runtime.getRuntime().availableProcessors(), 14 | maxPoolSize, 15 | 120L, //当线程数量大于corepoolsize时,若线程空闲时间大于keepAliveTime,则会被回收。 16 | TimeUnit.SECONDS, 17 | new ArrayBlockingQueue(queueSize)); 18 | } 19 | 20 | public void execute(Runnable task){ 21 | this.executor.execute(task); 22 | } 23 | 24 | 25 | 26 | } 27 | -------------------------------------------------------------------------------- /socket/src/wp/bio2/Server.java: -------------------------------------------------------------------------------- 1 | package wp.bio2; 2 | 3 | import java.io.BufferedReader; 4 | import java.io.PrintWriter; 5 | import java.net.ServerSocket; 6 | import java.net.Socket; 7 | 8 | public class Server { 9 | 10 | final static int PORT = 8765; 11 | 12 | public static void main(String[] args) { 13 | ServerSocket server = null; 14 | BufferedReader in = null; 15 | PrintWriter out = null; 16 | try { 17 | server = new ServerSocket(PORT); 18 | System.out.println("server start"); 19 | Socket socket = null; 20 | //内部封装了 一个ThreadPoolExecutor对象 21 | HandlerExecutorPool executorPool = new HandlerExecutorPool(50, 1000); 22 | //使用线程池节省线程的创建与销毁带来的资源浪费。 23 | while(true){ 24 | socket = server.accept(); 25 | executorPool.execute(new ServerHandler(socket)); 26 | } 27 | } catch (Exception e) { 28 | e.printStackTrace(); 29 | } finally { 30 | if(in != null){ 31 | try { 32 | in.close(); 33 | } catch (Exception e1) { 34 | e1.printStackTrace(); 35 | } 36 | } 37 | if(out != null){ 38 | try { 39 | out.close(); 40 | } catch (Exception e2) { 41 | e2.printStackTrace(); 42 | } 43 | } 44 | if(server != null){ 45 | try { 46 | server.close(); 47 | } catch (Exception e3) { 48 | e3.printStackTrace(); 49 | } 50 | } 51 | server = null; 52 | } 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /socket/src/wp/bio2/ServerHandler.java: -------------------------------------------------------------------------------- 1 | package wp.bio2; 2 | 3 | import java.io.BufferedReader; 4 | import java.io.InputStreamReader; 5 | import java.io.PrintWriter; 6 | import java.net.Socket; 7 | 8 | public class ServerHandler implements Runnable { 9 | 10 | private Socket socket; 11 | public ServerHandler (Socket socket){ 12 | this.socket = socket; 13 | } 14 | 15 | @Override 16 | public void run() { 17 | BufferedReader in = null; 18 | PrintWriter out = null; 19 | try { 20 | in = new BufferedReader(new InputStreamReader(this.socket.getInputStream())); 21 | out = new PrintWriter(this.socket.getOutputStream(), true); 22 | String body = null; 23 | while(true){ 24 | body = in.readLine(); 25 | if(body == null) break; 26 | System.out.println("Server:" + body); 27 | out.println("Server response"); 28 | } 29 | } catch (Exception e) { 30 | e.printStackTrace(); 31 | } finally { 32 | if(in != null){ 33 | try { 34 | in.close(); 35 | } catch (Exception e1) { 36 | e1.printStackTrace(); 37 | } 38 | } 39 | if(out != null){ 40 | try { 41 | out.close(); 42 | } catch (Exception e2) { 43 | e2.printStackTrace(); 44 | } 45 | } 46 | if(socket != null){ 47 | try { 48 | socket.close(); 49 | } catch (Exception e3) { 50 | e3.printStackTrace(); 51 | } 52 | } 53 | socket = null; 54 | } 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /socket/src/wp/nio/Client.java: -------------------------------------------------------------------------------- 1 | package wp.nio; 2 | 3 | import java.io.IOException; 4 | import java.net.InetSocketAddress; 5 | import java.nio.ByteBuffer; 6 | import java.nio.channels.SocketChannel; 7 | import java.util.Scanner; 8 | 9 | public class Client { 10 | 11 | //需要一个Selector 12 | public static void main(String[] args) { 13 | 14 | //创建连接的地址 15 | InetSocketAddress address = new InetSocketAddress("127.0.0.1", 8765); 16 | //声明连接通道 17 | SocketChannel sc = null; 18 | //建立缓冲区 19 | ByteBuffer buf = ByteBuffer.allocate(1024); 20 | ByteBuffer readBuf = ByteBuffer.allocate(1024); 21 | 22 | try { 23 | //打开通道 24 | sc = SocketChannel.open(); 25 | //进行连接 26 | sc.connect(address); 27 | Scanner scanner = new Scanner(System.in); 28 | while (true) { 29 | String str = scanner.next(); 30 | if (str.equals("q")){ 31 | break; 32 | } 33 | buf.put(str.getBytes()); 34 | //对缓冲区进行复位 35 | buf.flip(); 36 | //写出数据 37 | sc.write(buf); 38 | //清空缓冲区数据 39 | buf.clear(); 40 | 41 | // sc.read(readBuf); 42 | // System.out.println(new String(readBuf.array(),"utf-8")); 43 | 44 | sc.read(readBuf); 45 | readBuf.flip(); 46 | //6 根据缓冲区的数据长度创建相应大小的byte数组,接收缓冲区的数据 47 | byte[] byteRead = new byte[readBuf.remaining()]; 48 | //7 接收缓冲区数据 49 | readBuf.get(byteRead); 50 | //8 打印结果 51 | String body = new String(byteRead).trim(); 52 | System.out.println("客户端收到: " + body); 53 | } 54 | } catch (IOException e) { 55 | e.printStackTrace(); 56 | } finally { 57 | if (sc != null) { 58 | try { 59 | sc.close(); 60 | } catch (IOException e) { 61 | e.printStackTrace(); 62 | } 63 | } 64 | } 65 | } 66 | } 67 | -------------------------------------------------------------------------------- /socket/src/wp/nio/Server.java: -------------------------------------------------------------------------------- 1 | package wp.nio; 2 | 3 | import java.io.IOException; 4 | import java.net.InetSocketAddress; 5 | import java.nio.ByteBuffer; 6 | import java.nio.channels.*; 7 | import java.util.Iterator; 8 | 9 | public class Server implements Runnable { 10 | //1 多路复用器(管理所有的通道) 11 | private Selector seletor; 12 | //2 建立缓冲区 13 | private ByteBuffer readBuf = ByteBuffer.allocate(1024); 14 | 15 | //3 16 | private ByteBuffer writeBuf = ByteBuffer.allocate(1024); 17 | 18 | public Server(int port) { 19 | try { 20 | //1 打开路复用器 21 | this.seletor = Selector.open(); 22 | //2 打开服务器通道 23 | ServerSocketChannel ssc = ServerSocketChannel.open(); 24 | //3 设置服务器通道为非阻塞模式 25 | ssc.configureBlocking(false); 26 | //4 绑定地址 27 | ssc.bind(new InetSocketAddress(port)); 28 | //5 把服务器通道注册到多路复用器上,并且监听阻塞事件 29 | ssc.register(this.seletor, SelectionKey.OP_ACCEPT); 30 | this.seletor.keys().forEach(key -> System.out.println("感兴趣的事件:" + Integer.toBinaryString(key.interestOps()) + " 就绪事件:" + key.readyOps())); 31 | System.out.println("Server start, port :" + port); 32 | } catch (IOException e) { 33 | e.printStackTrace(); 34 | } 35 | } 36 | 37 | @Override 38 | public void run() { 39 | while (true) { 40 | try { 41 | //1 必须要让多路复用器开始监听 42 | this.seletor.select(); 43 | System.out.println(this.seletor.keys().size()); 44 | //2 返回多路复用器已经选择的结果集 45 | Iterator keys = this.seletor.selectedKeys().iterator(); 46 | //3 进行遍历 47 | while (keys.hasNext()) { 48 | //4 获取一个选择的元素 49 | SelectionKey key = keys.next(); 50 | //5 用掉后从容器中移除 51 | keys.remove(); 52 | // System.out.println("感兴趣的事件:" + Integer.toBinaryString(key.interestOps()) + " 就绪事件:" + Integer.toBinaryString(key.readyOps())); 53 | //6 如果是有效的 54 | if (key.isValid()) { 55 | //7 如果为阻塞状态 56 | if (key.isAcceptable()) { 57 | this.accept(key); 58 | } 59 | //8 如果为可读状态 60 | if (key.isReadable()) { 61 | this.read(key); 62 | } 63 | //9 写数据 64 | if (key.isWritable()) { 65 | this.write(key); //ssc 66 | } 67 | } 68 | } 69 | } catch (IOException e) { 70 | e.printStackTrace(); 71 | } 72 | } 73 | } 74 | 75 | private void write(SelectionKey key) throws IOException { 76 | SocketChannel sc = (SocketChannel) key.channel(); 77 | System.out.println("进入write"); 78 | writeBuf.clear(); 79 | writeBuf.put("王牌".getBytes()); 80 | //一定要flip。 81 | writeBuf.flip(); 82 | sc.write(writeBuf); 83 | sc.register(this.seletor, SelectionKey.OP_READ); 84 | } 85 | 86 | private void read(SelectionKey key) { 87 | try { 88 | //1 清空缓冲区旧的数据 89 | this.readBuf.clear(); 90 | //2 获取之前注册的socket通道对象 91 | SocketChannel sc = (SocketChannel) key.channel(); 92 | //3 读取数据 93 | int count = sc.read(this.readBuf); 94 | //4 如果没有数据 95 | if (count == -1) { 96 | key.channel().close(); 97 | key.cancel(); 98 | return; 99 | } 100 | //5 有数据则进行读取 读取之前需要进行复位方法(把position 和limit进行复位) 101 | this.readBuf.flip(); 102 | //6 根据缓冲区的数据长度创建相应大小的byte数组,接收缓冲区的数据 103 | byte[] bytes = new byte[this.readBuf.remaining()]; 104 | //7 接收缓冲区数据 105 | this.readBuf.get(bytes); 106 | //8 打印结果 107 | String body = new String(bytes).trim(); 108 | System.out.println("Server : " + body); 109 | sc.register(this.seletor, SelectionKey.OP_READ | SelectionKey.OP_WRITE); 110 | // sc.register(this.seletor, SelectionKey.OP_READ ); 111 | // 9..可以写回给客户端数据 112 | // ByteBuffer bufferResponse = ByteBuffer.allocate(1024).put("王盘".getBytes()); 113 | // bufferResponse.flip(); 114 | // sc.write(bufferResponse); 115 | } catch (IOException e) { 116 | e.printStackTrace(); 117 | } 118 | 119 | } 120 | 121 | private void accept(SelectionKey key) { 122 | try { 123 | //1 获取服务通道 124 | ServerSocketChannel ssc = (ServerSocketChannel) key.channel(); 125 | //2 执行阻塞方法 126 | SocketChannel sc = ssc.accept(); 127 | //3 设置阻塞模式 128 | sc.configureBlocking(false); 129 | //4 注册到多路复用器上,并设置读取标识 130 | sc.register(this.seletor, SelectionKey.OP_READ); 131 | } catch (IOException e) { 132 | e.printStackTrace(); 133 | } 134 | } 135 | 136 | public static void main(String[] args) { 137 | new Thread(new Server(8765)).start(); 138 | ; 139 | } 140 | } 141 | -------------------------------------------------------------------------------- /socket/src/wp/nio/test/TestBuffer.java: -------------------------------------------------------------------------------- 1 | package wp.nio.test; 2 | 3 | import java.nio.IntBuffer; 4 | 5 | public class TestBuffer { 6 | 7 | public static void main(String[] args) { 8 | 9 | // 1 基本操作 10 | //创建指定长度的缓冲区 11 | IntBuffer buf = IntBuffer.allocate(10); 12 | buf.put(13);// position位置:0 - > 1 13 | buf.put(21);// position位置:1 - > 2 14 | buf.put(35);// position位置:2 - > 3 15 | System.out.println("使用flip复位之前:" + buf); 16 | 17 | //把位置复位为0,也就是position位置:3 - > 0 18 | buf.flip(); 19 | System.out.println("使用flip复位:" + buf); 20 | System.out.println("容量为: " + buf.capacity()); //容量一旦初始化后不允许改变(warp方法包裹数组除外) 21 | System.out.println("限制为: " + buf.limit()); //由于只装载了三个元素,所以可读取或者操作的元素为3 则limit=3 22 | 23 | 24 | System.out.println("获取下标为1的元素:" + buf.get(1)); 25 | System.out.println("get(index)方法,position位置不改变:" + buf); 26 | buf.put(1, 4); 27 | System.out.println("put(index, change)方法,position位置不变:" + buf);; 28 | 29 | for (int i = 0; i < buf.limit(); i++) { 30 | //调用get方法会使其缓冲区位置(position)向后递增一位 31 | System.out.print(buf.get() + "\t"); 32 | } 33 | System.out.println("buf对象遍历之后为: " + buf); 34 | 35 | 36 | // 2 wrap方法使用 37 | /** 38 | // wrap方法会包裹一个数组: 一般这种用法不会先初始化缓存对象的长度,因为没有意义,最后还会被wrap所包裹的数组覆盖掉。 39 | // 并且wrap方法修改缓冲区对象的时候,数组本身也会跟着发生变化。 40 | int[] arr = new int[]{1,2,5}; 41 | IntBuffer buf1 = IntBuffer.wrap(arr); 42 | System.out.println(buf1); 43 | 44 | IntBuffer buf2 = IntBuffer.wrap(arr, 0 , 2); 45 | //这样使用表示容量为数组arr的长度,但是可操作的元素只有实际进入缓存区的元素长度 46 | System.out.println(buf2); 47 | */ 48 | 49 | 50 | // 3 其他方法 51 | /** 52 | IntBuffer buf1 = IntBuffer.allocate(10); 53 | int[] arr = new int[]{1,2,5}; 54 | buf1.put(arr); 55 | System.out.println(buf1); 56 | //一种复制方法 57 | IntBuffer buf3 = buf1.duplicate(); 58 | System.out.println(buf3); 59 | 60 | //设置buf1的位置属性 61 | //buf1.position(0); 62 | buf1.flip(); 63 | System.out.println(buf1); 64 | 65 | System.out.println("可读数据为:" + buf1.remaining()); 66 | 67 | int[] arr2 = new int[buf1.remaining()]; 68 | //将缓冲区数据放入arr2数组中去 69 | buf1.get(arr2); 70 | for(int i : arr2){ 71 | System.out.print(Integer.toString(i) + ","); 72 | } 73 | */ 74 | } 75 | } 76 | -------------------------------------------------------------------------------- /socket/src/wp/udp/UDPReceiver.java: -------------------------------------------------------------------------------- 1 | package wp.udp; 2 | 3 | import java.io.IOException; 4 | import java.net.DatagramPacket; 5 | import java.net.DatagramSocket; 6 | import java.net.SocketException; 7 | 8 | /** 9 | * Created by 王萍 on 2017/10/26 0026. 10 | */ 11 | public class UDPReceiver { 12 | 13 | public static void main(String[] args) { 14 | try { 15 | DatagramSocket receiveSocket = new DatagramSocket(10000); 16 | byte buf[] = new byte[1024]; 17 | DatagramPacket receivepPacket = new DatagramPacket(buf, buf.length); 18 | System.out.println("开始接收数据报......"); 19 | while (true) { 20 | receiveSocket.receive(receivepPacket); 21 | String receiveData = new String(receivepPacket.getData(), 0, receivepPacket.getLength()); 22 | String name = receivepPacket.getAddress().getHostName(); 23 | int port = receivepPacket.getPort(); 24 | System.out.println("来自主机:" + name + ",的端口:" + port + "的数据:" + receiveData); 25 | if ("Time".equals(receiveData)) { 26 | byte[] timeMillis = String.valueOf(System.currentTimeMillis()).getBytes(); 27 | System.out.println("send msg : " + String.valueOf(System.currentTimeMillis())); 28 | receiveSocket.send(new DatagramPacket(timeMillis, timeMillis.length, receivepPacket.getAddress(), receivepPacket.getPort())); 29 | } 30 | } 31 | } catch (SocketException e) { 32 | System.out.println("can not open the datagram socket"); 33 | System.exit(1); 34 | } catch (IOException e) { 35 | System.out.println(e.toString()); 36 | } 37 | } 38 | 39 | } -------------------------------------------------------------------------------- /socket/src/wp/udp/UDPSender.java: -------------------------------------------------------------------------------- 1 | package wp.udp; 2 | 3 | import java.io.IOException; 4 | import java.net.DatagramPacket; 5 | import java.net.DatagramSocket; 6 | import java.net.InetAddress; 7 | import java.net.SocketException; 8 | import java.text.SimpleDateFormat; 9 | import java.util.Date; 10 | 11 | /** 12 | * Created by 王萍 on 2017/10/26 0026. 13 | */ 14 | public class UDPSender { 15 | 16 | public static void main(String[] args) { 17 | 18 | try { 19 | DatagramSocket socket = new DatagramSocket(); 20 | String string = "Time"; 21 | byte[] databyte = string.getBytes(); 22 | DatagramPacket packet = new DatagramPacket(databyte, 23 | databyte.length, InetAddress.getByName("127.0.0.1"), 10000); 24 | socket.send(packet); 25 | System.out.println("send the data:" + string); 26 | 27 | DatagramPacket receiveDp = new DatagramPacket(new byte[1024], 1024); 28 | socket.receive(receiveDp); 29 | String response = new String(receiveDp.getData(), 0, receiveDp.getLength()); 30 | String rcvd = "服务器时间为: " + new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date(Long.valueOf(response))); 31 | System.out.println(rcvd); 32 | } catch (SocketException e) { 33 | System.out.println("can not open the datagram socket"); 34 | System.exit(1); 35 | } catch (IOException e) { 36 | System.out.println(e.toString()); 37 | } 38 | } 39 | } -------------------------------------------------------------------------------- /springIOC简单实现/pom.xml: -------------------------------------------------------------------------------- 1 | 3 | 4.0.0 4 | 5 | spring-IOC简单实现 6 | spring-IOC简单实现 7 | 1.0-SNAPSHOT 8 | jar 9 | 10 | spring-IOC简单实现 11 | http://maven.apache.org 12 | 13 | 14 | UTF-8 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | org.jdom 23 | jdom2 24 | 2.0.6 25 | 26 | 27 | 28 | junit 29 | junit 30 | 3.8.1 31 | test 32 | 33 | 34 | 35 | -------------------------------------------------------------------------------- /springIOC简单实现/src/main/java/com.wp/dao/UserDao.java: -------------------------------------------------------------------------------- 1 | package com.wp.dao; 2 | 3 | /** 4 | * Created by 王萍 on 2017/2/10 0010. 5 | */ 6 | public interface UserDao { 7 | void say(); 8 | 9 | 10 | } 11 | -------------------------------------------------------------------------------- /springIOC简单实现/src/main/java/com.wp/dao/impl/UserDaoImpl.java: -------------------------------------------------------------------------------- 1 | package com.wp.dao.impl; 2 | 3 | import com.wp.dao.UserDao; 4 | 5 | /** 6 | * Created by 王萍 on 2017/2/10 0010. 7 | */ 8 | public class UserDaoImpl implements UserDao { 9 | 10 | public void say() { 11 | System.out.println("IOC,你好"); 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /springIOC简单实现/src/main/java/com.wp/ioc/BeanFactory.java: -------------------------------------------------------------------------------- 1 | package com.wp.ioc; 2 | 3 | /** 4 | * Created by 王萍 on 2017/2/10 0010. 5 | */ 6 | public interface BeanFactory { 7 | 8 | public Object getBean(String id); 9 | } 10 | -------------------------------------------------------------------------------- /springIOC简单实现/src/main/java/com.wp/ioc/ClassPathXmlApplicationContext.java: -------------------------------------------------------------------------------- 1 | package com.wp.ioc; 2 | 3 | import java.lang.reflect.Method; 4 | import java.util.List; 5 | import java.util.Map; 6 | import java.util.concurrent.ConcurrentHashMap; 7 | 8 | import org.jdom2.Document; 9 | import org.jdom2.Element; 10 | import org.jdom2.input.SAXBuilder; 11 | 12 | /** 13 | * Created by 王萍 on 2017/2/10 0010. 14 | */ 15 | public class ClassPathXmlApplicationContext implements BeanFactory { 16 | 17 | private static final Map beanMap = new ConcurrentHashMap(); 18 | 19 | public ClassPathXmlApplicationContext(String xmlPath) throws Exception { 20 | SAXBuilder sb = new SAXBuilder(); 21 | // 构造文档对象 22 | 23 | //同级目录下加载 24 | // Document doc = sb.build(this.getClass().getResourceAsStream(xmlPath)); 25 | //从classpath下加载 这里maven项目加载的是resources下面的beans.xml 26 | Document doc = sb.build(this.getClass().getClassLoader().getResourceAsStream(xmlPath)); 27 | // 获取根元素Beans 28 | Element root = doc.getRootElement(); 29 | // 获取子元素bean 30 | List list = root.getChildren("bean"); 31 | // 遍历 32 | for (int i = 0; i < list.size(); i++) { 33 | Element element = list.get(i);// 第i个 34 | // 获取id的值 35 | String id = element.getAttributeValue("id"); 36 | // 获取class的值 37 | String className = element.getAttributeValue("class"); 38 | // 利用反射得到一个真实对象 39 | Object obj = Class.forName(className).newInstance(); 40 | // 存入Map 41 | beanMap.put(id, obj); 42 | List propertyElements = element.getChildren("property"); 43 | for (Element propertyElement : propertyElements) { 44 | // 得到userDao 45 | String propertyName = propertyElement.getAttributeValue("name"); 46 | String beanName = propertyElement.getAttributeValue("ref"); 47 | Object refObject = beanMap.get(beanName); 48 | // 构造一个属性的setter方法 49 | String methodName = "set" 50 | + propertyName.substring(0, 1).toUpperCase() 51 | + propertyName.substring(1); 52 | // 获取指定的方法 53 | //第一个参数为方法名,第二个为userDao的接口的class。 54 | Method method = obj.getClass().getMethod(methodName, 55 | refObject.getClass().getInterfaces()[0]); 56 | method.invoke(obj, refObject); 57 | } 58 | } 59 | } 60 | 61 | public Object getBean(String id) { 62 | return beanMap.get(id); 63 | } 64 | } 65 | -------------------------------------------------------------------------------- /springIOC简单实现/src/main/java/com.wp/ioc/Demo.java: -------------------------------------------------------------------------------- 1 | package com.wp.ioc; 2 | 3 | import com.wp.service.UserService; 4 | 5 | public class Demo { 6 | public static void main(String[] args) throws Exception { 7 | ClassPathXmlApplicationContext ctx = new ClassPathXmlApplicationContext( 8 | "beans.xml"); 9 | UserService userService = (UserService) ctx.getBean("userService"); 10 | userService.say(); 11 | } 12 | } -------------------------------------------------------------------------------- /springIOC简单实现/src/main/java/com.wp/ioc/beans.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /springIOC简单实现/src/main/java/com.wp/service/UserService.java: -------------------------------------------------------------------------------- 1 | package com.wp.service; 2 | 3 | /** 4 | * Created by 王萍 on 2017/2/10 0010. 5 | */ 6 | public interface UserService { 7 | void say(); 8 | } 9 | -------------------------------------------------------------------------------- /springIOC简单实现/src/main/java/com.wp/service/impl/UserServiceImpl.java: -------------------------------------------------------------------------------- 1 | package com.wp.service.impl; 2 | 3 | import com.wp.dao.UserDao; 4 | import com.wp.service.UserService; 5 | 6 | /** 7 | * Created by 王萍 on 2017/2/10 0010. 8 | */ 9 | public class UserServiceImpl implements UserService { 10 | 11 | private UserDao userDao; 12 | 13 | public void setUserDao(UserDao userDao) { 14 | this.userDao = userDao; 15 | } 16 | 17 | public void say() { 18 | userDao.say(); 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /springIOC简单实现/src/main/resources/beans.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /src/com/wp/ArrayList与HashSet比较及Hashcode分析/Demo.java: -------------------------------------------------------------------------------- 1 | package com.wp.ArrayList与HashSet比较及Hashcode分析; 2 | 3 | import java.util.Collection; 4 | import java.util.HashSet; 5 | 6 | /** 7 | * Created by 王萍 on 2017/2/6 0006. 8 | */ 9 | public class Demo { 10 | 11 | /** 12 | * Hashcode的作用参考 http://blog.csdn.net/fenglibing/article/details/8905007 13 | * 14 | * 在散列中找对象,先通过hashcode方法确定对象在哪个的桶里边,桶里边的实例对象有很多,然后需要根据equals方法找到具体对象。 15 | * @param args 16 | */ 17 | 18 | public static void main(String[] args) { 19 | //集合为hashset,存入一个元素会根据hasecode值确定应该存储的空间,并确定这片区域是否 20 | //有相同的元素 21 | //可以自定义HashCode方法,判断Has何从的值是否相等。 22 | Collection collection = new HashSet(); 23 | //arraylist的存储是按照先后顺序,不比较是否有相同元素 24 | // Collection collection = new ArrayList(); 25 | Slave slave1=new Slave(1,1); 26 | Slave slave2=new Slave(5,5); 27 | Slave slave3=new Slave(1,1); 28 | 29 | 30 | collection.add(slave1); 31 | collection.add(slave2); 32 | collection.add(slave3); 33 | collection.add(slave1); 34 | 35 | //此处对slave1实例中的x成员变量进行更改,slave1产生了一个新的Hashcode的值。 36 | //因此,当对其进行remove()操作时,无法找到以前那个存放地址,无法删除对象。 37 | //在内存中一直存在,属于内存泄漏。 38 | 39 | //在 Java 应用程序执行期间,在同一对象上多次调用 hashCode 方法时,必须一致地返回相同的整数,前提是对象上 equals 比较中所用的信息没有被修改 40 | //当equals方法被重写时,通常有必要重写 hashCode 方法,以维护 hashCode 方法的常规协定,该协定声明相等对象必须具有相等的哈希码。 41 | 42 | // Hashcode的作用参考 http://blog.csdn.net/fenglibing/article/details/8905007 43 | 44 | slave1.x=7; 45 | 46 | collection.remove(slave1); 47 | 48 | System.out.println(collection.size()); 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /src/com/wp/ArrayList与HashSet比较及Hashcode分析/HashTest.java: -------------------------------------------------------------------------------- 1 | package com.wp.ArrayList与HashSet比较及Hashcode分析; 2 | 3 | import java.util.HashSet; 4 | import java.util.Set; 5 | 6 | public class HashTest { 7 | private int i; 8 | 9 | public int getI() { 10 | return i; 11 | } 12 | 13 | public void setI(int i) { 14 | this.i = i; 15 | } 16 | 17 | public int hashCode() { 18 | return i % 10; 19 | } 20 | 21 | //若不重写equals方法那么下面HashTest两个实例对象是不相等的。 22 | @Override 23 | public boolean equals(Object o) { 24 | if (this == o) return true; 25 | if (o == null || getClass() != o.getClass()) return false; 26 | 27 | HashTest hashTest = (HashTest) o; 28 | 29 | return i == hashTest.i; 30 | 31 | } 32 | 33 | public final static void main(String[] args) { 34 | HashTest a = new HashTest(); 35 | HashTest b = new HashTest(); 36 | a.setI(1); 37 | b.setI(1); 38 | Set set = new HashSet(); 39 | set.add(a); 40 | set.add(b); 41 | System.out.println(a.hashCode() == b.hashCode()); 42 | System.out.println(a.equals(b)); 43 | System.out.println(set); 44 | System.out.println(set.size()); 45 | } 46 | } -------------------------------------------------------------------------------- /src/com/wp/ArrayList与HashSet比较及Hashcode分析/Reflect.java: -------------------------------------------------------------------------------- 1 | package com.wp.ArrayList与HashSet比较及Hashcode分析; 2 | 3 | import java.io.IOException; 4 | import java.io.InputStream; 5 | import java.util.Collection; 6 | import java.util.Properties; 7 | 8 | /** 9 | * Created by 王萍 on 2017/2/6 0006. 10 | */ 11 | public class Reflect { 12 | public static void main(String[] args) throws IOException, ClassNotFoundException, IllegalAccessException, InstantiationException { 13 | 14 | Properties properties = new Properties(); 15 | //使用文件输入流加载 16 | // InputStream inputStream = new FileInputStream("F:\\IDEA\\j2se深入\\src\\com\\wp\\ArrayList与HashSet比较及Hashcode分析\\config.properties"); 17 | 18 | //使用类加载器进行properties文件加载,类加载器用于加载.class文件,更可以加载普通文件 19 | //该方式是所有文件都从classpath,即根目录进行加载 20 | // InputStream inputStream = Reflect.class.getClassLoader().getResourceAsStream("com/wp/ArrayList与HashSet比较及Hashcode分析/config.properties"); 21 | 22 | //该方式可以从同级目录进行加载 23 | InputStream inputStream = Reflect.class.getResourceAsStream("config.properties"); 24 | 25 | properties.load(inputStream); 26 | String className = properties.getProperty("className"); 27 | inputStream.close(); 28 | 29 | Collection collection = (Collection) Class.forName(className).newInstance(); 30 | Slave slave1 = new Slave(1, 1); 31 | Slave slave2 = new Slave(5, 5); 32 | Slave slave3 = new Slave(1, 1); 33 | 34 | 35 | collection.add(slave1); 36 | collection.add(slave2); 37 | collection.add(slave3); 38 | collection.add(slave1); 39 | 40 | System.out.println(collection.size()); 41 | } 42 | 43 | } 44 | -------------------------------------------------------------------------------- /src/com/wp/ArrayList与HashSet比较及Hashcode分析/Slave.java: -------------------------------------------------------------------------------- 1 | package com.wp.ArrayList与HashSet比较及Hashcode分析; 2 | 3 | /** 4 | * Created by 王萍 on 2017/2/6 0006. 5 | */ 6 | public class Slave { 7 | public int x,y; 8 | 9 | public Slave(int x, int y) { 10 | this.x = x; 11 | this.y = y; 12 | } 13 | 14 | @Override 15 | public boolean equals(Object o) { 16 | if (this == o) return true; 17 | if (o == null || getClass() != o.getClass()) return false; 18 | 19 | Slave slave = (Slave) o; 20 | 21 | if (x != slave.x) return false; 22 | return y == slave.y; 23 | 24 | } 25 | 26 | @Override 27 | public int hashCode() { 28 | int result = x; 29 | result = 31 * result + y; 30 | return result; 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /src/com/wp/ArrayList与HashSet比较及Hashcode分析/config.properties: -------------------------------------------------------------------------------- 1 | className=java.util.ArrayList -------------------------------------------------------------------------------- /src/com/wp/IntegerWrapper.java: -------------------------------------------------------------------------------- 1 | package com.wp; 2 | 3 | /** 4 | * @author 王萍 5 | * @date 2017/12/22 0022 6 | */ 7 | public class IntegerWrapper { 8 | public static void main(String[] args) { 9 | 10 | Integer a = 1; 11 | Integer b = 2; 12 | Integer c = 3; 13 | Integer d = 3; 14 | Integer e = 321; 15 | Integer f = 321; 16 | Long g = 3L; 17 | Long h = 2L; 18 | //'=='两边的c和d都是引用则比较引用是否相等,因为3在-128到127之间,会将Integer对象提前缓存起来 19 | //Integer c = 3;实际上是Integer c = Integer.valueOf(3); valueOf方法会从IntegerCache中返回合适的Integer,即值在-128到127之间的。 20 | //因此c和d都指向缓存的那个Integer。 21 | System.out.println(c==d); //true 22 | System.out.println(e==f); //false 23 | // a+b为表达式,所以比较的是c与a+b的值 24 | System.out.println(c==(a+b)); //true 25 | //先a和b拆箱,然后相加,再装箱为Integer。根据Integer的equals规则比较。 26 | System.out.println(c.equals(a+b));//true 27 | System.out.println(g==(a+b)); //true,比较数值 28 | System.out.println(g.equals(a+b));//false, 比较引用,g为Long,右边a+b装箱后为Integer。 29 | System.out.println(g.equals(a+h));//true 比较引用,g为Long,右边a+b装箱后为Long。 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /src/com/wp/nio/channel/ServerSocketChannelDemo.java: -------------------------------------------------------------------------------- 1 | package com.wp.nio.channel; 2 | 3 | import java.net.InetSocketAddress; 4 | import java.nio.ByteBuffer; 5 | import java.nio.CharBuffer; 6 | import java.nio.channels.ServerSocketChannel; 7 | import java.nio.channels.SocketChannel; 8 | import java.nio.charset.Charset; 9 | import java.nio.charset.CharsetDecoder; 10 | 11 | /** 12 | * @author 王萍 13 | * @date 2018/1/8 0008 14 | */ 15 | public class ServerSocketChannelDemo { 16 | public static void main(String[] args) throws Exception { 17 | ServerSocketChannel serverSocketChannel = ServerSocketChannel.open(); 18 | serverSocketChannel.bind(new InetSocketAddress("localhost", 1234)); 19 | serverSocketChannel.configureBlocking(false); 20 | 21 | while (true) { 22 | //socketChannel.read() socketChannel.write() 23 | SocketChannel socketChannel = serverSocketChannel.accept(); 24 | if (socketChannel != null) { 25 | ByteBuffer byteBuffer = ByteBuffer.allocate(512); 26 | socketChannel.read(byteBuffer); 27 | byteBuffer.flip(); 28 | System.out.println("server received message: " + getString(byteBuffer)); 29 | byteBuffer.clear(); 30 | String message = "server sending message " + System.currentTimeMillis(); 31 | System.out.println("server sends message: " + message); 32 | byteBuffer.put(message.getBytes()); 33 | byteBuffer.flip(); 34 | socketChannel.write(byteBuffer); 35 | break; 36 | } 37 | } 38 | try { 39 | serverSocketChannel.close(); 40 | } catch (Exception e) { 41 | e.printStackTrace(); 42 | } 43 | } 44 | 45 | public static String getString(ByteBuffer buffer) { 46 | Charset charset; 47 | CharsetDecoder decoder; 48 | CharBuffer charBuffer; 49 | try { 50 | charset = Charset.forName("UTF-8"); 51 | decoder = charset.newDecoder(); 52 | charBuffer = decoder.decode(buffer.asReadOnlyBuffer()); 53 | return charBuffer.toString(); 54 | } catch (Exception ex) { 55 | ex.printStackTrace(); 56 | return ""; 57 | } 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /src/com/wp/nio/channel/SocketChannelDemo.java: -------------------------------------------------------------------------------- 1 | package com.wp.nio.channel; 2 | 3 | import java.net.InetSocketAddress; 4 | import java.nio.ByteBuffer; 5 | import java.nio.CharBuffer; 6 | import java.nio.channels.SocketChannel; 7 | import java.nio.charset.Charset; 8 | import java.nio.charset.CharsetDecoder; 9 | 10 | /** 11 | * @author 王萍 12 | * @date 2018/1/8 0008 13 | */ 14 | public class SocketChannelDemo { 15 | public static void main(String[] args) throws Exception { 16 | SocketChannel socketChannel = SocketChannel.open(); 17 | socketChannel.connect(new InetSocketAddress("localhost", 1234)); 18 | String message = "client sending message " + System.currentTimeMillis(); 19 | ByteBuffer byteBuffer = ByteBuffer.allocate(512); 20 | byteBuffer.clear(); 21 | System.out.println("client sends message: " + message); 22 | byteBuffer.put(message.getBytes()); 23 | byteBuffer.flip(); 24 | socketChannel.write(byteBuffer); 25 | 26 | while (true) { 27 | byteBuffer.clear(); 28 | int readBytes = socketChannel.read(byteBuffer); 29 | if (readBytes > 0) { 30 | byteBuffer.flip(); 31 | System.out.println("client receive message: " + getString(byteBuffer)); 32 | break; 33 | } 34 | } 35 | 36 | try { 37 | socketChannel.close(); 38 | } catch (Exception e) { 39 | e.printStackTrace(); 40 | } 41 | } 42 | 43 | public static String getString(ByteBuffer buffer) { 44 | Charset charset; 45 | CharsetDecoder decoder; 46 | CharBuffer charBuffer; 47 | try { 48 | charset = Charset.forName("UTF-8"); 49 | decoder = charset.newDecoder(); 50 | charBuffer = decoder.decode(buffer.asReadOnlyBuffer()); 51 | return charBuffer.toString(); 52 | } catch (Exception ex) { 53 | ex.printStackTrace(); 54 | return ""; 55 | } 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /src/com/wp/string/TestString.java: -------------------------------------------------------------------------------- 1 | package com.wp.string; 2 | 3 | public class TestString { 4 | 5 | // intern方法返回字符串首次出现的实例引用。 6 | public static void main(String[] args) { 7 | String str = "abc"; 8 | String str1 = "abc"; 9 | //str2中的value引用的是"abc"的地址,而不是复制abc的内容到value中 10 | String str2 = new String("abc"); 11 | System.out.println(str == str1); 12 | System.out.println(str1 == "abc"); 13 | System.out.println(str2 == "abc"); 14 | System.out.println(str1 == str2); 15 | System.out.println(str1.equals(str2)); 16 | System.out.println(str1 == str2.intern()); 17 | System.out.println(str2 == str2.intern()); 18 | //String的hashCode方法会根据value生成值。 19 | System.out.println(str1.hashCode() == str2.hashCode()); 20 | 21 | // char[] chars = new char[]{1, 2, 3, 4, 5}; 22 | // char[] newchars = chars; 23 | // System.out.println(System.identityHashCode(chars)); 24 | // System.out.println(System.identityHashCode(newchars)); 25 | 26 | //会生成一个StringBuilder对象,然后调用其append,toString方法。 27 | // String s = str + "abc"; 28 | // 编译器直接编译为 String s = "1234" 29 | // String s = "12" + "34"; 30 | 31 | // 返回true 32 | // final String s = "a"; //注意:这里s用final修饰,相当于一个常量 33 | // String str5 = s + "b"; 34 | // System.out.println(str5 == "ab"); 35 | 36 | // 返回false 37 | // String s = "a"; //注意:这里s没有用final修饰 38 | // String str5 = s + "b"; 39 | // System.out.println(str5 == "ab"); 40 | // String str3 = new String("wanwanpp"); 41 | // System.out.println(str3.intern() == str3); 42 | // 以"wanwanpp"作为构造函数的参数,这时会把"wanwanpp"这个常量串放到String池中 43 | // String str2 = new StringBuilder("wanwanpp").toString(); 44 | // //返回false 45 | // System.out.println(str2.intern() == str2); 46 | //这里"wanwan"和"pp"是分开的。不会把"wanwanpp"这个常量串放到String池中。 47 | // String str5 = new StringBuilder("wanwan").append("pp").toString(); 48 | // //返回true 49 | // System.out.println(str5.intern() == str5); 50 | 51 | //下面java和int是特殊字符,JVM开启,String池中就有这些特殊字符的常量串。因此返回false 52 | // String str4 = new StringBuilder("ja").append("va").toString(); 53 | // System.out.println(str4.intern() == str4); 54 | // String str1 = new StringBuilder("in").append("t").toString(); 55 | // System.out.println(str1.intern() == str1); 56 | 57 | //下面的str1.intern()和str2.intern()都是返回池中的地址,因此相等。返回true 58 | // String str1 = new StringBuilder("in").append("t").toString(); 59 | // String str2 = new StringBuilder("i").append("nt").toString(); 60 | // System.out.println(str1.intern() == str2.intern()); 61 | } 62 | } 63 | -------------------------------------------------------------------------------- /src/com/wp/内省操作javabean/Person.java: -------------------------------------------------------------------------------- 1 | package com.wp.内省操作javabean; 2 | 3 | /** 4 | * Created by 王萍 on 2017/2/6 0006. 5 | */ 6 | public class Person { 7 | 8 | private int age; 9 | private String name; 10 | 11 | public Person(int age, String name) { 12 | this.age = age; 13 | this.name = name; 14 | } 15 | 16 | public int getAge() { 17 | return age; 18 | } 19 | 20 | public void setAge(int age) { 21 | this.age = age; 22 | } 23 | 24 | public String getName() { 25 | return name; 26 | } 27 | 28 | public void setName(String name) { 29 | this.name = name; 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /src/com/wp/内省操作javabean/TestBean.java: -------------------------------------------------------------------------------- 1 | package com.wp.内省操作javabean; 2 | 3 | /** 4 | * Created by 王萍 on 2017/2/6 0006. 5 | */ 6 | public class TestBean { 7 | 8 | private Person person; 9 | 10 | private int num; 11 | 12 | public Person getPerson() { 13 | return person; 14 | } 15 | 16 | public void setPerson(Person person) { 17 | this.person = person; 18 | } 19 | 20 | private String name; 21 | 22 | public TestBean(int num, String name) { 23 | this.num = num; 24 | this.name = name; 25 | } 26 | 27 | public TestBean() { 28 | } 29 | 30 | public int getNum() { 31 | return num; 32 | } 33 | 34 | public void setNum(int num) { 35 | this.num = num; 36 | } 37 | 38 | public String getName() { 39 | return name; 40 | } 41 | 42 | public void setName(String name) { 43 | this.name = name; 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /src/com/wp/内省操作javabean/TestBeanUtils.java: -------------------------------------------------------------------------------- 1 | package com.wp.内省操作javabean; 2 | 3 | import org.apache.commons.beanutils.BeanUtils; 4 | 5 | import java.lang.reflect.InvocationTargetException; 6 | import java.util.HashMap; 7 | import java.util.Map; 8 | 9 | /** 10 | * Created by 王萍 on 2017/2/6 0006. 11 | */ 12 | public class TestBeanUtils { 13 | 14 | public static void main(String[] args) throws IllegalAccessException, NoSuchMethodException, InvocationTargetException { 15 | TestBean testBean = new TestBean(11, "wangping"); 16 | Person person = new Person(18, "wangping"); 17 | testBean.setPerson(person); 18 | 19 | System.out.println(BeanUtils.getProperty(testBean, "person.age")); 20 | 21 | //BeanUtils可以对对象的对象进行级联操作 22 | BeanUtils.setProperty(testBean, "person.age", 28); 23 | System.out.println(BeanUtils.getProperty(testBean, "person.age")); 24 | 25 | //将javabean转为map对象 26 | Map describe = BeanUtils.describe(testBean); 27 | for (String s : describe.keySet()) { 28 | System.out.println(s + " is " + describe.get(s)); 29 | } 30 | 31 | //将map对象填充至javabean实例中。 32 | Map map = new HashMap<>(); 33 | TestBean testBean1 = new TestBean(); 34 | map.put("num", 18); 35 | map.put("name", "wanwanpp"); 36 | BeanUtils.populate(testBean1, map); 37 | System.out.println(BeanUtils.getProperty(testBean1,"name")); 38 | 39 | System.out.println(map); 40 | 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /src/com/wp/内省操作javabean/TestIntrospector.java: -------------------------------------------------------------------------------- 1 | package com.wp.内省操作javabean; 2 | 3 | import org.apache.commons.beanutils.BeanUtils; 4 | import org.apache.commons.beanutils.PropertyUtils; 5 | 6 | import java.beans.BeanInfo; 7 | import java.beans.IntrospectionException; 8 | import java.beans.Introspector; 9 | import java.beans.PropertyDescriptor; 10 | import java.lang.reflect.InvocationTargetException; 11 | import java.lang.reflect.Method; 12 | 13 | /** 14 | * Created by 王萍 on 2017/2/6 0006. 15 | */ 16 | public class TestIntrospector { 17 | 18 | public static void main(String[] args) throws IntrospectionException, InvocationTargetException, IllegalAccessException, NoSuchMethodException { 19 | 20 | TestBean bean = new TestBean(12, "wanwanpp"); 21 | String propertyName = "name"; 22 | 23 | Object value = getProperty(bean, propertyName); 24 | System.out.println(value); 25 | 26 | Object newNum = "haha"; 27 | setProperty(bean, propertyName, newNum); 28 | 29 | //使用此工具包需要引入common-utils和common-loggingjar包,前者依赖于后者 30 | System.out.println(BeanUtils.getProperty(bean, "name")); 31 | //PropertyUtils也可以对javabean进行属性的操作,propertyutils不会进行类型转换,而BeanUtils会。 32 | System.out.println(PropertyUtils.getProperty(bean, "name")); 33 | 34 | System.out.println(bean.getName()); 35 | 36 | 37 | } 38 | 39 | private static void setProperty(TestBean bean, String propertyName, Object newValue) throws IntrospectionException, IllegalAccessException, InvocationTargetException { 40 | 41 | //使用API操作属性。 42 | //propertyName为属性名 43 | PropertyDescriptor descriptor = new PropertyDescriptor(propertyName, bean.getClass()); 44 | //获取指定属性的get方法 45 | Method writeMethod = descriptor.getWriteMethod(); 46 | writeMethod.invoke(bean, newValue); 47 | } 48 | 49 | private static Object getProperty(TestBean bean, String propertyName) throws IntrospectionException, IllegalAccessException, InvocationTargetException { 50 | 51 | // PropertyDescriptor descriptor = new PropertyDescriptor(propertyName,bean.getClass()); 52 | // Method readMethod = descriptor.getReadMethod(); 53 | // return readMethod.invoke(bean); 54 | 55 | Object o = null; 56 | //获取JavaBean的信息。 57 | BeanInfo beanInfo = Introspector.getBeanInfo(bean.getClass()); 58 | //这里面只提供了返回所有属性信息的方法,无法返回具体哪一个属性的信息 59 | PropertyDescriptor[] propertyDescriptors = beanInfo.getPropertyDescriptors(); 60 | //使用迭代获取特定的属性信息 61 | for (PropertyDescriptor propertyDescriptor : propertyDescriptors) { 62 | if (propertyDescriptor.getName().equals(propertyName)) { 63 | Method readMethod = propertyDescriptor.getReadMethod(); 64 | o = readMethod.invoke(bean); 65 | break; 66 | } 67 | } 68 | return o; 69 | } 70 | } 71 | -------------------------------------------------------------------------------- /src/com/wp/可变参数/VariableParameter.java: -------------------------------------------------------------------------------- 1 | package com.wp.可变参数; 2 | 3 | /** 4 | * Created by 王萍 on 2017/2/5 0005. 5 | */ 6 | public class VariableParameter { 7 | 8 | /** 9 | * since 1.5 10 | * @param args 11 | */ 12 | public static void main(String[] args) { 13 | 14 | System.out.println(add(3,5)); 15 | System.out.println(add(1,2,3,4,5)); 16 | } 17 | 18 | //可变参数使用...表示 19 | public static int add(int origin,int...args){ 20 | int sum = origin; 21 | /** 22 | * 增强for循环 23 | */ 24 | for (int arg:args){ 25 | sum+=arg; 26 | } 27 | return sum; 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /src/com/wp/回调/callback/CSCallBack.java: -------------------------------------------------------------------------------- 1 | package com.wp.回调.callback; 2 | 3 | public interface CSCallBack { 4 | void process(String status); 5 | } -------------------------------------------------------------------------------- /src/com/wp/回调/callback/CallBackTest.java: -------------------------------------------------------------------------------- 1 | package com.wp.回调.callback; 2 | 3 | public class CallBackTest { 4 | public static void main(String[] args) { 5 | Server server = new Server(); 6 | Client client = new Client(server); 7 | 8 | client.sendMsg("Server,Hello~"); 9 | } 10 | } -------------------------------------------------------------------------------- /src/com/wp/回调/callback/Client.java: -------------------------------------------------------------------------------- 1 | package com.wp.回调.callback; 2 | 3 | public class Client implements CSCallBack { 4 | 5 | private Server server; 6 | 7 | public Client(Server server) { 8 | this.server = server; 9 | } 10 | 11 | public void sendMsg(final String msg){ 12 | System.out.println("客户端:发送的消息为:" + msg); 13 | new Thread(new Runnable() { 14 | @Override 15 | public void run() { 16 | server.getClientMsg(Client.this,msg); 17 | } 18 | }).start(); 19 | System.out.println("客户端:异步发送成功"); 20 | } 21 | 22 | @Override 23 | public void process(String status) { 24 | System.out.println("客户端:服务端回调状态为:" + status); 25 | } 26 | } -------------------------------------------------------------------------------- /src/com/wp/回调/callback/Server.java: -------------------------------------------------------------------------------- 1 | package com.wp.回调.callback; 2 | 3 | public class Server { 4 | 5 | public void getClientMsg(CSCallBack csCallBack , String msg) { 6 | System.out.println("服务端:服务端接收到客户端发送的消息为:" + msg); 7 | 8 | // 模拟服务端需要对数据处理 9 | try { 10 | Thread.sleep(5 * 1000); 11 | } catch (InterruptedException e) { 12 | e.printStackTrace(); 13 | } 14 | System.out.println("服务端:数据处理成功,返回成功状态 200"); 15 | String status = "200"; 16 | csCallBack.process(status); 17 | } 18 | } -------------------------------------------------------------------------------- /src/com/wp/回调/callback2/GuavaFuture.java: -------------------------------------------------------------------------------- 1 | package com.wp.回调.callback2; 2 | 3 | import com.google.common.util.concurrent.*; 4 | 5 | import java.util.concurrent.Callable; 6 | import java.util.concurrent.ExecutorService; 7 | import java.util.concurrent.Executors; 8 | 9 | /** 10 | * Guava中回调的使用 11 | */ 12 | public class GuavaFuture { 13 | public static void main(String[] args) { 14 | ExecutorService executor = Executors.newFixedThreadPool(1); 15 | 16 | // 使用guava提供的MoreExecutors工具类包装原始的线程池 17 | ListeningExecutorService listeningExecutor = MoreExecutors.listeningDecorator(executor); 18 | //向线程池中提交一个任务后,将会返回一个可监听的Future,该Future由Guava框架提供 19 | ListenableFuture lf = listeningExecutor.submit(new Callable() { 20 | 21 | @Override 22 | public String call() throws Exception { 23 | System.out.println("task started!"); 24 | //模拟耗时操作 25 | Thread.sleep(3000); 26 | System.out.println("task finished!"); 27 | return "hello"; 28 | } 29 | }); 30 | //添加回调,回调由executor中的线程触发,但也可以指定一个新的线程 31 | Futures.addCallback(lf, new FutureCallback() { 32 | 33 | //耗时任务执行失败后回调该方法 34 | @Override 35 | public void onFailure(Throwable t) { 36 | System.out.println("failure"); 37 | } 38 | 39 | //耗时任务执行成功后回调该方法 40 | @Override 41 | public void onSuccess(String s) { 42 | System.out.println("success " + s); 43 | } 44 | }); 45 | 46 | //主线程可以继续做其他的工作 47 | System.out.println("main thread is running"); 48 | } 49 | } -------------------------------------------------------------------------------- /src/com/wp/回调/callback2/JavaFuture.java: -------------------------------------------------------------------------------- 1 | package com.wp.回调.callback2; 2 | 3 | import java.util.concurrent.*; 4 | 5 | /** 6 | * jdk1.8以前future的get()需要一个线程去阻塞等待,或者做一些其他的事然后轮询是否已经完成任务(isDone方法)。 7 | * 并不能做到真正的回调,即做好了任务就通知你。 8 | */ 9 | public class JavaFuture { 10 | public static void main(String[] args) throws Throwable, ExecutionException { 11 | ExecutorService executor = Executors.newFixedThreadPool(1); 12 | Future f = executor.submit(new Callable() { 13 | 14 | @Override 15 | public String call() throws Exception { 16 | System.out.println("task started!"); 17 | Thread.sleep(3000); 18 | System.out.println("task finished!"); 19 | return "hello"; 20 | } 21 | }); 22 | 23 | System.out.println(f.isDone()); 24 | //此处阻塞main线程 25 | System.out.println(f.get()); 26 | System.out.println("main thread is blocked"); 27 | } 28 | } -------------------------------------------------------------------------------- /src/com/wp/回调/callback2/JavaPromise.java: -------------------------------------------------------------------------------- 1 | package com.wp.回调.callback2; 2 | 3 | import java.util.concurrent.CompletableFuture; 4 | import java.util.concurrent.ExecutionException; 5 | import java.util.concurrent.ExecutorService; 6 | import java.util.concurrent.Executors; 7 | import java.util.function.Supplier; 8 | 9 | public class JavaPromise { 10 | public static void main(String[] args) throws Throwable, ExecutionException { 11 | // 两个线程的线程池 12 | ExecutorService executor = Executors.newFixedThreadPool(2); 13 | 14 | CompletableFuture future = CompletableFuture.supplyAsync(new Supplier() { 15 | @Override 16 | public String get() { 17 | System.out.println("task started!"); 18 | try { 19 | //模拟耗时操作 20 | Thread.sleep(2000); 21 | } catch (InterruptedException e) { 22 | e.printStackTrace(); 23 | } 24 | return "task finished!"; 25 | } 26 | }, executor); 27 | 28 | //采用lambada的实现方式 29 | future.thenAccept(e -> System.out.println(e + " ok")); 30 | System.out.println("main thread is running"); 31 | } 32 | } -------------------------------------------------------------------------------- /src/com/wp/枚举/EnumTest.java: -------------------------------------------------------------------------------- 1 | package com.wp.枚举; 2 | 3 | /** 4 | * 枚举功能测试 5 | */ 6 | public class EnumTest { 7 | 8 | public static void main(String[] args) { 9 | 10 | //使用普通JAVA类模拟枚举的应用 11 | WeekDate weekDate = WeekDate.MON; //获得一个枚举对象 12 | //调用枚举中提供的方法 13 | System.out.println(weekDate.nextDay()); 14 | System.out.println(weekDate.preDay()); 15 | System.out.println(weekDate.getName()); 16 | //获得枚举成员所在枚举成员列表中的位置 17 | System.out.println(weekDate.getOrdinal()); 18 | //调用某一个枚举成员的方法 19 | System.out.println(WeekDate.values()[0].preDay()); 20 | System.out.println("---------------遍历枚举成员,普通JAVA类模拟--------------------------"); 21 | for (WeekDate weekDate2 : WeekDate.values()) { 22 | System.out.println(weekDate2); 23 | } 24 | 25 | System.out.println("\n=================================================================\n"); 26 | 27 | //使用JDK中提供的枚举特性功能应用 28 | WeekDateEnum weekDateEnum = WeekDateEnum.MON; //获得一个枚举对象 29 | System.out.println(WeekDate.values().length); //获得枚举成员数量 30 | System.out.println(weekDateEnum.name()); //获得枚举的字符串名称 31 | System.out.println(weekDateEnum.toString()); //打印枚举对象,已重写toString方法,默认打印枚举的名称 32 | System.out.println(weekDateEnum.nextDay().ordinal()); //枚举成员列表中的位置 33 | System.out.println(WeekDateEnum.valueOf("FRI").nextDay().ordinal()); 34 | System.out.println("---------------遍历枚举成员,使用JDK的枚举特性-------------------------"); 35 | for (WeekDateEnum enumDemo : WeekDateEnum.values()) { 36 | System.out.println(enumDemo); 37 | } 38 | 39 | } 40 | 41 | } -------------------------------------------------------------------------------- /src/com/wp/枚举/WeekDate.java: -------------------------------------------------------------------------------- 1 | package com.wp.枚举; 2 | 3 | import java.util.HashMap; 4 | import java.util.Map; 5 | 6 | /** 7 | * 模拟星期中的表示的天,每个星期天都表示一个对象 8 | * 1、类中的每一个枚举成员都是该类的一个实例对象 9 | * 2、构造函数私有化 10 | * 3、提供操作枚举成员的抽象方法和静态方法 11 | */ 12 | public abstract class WeekDate { 13 | 14 | /** 15 | * 星期一 16 | */ 17 | public static final WeekDate MON = new WeekDate("MON",0) { //匿名子类 18 | 19 | @Override 20 | public WeekDate nextDay() { 21 | return TUES; 22 | } 23 | 24 | @Override 25 | public WeekDate preDay() { 26 | return WEDNES; 27 | } 28 | 29 | @Override 30 | public String toString() { 31 | return "WeekDate.MON"; 32 | } 33 | 34 | }; 35 | 36 | /** 37 | * 星期二 38 | */ 39 | public static final WeekDate TUES = new WeekDate("TUES",1) { 40 | 41 | @Override 42 | public WeekDate nextDay() { 43 | return WEDNES; 44 | } 45 | 46 | @Override 47 | public WeekDate preDay() { 48 | return MON; 49 | } 50 | 51 | @Override 52 | public String toString() { 53 | return "WeekDate.TUES"; 54 | } 55 | 56 | }; 57 | 58 | /** 59 | * 星期三 60 | */ 61 | public static final WeekDate WEDNES = new WeekDate("WEDNES",2) { 62 | 63 | @Override 64 | public WeekDate nextDay() { 65 | return MON; 66 | } 67 | 68 | @Override 69 | public WeekDate preDay() { 70 | return TUES; 71 | } 72 | 73 | @Override 74 | public String toString() { 75 | return "WeekDate.WEDNES"; 76 | } 77 | 78 | }; 79 | 80 | private static Map valueMap = new HashMap(); 81 | 82 | /** 83 | * 枚举名称 84 | */ 85 | private final String name; 86 | 87 | /** 88 | * 枚举成员的顺序 89 | */ 90 | private final int ordinal; 91 | 92 | private WeekDate(String name,int ordinal) { 93 | this.name = name; 94 | this.ordinal = ordinal; 95 | } 96 | 97 | /** 98 | * 保存枚举成员 99 | */ 100 | private static WeekDate[] values = { 101 | MON,TUES,WEDNES 102 | }; 103 | 104 | //初始化 105 | static { 106 | valueMap.put("MON", values[0]); 107 | valueMap.put("TUES", values[1]); 108 | valueMap.put("WEDNES", values[2]); 109 | } 110 | 111 | /** 112 | * 下一天 113 | * @return 114 | */ 115 | public abstract WeekDate nextDay(); 116 | 117 | /** 118 | * 前一天 119 | * @return 120 | */ 121 | public abstract WeekDate preDay(); 122 | 123 | /** 124 | * 枚举中的所有成员 125 | * @return 126 | */ 127 | public static WeekDate[] values() { 128 | return values; 129 | } 130 | 131 | /** 132 | * 将一个字符串转换成一个枚举成员对象 133 | * @param name 枚举名称 134 | * @return 枚举对象 135 | */ 136 | public static WeekDate valueOf(String name) { 137 | if (name.equalsIgnoreCase("MON")) { 138 | return MON; 139 | } else if (name.equalsIgnoreCase("TUES")) { 140 | return TUES; 141 | } else if (name.equalsIgnoreCase("WEDES")) { 142 | return WEDNES; 143 | }else { 144 | throw new IllegalArgumentException("找不到" + name + "枚举类型!"); 145 | } 146 | } 147 | 148 | /** 149 | * 优化字符串转枚举对象 150 | * @param name 枚举名称 151 | * @return 枚举对象 152 | */ 153 | public static WeekDate valueOf_2(String name) { 154 | WeekDate value = valueMap.get(name.toUpperCase()); 155 | if (value == null) { 156 | throw new IllegalArgumentException("找不到" + name + "枚举类型!"); 157 | } 158 | return value; 159 | } 160 | 161 | public String getName() { 162 | return name; 163 | } 164 | 165 | public int getOrdinal() { 166 | return ordinal; 167 | } 168 | 169 | /** 170 | * 下一天 171 | * @return 172 | */ 173 | /*public String nextDay() { 174 | if(this == MON) { 175 | return "TUES"; 176 | } else if (this == TUES) { 177 | return "WEDNES"; 178 | } else if (this == WEDNES) { 179 | return "THURS"; 180 | } else if (this == THURS) { 181 | return "FRI"; 182 | } else if (this == FRI) { 183 | return "SATUR"; 184 | } else if (this == SATUR) { 185 | return "SUN"; 186 | } else { 187 | return "MON"; 188 | } 189 | }*/ 190 | 191 | /** 192 | * 前一天 193 | */ 194 | /*public String preDay() { 195 | if (this == MON) { 196 | //.... 197 | } else if (...).... 198 | }*/ 199 | 200 | } 201 | -------------------------------------------------------------------------------- /src/com/wp/枚举/WeekDateEnum.java: -------------------------------------------------------------------------------- 1 | package com.wp.枚举; 2 | 3 | /** 4 | * 枚举的应用 5 | * 存储每周中的天份 6 | */ 7 | public enum WeekDateEnum { 8 | 9 | /** 10 | * 枚举中基本元素为名字和顺序 11 | * 当枚举中只有一个成员时,可以当做单例的一种实现方式。 12 | */ 13 | MON(1) { 14 | @Override 15 | public WeekDateEnum nextDay() { 16 | return TUES; 17 | } 18 | 19 | @Override 20 | public WeekDateEnum preDay() { 21 | return SUN; 22 | } 23 | 24 | }, TUES { 25 | @Override 26 | public WeekDateEnum nextDay() { 27 | return WEDNES; 28 | } 29 | 30 | @Override 31 | public WeekDateEnum preDay() { 32 | return MON; 33 | } 34 | 35 | }, WEDNES { 36 | @Override 37 | public WeekDateEnum nextDay() { 38 | return THURS; 39 | } 40 | 41 | @Override 42 | public WeekDateEnum preDay() { 43 | return TUES; 44 | } 45 | 46 | }, THURS { 47 | @Override 48 | public WeekDateEnum nextDay() { 49 | return FRI; 50 | } 51 | 52 | @Override 53 | public WeekDateEnum preDay() { 54 | return WEDNES; 55 | } 56 | 57 | }, FRI { 58 | @Override 59 | public WeekDateEnum nextDay() { 60 | return SATUR; 61 | } 62 | 63 | @Override 64 | public WeekDateEnum preDay() { 65 | return THURS; 66 | } 67 | 68 | }, SATUR { 69 | @Override 70 | public WeekDateEnum nextDay() { 71 | return SATUR; 72 | } 73 | 74 | @Override 75 | public WeekDateEnum preDay() { 76 | return FRI; 77 | } 78 | 79 | }, SUN { 80 | @Override 81 | public WeekDateEnum nextDay() { 82 | return SATUR; 83 | } 84 | 85 | @Override 86 | public WeekDateEnum preDay() { 87 | return MON; 88 | } 89 | 90 | }; 91 | 92 | private WeekDateEnum() { 93 | System.out.println("first"); 94 | } 95 | 96 | private WeekDateEnum(int i){ 97 | System.out.println("second"); 98 | } 99 | 100 | /** 101 | * 下一天 102 | * 103 | * @return 104 | */ 105 | public abstract WeekDateEnum nextDay(); 106 | 107 | /** 108 | * 前一天 109 | * 110 | * @return 111 | */ 112 | public abstract WeekDateEnum preDay(); 113 | 114 | /** 115 | * 枚举对象公共的toString方法,可以在case块中反馈自己想要返回的信息 116 | */ 117 | public String toString() { 118 | switch (this) { 119 | case MON: 120 | return "WeekDateEnum.MON"; 121 | case TUES: 122 | return "WeekDateEnum.TUES"; 123 | case WEDNES: 124 | return "WeekDateEnum.WEDNES"; 125 | case THURS: 126 | return "WeekDateEnum.THURS"; 127 | case FRI: 128 | return "WeekDateEnum.FRI"; 129 | case SATUR: 130 | return "WeekDateEnum.SATUR"; 131 | case SUN: 132 | return "WeekDateEnum.SUN"; 133 | default: 134 | return null; 135 | } 136 | } 137 | } 138 | -------------------------------------------------------------------------------- /src/com/wp/泛型/泛型擦除/反射观察泛型擦除.java: -------------------------------------------------------------------------------- 1 | package com.wp.泛型.泛型擦除; 2 | 3 | import java.lang.reflect.InvocationTargetException; 4 | import java.lang.reflect.Method; 5 | import java.util.ArrayList; 6 | import java.util.List; 7 | 8 | /** 9 | * @author 王萍 10 | * @date 2017/12/3 0003 11 | */ 12 | //利用反射观察泛型擦除 13 | public class 反射观察泛型擦除 { 14 | 15 | public static void main(String[] args) throws NoSuchMethodException, InvocationTargetException, IllegalAccessException { 16 | List integerList = new ArrayList<>(); 17 | integerList.add(12); 18 | Method add = integerList.getClass().getMethod("add", Object.class); 19 | add.invoke(integerList, "123abc"); 20 | add.invoke(integerList, false); 21 | add.invoke(integerList, new Object()); 22 | 23 | for (int i = 0; i < integerList.size(); i++) { 24 | System.out.println(integerList.get(i)); 25 | } 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /src/com/wp/泛型/泛型擦除/比较字节码.java: -------------------------------------------------------------------------------- 1 | package com.wp.泛型.泛型擦除; 2 | 3 | import java.util.HashMap; 4 | 5 | /** 6 | * @author 王萍 7 | * @date 2017/12/3 0003 8 | */ 9 | public class 比较字节码 { 10 | public static void main(String[] args) { 11 | 12 | HashMap hashMap = new HashMap<>(); 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /src/com/wp/类加载器/FileSystemClassLoader.java: -------------------------------------------------------------------------------- 1 | package com.wp.类加载器; 2 | 3 | import java.io.FileInputStream; 4 | import java.io.FileNotFoundException; 5 | import java.io.IOException; 6 | 7 | /** 8 | * Created by 王萍 on 2017/10/23 0023. 9 | */ 10 | public class FileSystemClassLoader extends ClassLoader { 11 | 12 | private String classLoaderName; 13 | private String path; 14 | 15 | public FileSystemClassLoader(ClassLoader parent, String classLoaderName, String path) { 16 | super(parent); 17 | this.classLoaderName = classLoaderName; 18 | this.path = path; 19 | } 20 | 21 | public FileSystemClassLoader(String classLoaderName, String path) {//这里没有指定父加载器,默认为AppClassLoader(SystemClassLoader) 22 | this.classLoaderName = classLoaderName; 23 | this.path = path; 24 | } 25 | 26 | @Override 27 | public String toString() { 28 | return this.classLoaderName; 29 | } 30 | 31 | @Override 32 | protected Class findClass(String name) throws ClassNotFoundException { 33 | byte[] bytes = readClassFile(name); 34 | return this.defineClass(name, bytes, 0, bytes.length); 35 | } 36 | 37 | // private byte[] readClassFile(String name) { 38 | // FileInputStream fileInputStream = null; 39 | // byte[] returnBytes = null; 40 | // 41 | // name = name.replaceAll("\\.", "/"); 42 | // String filePath = this.path + name + ".class"; 43 | // try { 44 | // fileInputStream = new FileInputStream(filePath); 45 | // ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); 46 | // int tmp = 0; 47 | // while ((tmp = fileInputStream.read()) != -1) { 48 | // outputStream.write(tmp); 49 | // } 50 | // returnBytes = outputStream.toByteArray(); 51 | // outputStream.close(); 52 | // fileInputStream.close(); 53 | // } catch (FileNotFoundException e) { 54 | // e.printStackTrace(); 55 | // } catch (IOException e) { 56 | // e.printStackTrace(); 57 | // } 58 | // return returnBytes; 59 | // } 60 | 61 | private byte[] readClassFile(String name) { 62 | FileInputStream fileInputStream = null; 63 | byte[] returnBytes = null; 64 | 65 | name = name.replaceAll("\\.", "/"); 66 | String filePath = this.path + name + ".class"; 67 | try { 68 | fileInputStream = new FileInputStream(filePath); 69 | returnBytes = new byte[fileInputStream.available()]; 70 | fileInputStream.read(returnBytes); 71 | fileInputStream.close(); 72 | } catch (FileNotFoundException e) { 73 | e.printStackTrace(); 74 | } catch (IOException e) { 75 | e.printStackTrace(); 76 | } 77 | return returnBytes; 78 | } 79 | } 80 | -------------------------------------------------------------------------------- /src/com/wp/类加载器/Main.java: -------------------------------------------------------------------------------- 1 | package com.wp.类加载器; 2 | 3 | /** 4 | * Created by 王萍 on 2017/10/24 0024. 5 | */ 6 | public class Main { 7 | 8 | public static void main(String[] args) throws ClassNotFoundException, IllegalAccessException, InstantiationException { 9 | FileSystemClassLoader classLoader=new FileSystemClassLoader("wanwnapp","F:/tmp/"); 10 | Class printClassLoader = classLoader.loadClass("com.wp.PrintClassLoader"); 11 | printClassLoader.newInstance(); 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /src/com/wp/类加载器/PrintClassLoader.java: -------------------------------------------------------------------------------- 1 | package com.wp.类加载器; 2 | public class PrintClassLoader{ 3 | public PrintClassLoader(){ 4 | System.out.println("classLoader is : "+this.getClass().getClassLoader()); 5 | } 6 | } -------------------------------------------------------------------------------- /src/com/wp/编码/Encoding.java: -------------------------------------------------------------------------------- 1 | package com.wp.编码; 2 | 3 | import java.io.UnsupportedEncodingException; 4 | 5 | /** 6 | * @author 王萍 7 | * @date 2018/1/23 0023 8 | */ 9 | public class Encoding { 10 | public static void main(String[] args) { 11 | String name = "I am 君山"; 12 | toHex(name.toCharArray()); 13 | try { 14 | toHex(name.getBytes("iso-8859-1")); 15 | toHex(name.getBytes("gb2312")); 16 | toHex(name.getBytes("gbk")); 17 | toHex(name.getBytes("utf-16")); //会打印一feff开头,是utf-16中的格式 18 | toHex(name.getBytes("utf-8")); 19 | } catch (UnsupportedEncodingException e) { 20 | e.printStackTrace(); 21 | } 22 | } 23 | 24 | public static void toHex(char[] chars) { 25 | for (char c : chars) { 26 | System.out.print(" " + Integer.toHexString(c)); 27 | } 28 | System.out.println(); 29 | } 30 | 31 | private static void toHex(byte[] buffer) { 32 | String h = ""; 33 | for (int i = 0; i < buffer.length; i++) { 34 | String temp = Integer.toHexString(buffer[i] & 0xFF); 35 | if (temp.length() == 1) { 36 | temp = "0" + temp; 37 | } 38 | h = h + " " + temp; 39 | } 40 | System.out.println(h); 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /src/com/wp/自动装箱和拆箱/Box.java: -------------------------------------------------------------------------------- 1 | package com.wp.自动装箱和拆箱; 2 | 3 | /** 4 | * Created by 王萍 on 2017/2/5 0005. 5 | */ 6 | public class Box { 7 | 8 | /** 9 | * since 1.5 10 | * @param args 11 | */ 12 | public static void main(String[] args) { 13 | //自动装箱,将数据类型自动转为包装类型 14 | Integer integer = 3; 15 | 16 | //自动拆箱,将包装类型转为数据类型 17 | System.out.println(integer.getClass().getName()); 18 | System.out.println(integer+10); 19 | 20 | int i = 128; 21 | //栈对象 22 | Integer i2 = 128; 23 | //堆对象 24 | Integer i3 = new Integer(128); 25 | 26 | //Integer会自动拆箱为int,所以为true 27 | System.out.println(i == i2);//true 28 | System.out.println(i == i3);//true 29 | System.out.println(i2 == i3);//false 堆对象和栈对象,对象之间比较,而自动拆箱后对象都转换为int比较值 30 | System.out.println("----------------------"); 31 | 32 | Integer i5 = 127;//java在编译的时候,被翻译成-> Integer i5 = Integer.valueOf(127); 33 | Integer i6 = 127; 34 | System.out.println(i5 == i6);//true 35 | 36 | //对于-128到127之间的数,会进行缓存,Integer i5 = 127时,会将127进行缓存,下次再写Integer i6 = 127时,就会直接从缓存中取,就不会new了。 37 | // Integer i51 = 128; 38 | // Integer i61 = 128; 39 | // System.out.println(i51 == i61);//false 40 | 41 | Integer i52=new Integer(126); 42 | Integer i62=new Integer(126); 43 | System.out.println(i52==i62);//false 堆中两个不同对象 44 | System.out.println("----------------------"); 45 | 46 | Integer ii5 = new Integer(127); 47 | System.out.println(i5 == ii5); //false 堆对象和栈对象,对象之间比较, 48 | //new出来的两个对象肯定不相等 49 | 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /src/com/wp/静态导入/StaticImport.java: -------------------------------------------------------------------------------- 1 | package com.wp.静态导入; 2 | 3 | /** 4 | * 静态导入,导入某个类中的某个静态方法,以免使用方法时重复书写类名加上方法名 5 | * since 1.5 6 | */ 7 | 8 | import static java.lang.Math.abs; 9 | import static java.lang.Math.max; 10 | 11 | /** 12 | * Created by 王萍 on 2017/2/5 0005. 13 | */ 14 | public class StaticImport { 15 | 16 | public static void main(String[] args) { 17 | System.out.println(max(5,10)); 18 | System.out.println(abs(3-4)); 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /动态代理/pom.xml: -------------------------------------------------------------------------------- 1 | 3 | 4.0.0 4 | 5 | 动态代理 6 | 动态代理 7 | 1.0-SNAPSHOT 8 | jar 9 | 10 | 动态代理 11 | http://maven.apache.org 12 | 13 | 14 | UTF-8 15 | 16 | 17 | 18 | 19 | 20 | cglib 21 | cglib 22 | 2.2.2 23 | 24 | 25 | 26 | junit 27 | junit 28 | 3.8.1 29 | test 30 | 31 | 32 | junit 33 | junit 34 | 4.12 35 | 36 | 37 | 38 | -------------------------------------------------------------------------------- /动态代理/src/main/java/aop/chain/CglibProxyChain.java: -------------------------------------------------------------------------------- 1 | package aop.chain; 2 | 3 | import aop.interceptor.ProxyInterceptor; 4 | import net.sf.cglib.proxy.MethodProxy; 5 | 6 | import java.lang.reflect.Method; 7 | import java.util.List; 8 | 9 | /** 10 | * Created by 王萍 on 2017/11/12 0012. 11 | */ 12 | public class CglibProxyChain extends DefaultProxyChain { 13 | 14 | private MethodProxy methodProxy; 15 | 16 | public CglibProxyChain(Class targetClass, Object targetObject, Method method, MethodProxy methodProxy, Object[] params, List interceptors) { 17 | super(targetClass, targetObject, method, params, interceptors); 18 | this.methodProxy = methodProxy; 19 | } 20 | 21 | public Object doChain() throws Throwable { 22 | 23 | Object result; 24 | if (interceptorIndex < interceptors.size()) { 25 | result = interceptors.get(interceptorIndex++).intercept(this); 26 | } else { 27 | result = methodProxy.invokeSuper(targetObject, params); 28 | } 29 | return result; 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /动态代理/src/main/java/aop/chain/DefaultProxyChain.java: -------------------------------------------------------------------------------- 1 | package aop.chain; 2 | 3 | import aop.interceptor.ProxyInterceptor; 4 | 5 | import java.lang.reflect.Method; 6 | import java.util.ArrayList; 7 | import java.util.List; 8 | 9 | /** 10 | * Created by 王萍 on 2017/11/11 0011. 11 | */ 12 | public class DefaultProxyChain { 13 | 14 | protected List interceptors = new ArrayList(); 15 | protected int interceptorIndex = 0; 16 | 17 | protected Class targetClass; 18 | protected Object targetObject; 19 | protected Method method; 20 | protected Object[] params; 21 | 22 | public Class getTargetClass() { 23 | return targetClass; 24 | } 25 | 26 | public Method getMethod() { 27 | return method; 28 | } 29 | 30 | public Object[] getParams() { 31 | return params; 32 | } 33 | 34 | public DefaultProxyChain(Class targetClass, Object targetObject, Method method, Object[] params, List interceptors) { 35 | this.targetClass = targetClass; 36 | this.targetObject = targetObject; 37 | this.method = method; 38 | this.params = params; 39 | this.interceptors = interceptors; 40 | } 41 | 42 | 43 | public Object doChain() throws Throwable { 44 | 45 | Object result; 46 | if (interceptorIndex < interceptors.size()) { 47 | result = interceptors.get(interceptorIndex++).intercept(this); 48 | } else { 49 | result = method.invoke(targetObject, params); 50 | } 51 | return result; 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /动态代理/src/main/java/aop/creator/CglibCreator.java: -------------------------------------------------------------------------------- 1 | package aop.creator; 2 | 3 | import aop.chain.CglibProxyChain; 4 | import aop.interceptor.ProxyInterceptor; 5 | import net.sf.cglib.proxy.Enhancer; 6 | import net.sf.cglib.proxy.MethodInterceptor; 7 | import net.sf.cglib.proxy.MethodProxy; 8 | 9 | import java.lang.reflect.Method; 10 | import java.util.List; 11 | 12 | /** 13 | * Created by 王萍 on 2017/11/12 0012. 14 | */ 15 | public class CglibCreator implements ProxyCreator { 16 | public T createProxy(final Class targetClass,final List interceptors) { 17 | return (T) Enhancer.create(targetClass, new MethodInterceptor() { 18 | public Object intercept(Object targetObject, Method method, Object[] params, MethodProxy methodProxy) throws Throwable { 19 | return new CglibProxyChain(targetClass, targetObject, method, methodProxy, params, interceptors).doChain(); 20 | } 21 | }); 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /动态代理/src/main/java/aop/creator/JdkCreator.java: -------------------------------------------------------------------------------- 1 | package aop.creator; 2 | 3 | import aop.chain.DefaultProxyChain; 4 | import aop.interceptor.ProxyInterceptor; 5 | 6 | import java.lang.reflect.InvocationHandler; 7 | import java.lang.reflect.Method; 8 | import java.lang.reflect.Proxy; 9 | import java.util.List; 10 | 11 | /** 12 | * Created by 王萍 on 2017/11/12 0012. 13 | */ 14 | public class JdkCreator implements ProxyCreator { 15 | public T createProxy(final Class targetClass, final List interceptors) { 16 | return (T) Proxy.newProxyInstance(targetClass.getClassLoader(), targetClass.getInterfaces(), new InvocationHandler() { 17 | public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { 18 | return new DefaultProxyChain(targetClass, targetClass.getConstructor().newInstance(), method, args, interceptors).doChain(); 19 | } 20 | }); 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /动态代理/src/main/java/aop/creator/ProxyCreator.java: -------------------------------------------------------------------------------- 1 | package aop.creator; 2 | 3 | import java.util.List; 4 | 5 | import aop.interceptor.ProxyInterceptor; 6 | 7 | /** 8 | * Created by 王萍 on 2017/11/12 0012. 9 | */ 10 | public interface ProxyCreator { 11 | 12 | public T createProxy(final Class targetClass, final List interceptors); 13 | } 14 | -------------------------------------------------------------------------------- /动态代理/src/main/java/aop/factory/AbstractProxyFactory.java: -------------------------------------------------------------------------------- 1 | package aop.factory; 2 | 3 | import java.util.ArrayList; 4 | import java.util.List; 5 | 6 | import aop.creator.CglibCreator; 7 | import aop.creator.JdkCreator; 8 | import aop.interceptor.ProxyInterceptor; 9 | 10 | /** 11 | * Created by 王萍 on 2017/11/11 0011. 12 | */ 13 | 14 | public abstract class AbstractProxyFactory { 15 | 16 | protected List interceptors=new ArrayList(); 17 | 18 | protected JdkCreator jdkCreator = new JdkCreator(); 19 | protected CglibCreator cglibCreator = new CglibCreator(); 20 | 21 | protected T proxy; 22 | 23 | public void addInterceptor(ProxyInterceptor interceptor) { 24 | this.interceptors.add(interceptor); 25 | } 26 | 27 | public void removeInterceptor(ProxyInterceptor interceptor) { 28 | this.interceptors.remove(interceptor); 29 | } 30 | 31 | public abstract T getProxy(Class targetClass); 32 | } 33 | -------------------------------------------------------------------------------- /动态代理/src/main/java/aop/factory/CglibProxyFactory.java: -------------------------------------------------------------------------------- 1 | package aop.factory; 2 | 3 | /** 4 | * Created by 王萍 on 2017/11/12 0012. 5 | */ 6 | public class CglibProxyFactory extends AbstractProxyFactory { 7 | 8 | @Override 9 | public T getProxy(Class targetClass) { 10 | proxy = this.cglibCreator.createProxy(targetClass, interceptors); 11 | return proxy; 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /动态代理/src/main/java/aop/factory/JdkProxyFactory.java: -------------------------------------------------------------------------------- 1 | package aop.factory; 2 | 3 | /** 4 | * Created by 王萍 on 2017/11/12 0012. 5 | */ 6 | public class JdkProxyFactory extends AbstractProxyFactory { 7 | 8 | @Override 9 | public T getProxy(Class targetClass) { 10 | proxy = this.jdkCreator.createProxy(targetClass, interceptors); 11 | return proxy; 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /动态代理/src/main/java/aop/interceptor/AbstractProxyInterceptor.java: -------------------------------------------------------------------------------- 1 | package aop.interceptor; 2 | 3 | import aop.chain.DefaultProxyChain; 4 | 5 | import java.lang.reflect.Method; 6 | /** 7 | * Created by 王萍 on 2017/11/11 0011. 8 | */ 9 | //interceptor的拦截还可以提供不同的逻辑。 10 | // 例如:1. 只写before(targetClass, method, params); result = chain.doChain();就和spring aop的aop:before的实现一样。 11 | //2. 只写result = chain.doChain(); after(targetClass, method, params, result);就和spring aop的aop:after的实现一样。 12 | 13 | public abstract class AbstractProxyInterceptor implements ProxyInterceptor { 14 | public Object intercept(DefaultProxyChain chain) throws Throwable { 15 | 16 | Object result; 17 | 18 | Class targetClass = chain.getTargetClass(); 19 | Method method = chain.getMethod(); 20 | Object[] params = chain.getParams(); 21 | 22 | if (support()) { 23 | before(targetClass, method, params); 24 | result = chain.doChain(); 25 | after(targetClass, method, params, result); 26 | } else { 27 | result = chain.doChain(); 28 | } 29 | return result; 30 | } 31 | 32 | public abstract void before(Class targetClass, Method method, Object[] params); 33 | 34 | public abstract void after(Class targetClass, Method method, Object[] params, Object result); 35 | 36 | public boolean support() { 37 | return true; 38 | } 39 | 40 | 41 | } 42 | -------------------------------------------------------------------------------- /动态代理/src/main/java/aop/interceptor/ProxyInterceptor.java: -------------------------------------------------------------------------------- 1 | package aop.interceptor; 2 | 3 | import aop.chain.DefaultProxyChain; 4 | 5 | /** 6 | * Created by 王萍 on 2017/11/11 0011. 7 | */ 8 | public interface ProxyInterceptor { 9 | 10 | Object intercept(DefaultProxyChain chain) throws Throwable; 11 | 12 | boolean support(); 13 | } 14 | -------------------------------------------------------------------------------- /动态代理/src/main/java/proxy/InvocationImpl.java: -------------------------------------------------------------------------------- 1 | package proxy; 2 | 3 | import java.lang.reflect.InvocationHandler; 4 | import java.lang.reflect.Method; 5 | 6 | public class InvocationImpl implements InvocationHandler { 7 | 8 | private Object student; 9 | 10 | public InvocationImpl(Object student) { 11 | this.student = student; 12 | } 13 | 14 | public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { 15 | System.out.println("before method invoke"); 16 | Object returnValue = method.invoke(student, args); 17 | System.out.println("after method invoke"); 18 | return returnValue; 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /动态代理/src/main/java/proxy/Main.java: -------------------------------------------------------------------------------- 1 | package proxy; 2 | 3 | import sun.misc.ProxyGenerator; 4 | 5 | import java.io.FileNotFoundException; 6 | import java.io.FileOutputStream; 7 | import java.io.IOException; 8 | import java.lang.reflect.Proxy; 9 | 10 | public class Main { 11 | 12 | //public static void main(String[] args) { 13 | // Student student = new Student(); 14 | // // 代理类的动作 15 | // InvocationImpl invocation = new InvocationImpl(student); 16 | // ClassLoader classLoader = student.getClass().getClassLoader(); 17 | // Class[] interfaces = student.getClass().getInterfaces(); 18 | // Study proxyInstance = (Study) Proxy.newProxyInstance(classLoader,interfaces , invocation); 19 | // System.out.println("动态代理对象的类型:"+proxyInstance.getClass().getName()); 20 | // proxyInstance.read(); 21 | // System.out.println("---------------------------------"); 22 | // proxyInstance.write(); 23 | // 24 | // createProxyClassFile(); 25 | //} 26 | 27 | public static void main(String[] args) { 28 | Student student = new Student(); 29 | InvocationImpl invocation = new InvocationImpl(student); 30 | ClassLoader classLoader = student.getClass().getClassLoader(); 31 | Class[] interfaces = student.getClass().getInterfaces(); 32 | Study proxyInstance = (Study) Proxy.newProxyInstance(classLoader, interfaces, invocation); 33 | 34 | proxyInstance.write(); 35 | 36 | //代理两层 37 | Study proxyProxyInstance = (Study)Proxy.newProxyInstance(proxyInstance.getClass().getClassLoader(), 38 | proxyInstance.getClass().getInterfaces(), 39 | new ProxyInvocationImpl(proxyInstance)); 40 | System.out.println("动态代理对象的类型:"+proxyInstance.getClass().getName()); 41 | proxyProxyInstance.read(); 42 | System.out.println("---------------------------------"); 43 | proxyProxyInstance.write(); 44 | } 45 | 46 | 47 | private static void createProxyClassFile() { 48 | String name = "StudentProxy"; 49 | byte[] data = ProxyGenerator.generateProxyClass(name, new Class[]{Study.class}); 50 | FileOutputStream out = null; 51 | try { 52 | out = new FileOutputStream(name + ".class"); 53 | out.write(data); 54 | } catch (FileNotFoundException e) { 55 | e.printStackTrace(); 56 | } catch (IOException e) { 57 | e.printStackTrace(); 58 | } finally { 59 | if (null != out) try { 60 | out.close(); 61 | } catch (IOException e) { 62 | e.printStackTrace(); 63 | } 64 | } 65 | } 66 | } 67 | -------------------------------------------------------------------------------- /动态代理/src/main/java/proxy/ProxyInvocationImpl.java: -------------------------------------------------------------------------------- 1 | package proxy; 2 | 3 | import java.lang.reflect.InvocationHandler; 4 | import java.lang.reflect.Method; 5 | 6 | /** 7 | * Created by 王萍 on 2017/10/25 0025. 8 | */ 9 | public class ProxyInvocationImpl implements InvocationHandler { 10 | 11 | private Object object; 12 | 13 | public ProxyInvocationImpl(Object object) { 14 | this.object = object; 15 | } 16 | 17 | public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { 18 | System.out.println("为动态代理对象进行代理----before"); 19 | Object returnValue = method.invoke(object, args); 20 | System.out.println("为动态代理对象进行代理----after"); 21 | return returnValue; 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /动态代理/src/main/java/proxy/Student.java: -------------------------------------------------------------------------------- 1 | package proxy; 2 | 3 | /** 4 | * Created by 王萍 on 2017/10/24 0024. 5 | */ 6 | public class Student implements Study { 7 | 8 | public void write() { 9 | System.out.println("I am writing"); 10 | } 11 | 12 | public void read() { 13 | System.out.println("I am reading"); 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /动态代理/src/main/java/proxy/Study.java: -------------------------------------------------------------------------------- 1 | package proxy; 2 | 3 | /** 4 | * Created by 王萍 on 2017/10/24 0024. 5 | */ 6 | public interface Study { 7 | 8 | void write(); 9 | 10 | void read(); 11 | 12 | } 13 | -------------------------------------------------------------------------------- /动态代理/src/test/java/aop/Dao.java: -------------------------------------------------------------------------------- 1 | package aop; 2 | 3 | /** 4 | * Created by 王萍 on 2017/11/11 0011. 5 | */ 6 | public interface Dao { 7 | 8 | void select(); 9 | 10 | void insert(); 11 | } 12 | -------------------------------------------------------------------------------- /动态代理/src/test/java/aop/TestAop.java: -------------------------------------------------------------------------------- 1 | package aop; 2 | 3 | 4 | import aop.factory.AbstractProxyFactory; 5 | import aop.factory.CglibProxyFactory; 6 | import aop.factory.JdkProxyFactory; 7 | import org.junit.Test; 8 | 9 | /** 10 | * Created by 王萍 on 2017/11/11 0011. 11 | */ 12 | public class TestAop { 13 | 14 | 15 | @Test 16 | public void testCglibProxy() { 17 | 18 | AbstractProxyFactory proxyFactory = new CglibProxyFactory(); 19 | proxyFactory.addInterceptor(new TimeMonitorProxy()); 20 | Dao proxy = proxyFactory.getProxy(UserDao.class); 21 | proxy.insert(); 22 | // proxy.select(); 23 | 24 | System.out.println("----------------------------------"); 25 | proxyFactory.addInterceptor(new TimeMonitorProxy()); 26 | proxy = proxyFactory.getProxy(UserDao.class); 27 | proxy.insert(); 28 | } 29 | 30 | @Test 31 | public void testJdkProxy() { 32 | 33 | AbstractProxyFactory proxyFactory = new JdkProxyFactory(); 34 | proxyFactory.addInterceptor(new TimeMonitorProxy()); 35 | Dao proxy = proxyFactory.getProxy(UserDao.class); 36 | proxy.insert(); 37 | 38 | System.out.println("----------------------------------"); 39 | proxyFactory.addInterceptor(new TimeMonitorProxy()); 40 | proxy = proxyFactory.getProxy(UserDao.class); 41 | proxy.insert(); 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /动态代理/src/test/java/aop/TimeMonitorProxy.java: -------------------------------------------------------------------------------- 1 | package aop; 2 | 3 | 4 | import aop.interceptor.AbstractProxyInterceptor; 5 | 6 | import java.lang.reflect.Method; 7 | 8 | /** 9 | * Created by 王萍 on 2017/11/11 0011. 10 | */ 11 | public class TimeMonitorProxy extends AbstractProxyInterceptor { 12 | 13 | long t1; 14 | 15 | @Override 16 | public void before(Class targetClass, Method method, Object[] params) { 17 | t1 = System.currentTimeMillis(); 18 | System.out.println("before currentTime: " + t1); 19 | try { 20 | Thread.sleep(10); 21 | } catch (InterruptedException e) { 22 | e.printStackTrace(); 23 | } 24 | } 25 | 26 | @Override 27 | public void after(Class targetClass, Method method, Object[] params, Object result) { 28 | long t2 = System.currentTimeMillis(); 29 | System.out.println("after currentTime: " + t2); 30 | System.out.println("执行方法:" + method.getName() + "用了" + (t2 - t1)); 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /动态代理/src/test/java/aop/UserDao.java: -------------------------------------------------------------------------------- 1 | package aop; 2 | 3 | /** 4 | * Created by 王萍 on 2017/11/11 0011. 5 | */ 6 | public class UserDao implements Dao { 7 | 8 | public void select() { 9 | System.out.println("获取User信息"); 10 | } 11 | 12 | public void insert() { 13 | System.out.println("插入User信息"); 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /反射/src/reflect/之前的代码/application/ReplaceChar.java: -------------------------------------------------------------------------------- 1 | package reflect.之前的代码.application; 2 | 3 | import java.lang.reflect.Field; 4 | 5 | /** 6 | * Created by 王萍 on 2017/2/5 0005. 7 | */ 8 | public class ReplaceChar { 9 | 10 | /** 11 | * 使用反射将Demo中的成员变量中字符串类型中有a的字符替换为z。 12 | */ 13 | private String name = "wanwanpp"; 14 | private String sentence = "hanhanpp"; 15 | private String str1 = "fasw"; 16 | private int num = 12; 17 | 18 | public static void main(String[] args) throws IllegalAccessException, InstantiationException { 19 | Class demoClass = ReplaceChar.class; 20 | Field[] declaredFields = demoClass.getDeclaredFields(); 21 | ReplaceChar instance = demoClass.newInstance(); 22 | for (Field field : declaredFields) { 23 | field.setAccessible(true); 24 | 25 | //排除非String对象 26 | if (field.getType() == String.class) { 27 | String string = (String) field.get(instance); 28 | System.out.println("before:" + string); 29 | 30 | //string类型是不可变的需要创建另一个string对象进行接收替换后的字符串。 31 | String s = string.replaceAll("a", "z"); 32 | field.set(instance, s); 33 | 34 | System.out.println("after:" + field.get(instance)); 35 | } 36 | } 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /反射/src/reflect/之前的代码/application/RunOtherZMain.java: -------------------------------------------------------------------------------- 1 | package reflect.之前的代码.application; 2 | 3 | import java.lang.reflect.InvocationTargetException; 4 | import java.lang.reflect.Method; 5 | 6 | /** 7 | * Created by 王萍 on 2017/2/5 0005. 8 | */ 9 | public class RunOtherZMain { 10 | 11 | /** 12 | * 调用其他类的main方法 13 | * @param args 14 | * @throws NoSuchMethodException 15 | * @throws InvocationTargetException 16 | * @throws IllegalAccessException 17 | */ 18 | public static void main(String[] args) throws NoSuchMethodException, InvocationTargetException, IllegalAccessException { 19 | 20 | Class numClass = Num.class; 21 | Method mainmethod = numClass.getMethod("main", String[].class); 22 | //这里传入Num的main方法中时,会将string[]拆为3个string对象。报参数个数错误。 23 | // mainmethod.invoke(null,new String[]{"111","222","333"}); 24 | 25 | //将string[]对象转为以object对象 26 | mainmethod.invoke(null,(Object) new String[]{"111","222","333"}); 27 | 28 | //将string[]对象封装为一个object对象数组。 29 | mainmethod.invoke(null,new Object[]{new String[]{"111","222","333"}}); 30 | 31 | } 32 | 33 | 34 | } 35 | 36 | class Num{ 37 | public static void main(String[] args) { 38 | 39 | for (String arg:args){ 40 | System.out.println(arg); 41 | } 42 | } 43 | } -------------------------------------------------------------------------------- /反射/src/reflect/之前的代码/reflect/Main.java: -------------------------------------------------------------------------------- 1 | package reflect.之前的代码.reflect; 2 | 3 | import java.lang.reflect.*; 4 | 5 | public class Main { 6 | /** 7 | * 为了看清楚Java反射部分代码,所有异常我都最后抛出来给虚拟机处理! 8 | * @param args 9 | * @throws ClassNotFoundException 10 | * @throws InstantiationException 11 | * @throws IllegalAccessException 12 | * @throws InvocationTargetException 13 | * @throws IllegalArgumentException 14 | * @throws NoSuchFieldException 15 | * @throws SecurityException 16 | * @throws NoSuchMethodException 17 | */ 18 | public static void main(String[] args) throws ClassNotFoundException, InstantiationException, IllegalAccessException, IllegalArgumentException, InvocationTargetException, SecurityException, NoSuchFieldException, NoSuchMethodException { 19 | // TODO Auto-generated method stub 20 | 21 | //Demo1. 通过Java反射机制得到类的包名和类名 22 | Demo1(); 23 | System.out.println("==============================================="); 24 | 25 | //Demo2. 验证所有的类都是Class类的实例对象 26 | Demo2(); 27 | System.out.println("==============================================="); 28 | 29 | //Demo3. 通过Java反射机制,用Class 创建类对象[这也就是反射存在的意义所在],无参构造 30 | Demo3(); 31 | System.out.println("==============================================="); 32 | 33 | //Demo4: 通过Java反射机制得到一个类的构造函数,并实现构造带参实例对象 34 | Demo4(); 35 | System.out.println("==============================================="); 36 | 37 | //Demo5: 通过Java反射机制操作成员变量, set 和 get 38 | Demo5(); 39 | System.out.println("==============================================="); 40 | 41 | //Demo6: 通过Java反射机制得到类的一些属性: 继承的接口,父类,函数信息,成员信息,类型等 42 | Demo6(); 43 | System.out.println("==============================================="); 44 | 45 | //Demo7: 通过Java反射机制调用类中方法 46 | Demo7(); 47 | System.out.println("==============================================="); 48 | 49 | //Demo8: 通过Java反射机制获得类加载器 50 | Demo8(); 51 | System.out.println("==============================================="); 52 | 53 | } 54 | 55 | /** 56 | * Demo1: 通过Java反射机制得到类的包名和类名 57 | */ 58 | public static void Demo1() 59 | { 60 | Person person = new Person(); 61 | System.out.println("Demo1: 包名: " + person.getClass().getPackage().getName() + "," 62 | + "完整类名: " + person.getClass().getName()); 63 | System.out.println("Demo1:包名: "+Person.class.getPackage().getName()+",完整类名:"+Person.class.getName()); 64 | } 65 | 66 | /** 67 | * Demo2: 验证所有的类都是Class类的实例对象 68 | * @throws ClassNotFoundException 69 | */ 70 | public static void Demo2() throws ClassNotFoundException 71 | { 72 | //定义两个类型都未知的Class , 设置初值为null, 看看如何给它们赋值成Person类 73 | Class class1 = null; 74 | Class class2 = null; 75 | 76 | //写法1, 可能抛出 ClassNotFoundException [多用这个写法] 77 | class1 = Class.forName("com.wp.reflect.Person"); 78 | System.out.println("Demo2:(写法1) 包名: " + class1.getPackage().getName() + "," 79 | + "完整类名: " + class1.getName()); 80 | 81 | //写法2 82 | class2 = Person.class; 83 | System.out.println("Demo2:(写法2) 包名: " + class2.getPackage().getName() + "," 84 | + "完整类名: " + class2.getName()); 85 | } 86 | 87 | /** 88 | * Demo3: 通过Java反射机制,用Class 创建类对象[这也就是反射存在的意义所在] 89 | * @throws ClassNotFoundException 90 | * @throws IllegalAccessException 91 | * @throws InstantiationException 92 | */ 93 | public static void Demo3() throws ClassNotFoundException, InstantiationException, IllegalAccessException 94 | { 95 | Class class1 = null; 96 | class1 = Class.forName("com.wp.reflect.Person"); 97 | //由于这里不能带参数,所以你要实例化的这个类Person,一定要有无参构造函数哈~ newInstance只能实例化无参构造函数 98 | Person person = (Person) class1.newInstance(); 99 | person.setAge(18); 100 | person.setName("王萍"); 101 | System.out.println("Demo3: " + person.getName() + " : " + person.getAge()); 102 | } 103 | 104 | /** 105 | * Demo4: 通过Java反射机制得到一个类的构造函数,并实现创建带参实例对象 106 | * @throws ClassNotFoundException 107 | * @throws InvocationTargetException 108 | * @throws IllegalAccessException 109 | * @throws InstantiationException 110 | * @throws IllegalArgumentException 111 | */ 112 | public static void Demo4() throws ClassNotFoundException, IllegalArgumentException, InstantiationException, IllegalAccessException, InvocationTargetException, NoSuchMethodException { 113 | Class class1 = null; 114 | Person person1 = null; 115 | Person person2 = null; 116 | 117 | class1 = Class.forName("com.wp.reflect.Person"); 118 | //得到一系列构造函数集合 119 | Constructor[] constructors = class1.getConstructors(); 120 | 121 | person1 = (Person) constructors[0].newInstance(); 122 | person1.setAge(30); 123 | person1.setName("王萍"); 124 | 125 | person2 = (Person) constructors[1].newInstance(18,"王萍"); 126 | //获取指定参数类型的构造函数,与person2使用的同一个构造函数 127 | //这里如果使用Integer.class会报错 128 | Constructor constructor = class1.getConstructor(int.class, String.class); 129 | System.out.println("Demo4: " + person1.getName() + " : " + person1.getAge() 130 | + " , " + person2.getName() + " : " + person2.getAge() 131 | ); 132 | 133 | } 134 | 135 | /** 136 | * Demo5: 通过Java反射机制操作成员变量, set 和 get 137 | * 138 | * @throws IllegalAccessException 139 | * @throws IllegalArgumentException 140 | * @throws NoSuchFieldException 141 | * @throws SecurityException 142 | * @throws InstantiationException 143 | * @throws ClassNotFoundException 144 | */ 145 | public static void Demo5() throws IllegalArgumentException, IllegalAccessException, SecurityException, NoSuchFieldException, InstantiationException, ClassNotFoundException 146 | { 147 | Class class1 = null; 148 | class1 = Class.forName("com.wp.reflect.Person"); 149 | Object obj = class1.newInstance(); 150 | 151 | Field personNameField = class1.getDeclaredField("name"); 152 | 153 | //可访问私有属性 154 | personNameField.setAccessible(true); 155 | //先设置为可访问后,才可以进行get set操作 156 | System.out.println("Demo5: 修改属性之前属性变量的值:" + personNameField.get(obj)); 157 | 158 | //在obj对象中操作字段 159 | personNameField.set(obj, "胖虎先森"); 160 | 161 | System.out.println("Demo5: 修改属性之后得到属性变量的值:" + personNameField.get(obj)); 162 | } 163 | 164 | 165 | /** 166 | * Demo6: 通过Java反射机制得到类的一些属性: 继承的接口,父类,函数信息,成员信息,类型等 167 | * @throws ClassNotFoundException 168 | */ 169 | public static void Demo6() throws ClassNotFoundException 170 | { 171 | Class class1 = null; 172 | class1 = Class.forName("com.wp.reflect.SuperMan"); 173 | 174 | //取得父类名称 175 | Class superClass = class1.getSuperclass(); 176 | System.out.println("Demo6: SuperMan类的父类名: " + superClass.getName()); 177 | 178 | System.out.println("==============================================="); 179 | 180 | 181 | Field[] fields = class1.getDeclaredFields(); 182 | for (int i = 0; i < fields.length; i++) { 183 | System.out.println("类中的成员: " + fields[i]); 184 | } 185 | 186 | //表示该类中的公共字段 187 | // Field[] fields1 = class1.getFields(); 188 | 189 | System.out.println("==============================================="); 190 | 191 | //取得类方法 192 | Method[] methods = class1.getDeclaredMethods(); 193 | for (int i = 0; i < methods.length; i++) { 194 | System.out.println("Demo6,取得SuperMan类的方法:"); 195 | System.out.println("函数名:" + methods[i].getName()); 196 | System.out.println("函数返回类型:" + methods[i].getReturnType()); 197 | System.out.println("函数访问修饰符:" + Modifier.toString(methods[i].getModifiers())); 198 | System.out.println("函数代码写法: " + methods[i]); 199 | } 200 | 201 | System.out.println("==============================================="); 202 | 203 | //取得类实现的接口,因为接口类也属于Class,所以得到接口中的方法也是一样的方法得到哈 204 | Class interfaces[] = class1.getInterfaces(); 205 | for (int i = 0; i < interfaces.length; i++) { 206 | System.out.println("实现的接口类名: " + interfaces[i].getName() ); 207 | } 208 | 209 | } 210 | 211 | /** 212 | * Demo7: 通过Java反射机制调用类方法 213 | * @throws ClassNotFoundException 214 | * @throws NoSuchMethodException 215 | * @throws SecurityException 216 | * @throws InvocationTargetException 217 | * @throws IllegalAccessException 218 | * @throws IllegalArgumentException 219 | * @throws InstantiationException 220 | */ 221 | public static void Demo7() throws ClassNotFoundException, SecurityException, NoSuchMethodException, IllegalArgumentException, IllegalAccessException, InvocationTargetException, InstantiationException 222 | { 223 | Class class1 = null; 224 | class1 = Class.forName("com.wp.reflect.SuperMan"); 225 | 226 | System.out.println("Demo7: \n调用无参方法fly():"); 227 | Method method = class1.getMethod("fly"); 228 | //在某类的特定示例中执行该类的方法 229 | method.invoke(class1.newInstance()); 230 | 231 | System.out.println("调用有参方法walk(int m):"); 232 | method = class1.getMethod("walk",int.class); 233 | method.invoke(class1.newInstance(),100); 234 | } 235 | 236 | /** 237 | * Demo8: 通过Java反射机制得到类加载器信息 238 | * 239 | * 在java中有三种类类加载器。[这段资料网上截取] 240 | 1)Bootstrap ClassLoader 此加载器采用c++编写,一般开发中很少见。 241 | 2)Extension ClassLoader 用来进行扩展类的加载,一般对应的是jre\lib\ext目录中的类 242 | 3)AppClassLoader 加载classpath指定的类,是最常用的加载器。同时也是java中默认的加载器。 243 | * 244 | * @throws ClassNotFoundException 245 | */ 246 | public static void Demo8() throws ClassNotFoundException 247 | { 248 | Class class1 = null; 249 | class1 = Class.forName("com.wp.reflect.SuperMan"); 250 | String nameString = class1.getClassLoader().getClass().getName(); 251 | 252 | System.out.println("Demo8: 类加载器类名: " + nameString); 253 | } 254 | 255 | 256 | 257 | } 258 | 259 | /** 260 | * 261 | * @author xiaoyaomeng 262 | * 263 | */ 264 | class Person{ 265 | private int age; 266 | private String name; 267 | public Person(){ 268 | 269 | } 270 | public Person(int age, String name){ 271 | this.age = age; 272 | this.name = name; 273 | } 274 | 275 | public int getAge() { 276 | return age; 277 | } 278 | public void setAge(int age) { 279 | this.age = age; 280 | } 281 | public String getName() { 282 | return name; 283 | } 284 | public void setName(String name) { 285 | this.name = name; 286 | } 287 | } 288 | 289 | class SuperMan extends Person implements ActionInterface 290 | { 291 | private boolean BlueBriefs; 292 | 293 | public void fly() 294 | { 295 | System.out.println("超人会飞耶~~"); 296 | } 297 | 298 | public boolean isBlueBriefs() { 299 | return BlueBriefs; 300 | } 301 | public void setBlueBriefs(boolean blueBriefs) { 302 | BlueBriefs = blueBriefs; 303 | } 304 | 305 | @Override 306 | public void walk(int m) { 307 | // TODO Auto-generated method stub 308 | System.out.println("超人会走耶~~走了" + m + "米就走不动了!"); 309 | } 310 | } 311 | 312 | interface ActionInterface{ 313 | public void walk(int m); 314 | } -------------------------------------------------------------------------------- /反射/src/reflect/之前的代码/reflectArray/Demo.java: -------------------------------------------------------------------------------- 1 | package reflect.之前的代码.reflectArray; 2 | 3 | /** 4 | * Created by 王萍 on 2017/2/5 0005. 5 | */ 6 | public class Demo { 7 | /** 8 | * 数组也是对象,他们的父类都是Object对象 9 | * 10 | * @param args 11 | */ 12 | public static void main(String[] args) { 13 | int[] a1 = new int[3]; 14 | int[] a2 = new int[4]; 15 | int[][] a3 = new int[2][3]; 16 | String[] a4 = new String[3]; 17 | 18 | System.out.println(a1.getClass() == a2.getClass()); 19 | 20 | //经编译器检查后,发现a1与a3,a4比较无法通过。 21 | // System.out.println(a1.getClass()==a4.getClass()); 22 | // System.out.println(a1.getClass()==a3.getClass()); 23 | 24 | System.out.println(a1.getClass().getName()); 25 | System.out.println(a1.getClass().getSuperclass().getName()); 26 | System.out.println(a4.getClass().getName()); 27 | System.out.println(a4.getClass().getSuperclass().getName()); 28 | System.out.println(a3.getClass().getName()); 29 | System.out.println(a3.getClass().getSuperclass().getName()); 30 | 31 | Object object1 = a1; 32 | Object object2 = a3; 33 | Object object3 = a4; 34 | 35 | //无法将int数组转为一个object数组对象 36 | // Object[] object4 = a1; 37 | 38 | //对于a3这种二维数组,可以将其中一个一维数组当做Object对象 39 | Object[] object5 = a3; 40 | 41 | //String本身的父类就是Object。 42 | Object[] object6 = a4; 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /反射/src/reflect/之前的代码/reflectArray/Demo2.java: -------------------------------------------------------------------------------- 1 | package reflect.之前的代码.reflectArray; 2 | 3 | import java.lang.reflect.Array; 4 | 5 | /** 6 | * Created by 王萍 on 2017/2/5 0005. 7 | */ 8 | public class Demo2 { 9 | 10 | /** 11 | * java.lang.reflect包下的Array对象,用于Array的反射操作 12 | * @param args 13 | */ 14 | public static void main(String[] args) { 15 | 16 | print(new int[]{1,2,3}); 17 | print("haha"); 18 | 19 | 20 | Object[] objects = {"1", 1, 1.2}; 21 | for (Object o:objects){ 22 | System.out.println(o.getClass().getName()); 23 | } 24 | } 25 | 26 | public static void print(Object object){ 27 | Class objectClass = object.getClass(); 28 | if (objectClass.isArray()){ 29 | for (int i=0;i< Array.getLength(object);i++){ 30 | System.out.println(Array.get(object,i)); 31 | } 32 | }else { 33 | System.out.println(object); 34 | } 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /反射/src/reflect/之前的代码/反射的扩展性/Dundi.java: -------------------------------------------------------------------------------- 1 | package reflect.之前的代码.反射的扩展性; 2 | 3 | /** 4 | * Created by 王萍 on 2017/2/5 0005. 5 | */ 6 | public class Dundi implements Special { 7 | @Override 8 | public void mySpecial() { 9 | System.out.println("I can Dundi"); 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /反射/src/reflect/之前的代码/反射的扩展性/Fly.java: -------------------------------------------------------------------------------- 1 | package reflect.之前的代码.反射的扩展性; 2 | 3 | /** 4 | * Created by 王萍 on 2017/2/5 0005. 5 | */ 6 | public class Fly implements Special { 7 | @Override 8 | public void mySpecial() { 9 | System.out.println("I can fly"); 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /反射/src/reflect/之前的代码/反射的扩展性/MainTest.java: -------------------------------------------------------------------------------- 1 | package reflect.之前的代码.反射的扩展性; 2 | 3 | import java.io.File; 4 | import java.io.FileInputStream; 5 | import java.io.IOException; 6 | import java.io.InputStreamReader; 7 | import java.util.Properties; 8 | 9 | /** 10 | * Created by ��Ƽ on 2017/2/5 0005. 11 | */ 12 | public class MainTest { 13 | 14 | public static void main(String[] args) throws IOException, ClassNotFoundException, IllegalAccessException, InstantiationException { 15 | Person person = new Person(); 16 | person.produce(); 17 | 18 | File properties = new File("F:\\IDEA\\reflect\\src\\com\\wp\\反射的扩展性\\special.properties"); 19 | Properties prop = new Properties(); 20 | FileInputStream inputStream= new FileInputStream(properties); 21 | 22 | // prop.load(inputStream); 23 | 24 | /** 25 | * 需要使用reader接口,可以指定编码方式。注意调整编码 26 | */ 27 | prop.load(new InputStreamReader(inputStream,"utf-8")); 28 | 29 | for (int i=0;i clazz = Class.forName(className); 32 | Special o = (Special) clazz.newInstance(); 33 | person.can(o); 34 | } 35 | 36 | inputStream.close(); 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /反射/src/reflect/之前的代码/反射的扩展性/Person.java: -------------------------------------------------------------------------------- 1 | package reflect.之前的代码.反射的扩展性; 2 | 3 | /** 4 | * Created by 王萍 on 2017/2/5 0005. 5 | */ 6 | public class Person { 7 | 8 | public void produce() { 9 | System.out.println("我是一个man"); 10 | } 11 | 12 | public void can(Special special){ 13 | special.mySpecial(); 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /反射/src/reflect/之前的代码/反射的扩展性/Special.java: -------------------------------------------------------------------------------- 1 | package reflect.之前的代码.反射的扩展性; 2 | 3 | /** 4 | * Created by 王萍 on 2017/2/5 0005. 5 | */ 6 | public interface Special { 7 | public void mySpecial(); 8 | } 9 | -------------------------------------------------------------------------------- /反射/src/reflect/之前的代码/反射的扩展性/special.properties: -------------------------------------------------------------------------------- 1 | #special1=com.wp.反射的扩展性.Fly 2 | special1=com.wp.反射的扩展性.Dundi -------------------------------------------------------------------------------- /反射/src/reflect/了解反射/HiddenImplementation.java: -------------------------------------------------------------------------------- 1 | package reflect.了解反射; 2 | 3 | import reflect.了解反射.interfacea.A; 4 | import reflect.了解反射.packageaccess.HiddenC; 5 | 6 | import java.lang.reflect.Method; 7 | 8 | public class HiddenImplementation { 9 | public static void main(String[] args) throws Exception { 10 | A a = HiddenC.makeA(); 11 | a.f(); 12 | System.out.println(a.getClass().getName()); 13 | // Oops! Reflection still allows us to call g(): 14 | callHiddenMethod(a, "g"); 15 | // And even methods that are less accessible! 16 | callHiddenMethod(a, "u"); 17 | callHiddenMethod(a, "v"); 18 | callHiddenMethod(a, "w"); 19 | } 20 | 21 | /** 22 | * 任何修饰符下的方法或者field都可以通过反射获取 23 | * @param a 24 | * @param methodName 25 | * @throws Exception 26 | */ 27 | static void callHiddenMethod(Object a, String methodName) throws Exception { 28 | Method g = a.getClass().getDeclaredMethod(methodName); 29 | g.setAccessible(true); 30 | g.invoke(a); 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /反射/src/reflect/了解反射/interfacea/A.java: -------------------------------------------------------------------------------- 1 | package reflect.了解反射.interfacea; 2 | 3 | public interface A { void f(); } -------------------------------------------------------------------------------- /反射/src/reflect/了解反射/packageaccess/HiddenC.java: -------------------------------------------------------------------------------- 1 | package reflect.了解反射.packageaccess; 2 | 3 | import reflect.了解反射.interfacea.A; 4 | 5 | class C implements A { 6 | public void f() { 7 | System.out.println("public C.f()"); 8 | } 9 | 10 | public void g() { 11 | System.out.println("public C.g()"); 12 | } 13 | 14 | protected void v() { 15 | System.out.println("protected C.v()"); 16 | } 17 | 18 | void u() { 19 | System.out.println("package C.u()"); 20 | } 21 | 22 | private void w() { 23 | System.out.println("private C.w()"); 24 | } 25 | } 26 | 27 | public class HiddenC { 28 | public static A makeA() { 29 | return new C(); 30 | } 31 | } -------------------------------------------------------------------------------- /反射/src/reflect/泛型擦除/Cat.java: -------------------------------------------------------------------------------- 1 | package reflect.泛型擦除; 2 | 3 | public class Cat extends Pet { 4 | public Cat(String name) { super(name); } 5 | public Cat() { super(); } 6 | } -------------------------------------------------------------------------------- /反射/src/reflect/泛型擦除/Dog.java: -------------------------------------------------------------------------------- 1 | package reflect.泛型擦除; 2 | 3 | public class Dog extends Pet { 4 | public Dog(String name) { super(name); } 5 | public Dog() { super(); } 6 | } -------------------------------------------------------------------------------- /反射/src/reflect/泛型擦除/EgyptianMau.java: -------------------------------------------------------------------------------- 1 | package reflect.泛型擦除; 2 | 3 | public class EgyptianMau extends Cat { 4 | public EgyptianMau(String name) { super(name); } 5 | public EgyptianMau() { super(); } 6 | } -------------------------------------------------------------------------------- /反射/src/reflect/泛型擦除/Individual.java: -------------------------------------------------------------------------------- 1 | package reflect.泛型擦除; 2 | 3 | public class Individual implements Comparable { 4 | private static long counter = 0; 5 | private final long id = counter++; 6 | private String name; // name is optional 7 | 8 | public long id() { 9 | return id; 10 | } 11 | 12 | public Individual(String name) { 13 | this.name = name; 14 | } 15 | 16 | public Individual() { 17 | } 18 | 19 | public String toString() { 20 | return getClass().getSimpleName() + (name == null ? "" : " " + name); 21 | } 22 | 23 | public boolean equals(Object o) { 24 | return o instanceof Individual && id == ((Individual) o).id; 25 | } 26 | 27 | public int hashCode() { 28 | int result = 17; 29 | if (name != null) { 30 | result = 37 * result + name.hashCode(); 31 | } 32 | result = 37 * result + (int) id; 33 | return result; 34 | } 35 | 36 | //Comparable接口中的方法 37 | public int compareTo(Individual arg) { 38 | // Compare by class name first: 39 | String first = getClass().getSimpleName(); 40 | String argFirst = arg.getClass().getSimpleName(); 41 | int firstCompare = first.compareTo(argFirst); 42 | if (firstCompare != 0) { 43 | return firstCompare; 44 | } 45 | if (name != null && arg.name != null) { 46 | int secendCompare = name.compareTo(arg.name); 47 | if (secendCompare != 0) { 48 | return secendCompare; 49 | } 50 | } 51 | return (arg.id < id ? -1 : (arg.id == id ? 0 : 1)); 52 | } 53 | } -------------------------------------------------------------------------------- /反射/src/reflect/泛型擦除/LiteralPetCreator.java: -------------------------------------------------------------------------------- 1 | package reflect.泛型擦除; 2 | 3 | import java.util.*; 4 | 5 | public class LiteralPetCreator extends PetCreator { 6 | 7 | @SuppressWarnings("unchecked") 8 | public static final List> allTypes = Collections.unmodifiableList( 9 | Arrays.asList(Pet.class, Dog.class, Cat.class, Mutt.class, EgyptianMau.class)); 10 | private static final List> types = allTypes.subList( 11 | allTypes.indexOf(Mutt.class), allTypes.size()); 12 | 13 | public List> getTypes() { 14 | return types; 15 | } 16 | 17 | public static void main(String[] args) { 18 | PetCreator petCreator = new LiteralPetCreator(); 19 | ArrayList pets = petCreator.arrayList(5);//随机生成一个size为5的ArrayList对象 20 | 21 | //计算pets中有多少个对象属于那种子类类型。 22 | TypeCounter typeCounter = new TypeCounter(Pet.class); 23 | Iterator iterator = pets.iterator(); 24 | while (iterator.hasNext()){ 25 | typeCounter.count(iterator.next()); 26 | } 27 | System.out.println(typeCounter.toString()); 28 | } 29 | } -------------------------------------------------------------------------------- /反射/src/reflect/泛型擦除/Mutt.java: -------------------------------------------------------------------------------- 1 | package reflect.泛型擦除; 2 | 3 | public class Mutt extends Dog { 4 | public Mutt(String name) { super(name); } 5 | public Mutt() { super(); } 6 | } -------------------------------------------------------------------------------- /反射/src/reflect/泛型擦除/Pet.java: -------------------------------------------------------------------------------- 1 | package reflect.泛型擦除; 2 | 3 | public class Pet extends Individual { 4 | public Pet(String name) { super(name); } 5 | public Pet() { super(); } 6 | } -------------------------------------------------------------------------------- /反射/src/reflect/泛型擦除/PetCreator.java: -------------------------------------------------------------------------------- 1 | package reflect.泛型擦除; 2 | 3 | import java.util.ArrayList; 4 | import java.util.Collections; 5 | import java.util.List; 6 | import java.util.Random; 7 | 8 | public abstract class PetCreator { 9 | private Random rand = new Random(47); 10 | 11 | // The List of the different getTypes of Pet to create: 12 | public abstract List> getTypes(); 13 | 14 | public Pet randomPet() { 15 | // Create one random Pet 16 | int n = rand.nextInt(getTypes().size()); //生成0到getTypes().size()之间的随机数(包括0) 17 | try { 18 | return getTypes().get(n).newInstance(); 19 | } catch (InstantiationException e) { 20 | throw new RuntimeException(e); 21 | } catch (IllegalAccessException e) { 22 | throw new RuntimeException(e); 23 | } 24 | } 25 | 26 | public Pet[] createArray(int size) { 27 | Pet[] result = new Pet[size]; 28 | for (int i = 0; i < size; i++) { 29 | result[i] = randomPet(); 30 | } 31 | return result; 32 | } 33 | 34 | public ArrayList arrayList(int size) { 35 | ArrayList result = new ArrayList(); 36 | Collections.addAll(result, createArray(size)); 37 | return result; 38 | } 39 | } -------------------------------------------------------------------------------- /反射/src/reflect/泛型擦除/TypeCounter.java: -------------------------------------------------------------------------------- 1 | package reflect.泛型擦除; 2 | 3 | import java.util.ArrayList; 4 | import java.util.HashMap; 5 | import java.util.Map; 6 | 7 | public class TypeCounter extends HashMap, Integer> { //继承HashMap是为了更方便的使用其get,put方法 8 | private Class baseType; 9 | 10 | public TypeCounter(Class baseType) { 11 | this.baseType = baseType; 12 | } 13 | 14 | public void count(Object obj) { 15 | Class type = obj.getClass(); 16 | if (!baseType.isAssignableFrom(type)) { //判断baseType类型是否为type类型的父类或者间接父类 17 | throw new RuntimeException( 18 | obj + " incorrect type " + type + ", should be type or subtype of " + baseType); 19 | } 20 | countClass(type); 21 | } 22 | 23 | private void countClass(Class type) { 24 | Integer quantity = get(type); 25 | put(type, quantity == null ? 1 : quantity + 1); 26 | Class superClass = type.getSuperclass(); 27 | if (superClass != null && baseType.isAssignableFrom(superClass)) { 28 | countClass(superClass); 29 | } 30 | } 31 | 32 | @Override 33 | public String toString() { 34 | StringBuilder result = new StringBuilder("{"); 35 | for (Map.Entry, Integer> pair : entrySet()) { 36 | result.append(pair.getKey().getSimpleName()); 37 | result.append("="); 38 | result.append(pair.getValue()); 39 | result.append(", "); 40 | } 41 | result.delete(result.length() - 2, result.length()); 42 | result.append("} "); 43 | return result.toString(); 44 | } 45 | 46 | public static void main(String[] args) { 47 | TypeCounter typeCounter = new TypeCounter(Object.class); 48 | typeCounter.count(new ArrayList<>()); 49 | System.out.println(typeCounter.toString()); 50 | } 51 | } -------------------------------------------------------------------------------- /反射/src/reflect/结合注解/PasswordUtils.java: -------------------------------------------------------------------------------- 1 | package reflect.结合注解; 2 | 3 | import java.util.List; 4 | 5 | /** 6 | * Created by 王萍 on 2017/4/13 0013. 7 | */ 8 | public class PasswordUtils { 9 | 10 | @UserCase(id = 47, description = "Password must contain at least one numeric") 11 | private boolean validatePassword(String password) { 12 | return password.matches("\\w*\\d\\w*"); 13 | } 14 | 15 | @UserCase(id = 48) 16 | public String encryptPassword(String password) { 17 | return new StringBuilder(password).reverse().toString(); 18 | } 19 | 20 | @UserCase(id=49, description="New passwords can't equal previously used ones") 21 | public boolean checkForNewPassword(List prevPasswords, String password) { 22 | return !prevPasswords.contains(password); 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /反射/src/reflect/结合注解/UseCaseTracker.java: -------------------------------------------------------------------------------- 1 | package reflect.结合注解; 2 | 3 | import java.lang.reflect.Method; 4 | import java.util.ArrayList; 5 | import java.util.Collections; 6 | import java.util.List; 7 | 8 | public class UseCaseTracker { 9 | public static void trackUseCases(List useCases, Class cl) { 10 | for(Method m : cl.getDeclaredMethods()) {//遍历cl中的所有方法 11 | UserCase uc = m.getAnnotation(UserCase.class); 12 | if(uc != null) { 13 | System.out.println("Found Use Case: " + uc.id() + " " + uc.description()); //获取UserCase的属性 14 | useCases.remove(new Integer(uc.id())); 15 | } 16 | } 17 | for(int i : useCases) { 18 | System.out.println("Warning: Missing use case " + i); 19 | } 20 | } 21 | public static void main(String[] args) { 22 | List useCases = new ArrayList(); 23 | Collections.addAll(useCases, 47, 48, 49, 50); 24 | trackUseCases(useCases, PasswordUtils.class); 25 | } 26 | } -------------------------------------------------------------------------------- /反射/src/reflect/结合注解/UserCase.java: -------------------------------------------------------------------------------- 1 | package reflect.结合注解; 2 | 3 | import java.lang.annotation.ElementType; 4 | import java.lang.annotation.Retention; 5 | import java.lang.annotation.RetentionPolicy; 6 | import java.lang.annotation.Target; 7 | 8 | /** 9 | * Created by 王萍 on 2017/4/13 0013. 10 | */ 11 | @Target(ElementType.METHOD) 12 | @Retention(RetentionPolicy.RUNTIME) 13 | public @interface UserCase { 14 | 15 | public int id(); 16 | 17 | public String description() default "no description"; 18 | } 19 | -------------------------------------------------------------------------------- /反射/反射总结.txt: -------------------------------------------------------------------------------- 1 | 1.反射允许在运行期获取对象的类型信息 2 | 2.可通过getClass(),forName(), .class三种方式获取 3 | 4 | 5 | 反射应用: 6 | 1.工厂模式:Factory类中用反射的话,添加了一个新的类之后,就不需要再修改工厂类Factory了 7 | 2.数据库JDBC中通过Class.forName(Driver).来获得数据库连接驱动 8 | 3.分析类文件:毕竟能得到类中的方法等等 9 | 4.访问一些不能访问的变量或属性:破解别人代码 10 | 11 | 注意: 12 | 调用非静态方法时,使用invoke(object,args),object为实例对象,args为传入的参数 13 | 调用静态方法时,使用invoke(null,args)使用null是因为静态方法中没有具体的实例对象。 14 | -------------------------------------------------------------------------------- /多线程/src/concurrent/atomic/LongAccumulatorDemo.java: -------------------------------------------------------------------------------- 1 | package concurrent.atomic; 2 | 3 | import java.util.Random; 4 | import java.util.concurrent.atomic.LongAccumulator; 5 | 6 | /** 7 | * LongAccumulator是LongAdder的功能增强版。LongAdder的API只有对数值的加减, 8 | * 而LongAccumulator提供了自定义的函数操作。 9 | */ 10 | public class LongAccumulatorDemo { 11 | 12 | private static final int THREAD_NUMBER = 10; 13 | 14 | // 找出最大值 15 | public static void main(String[] args) throws InterruptedException { 16 | 17 | // 传入一个函数 18 | LongAccumulator accumulator = new LongAccumulator(Long::max, Long.MIN_VALUE); 19 | // 也可以自定义函数 20 | //LongAccumulator accumulator2 = new LongAccumulator(LongAccumulatorDemo::getMax, Long.MIN_VALUE); 21 | Thread[] ts = new Thread[THREAD_NUMBER]; 22 | 23 | for (int i = 0; i < THREAD_NUMBER; i++) { 24 | ts[i] = new Thread(() -> { 25 | Random random = new Random(); 26 | long value = random.nextLong(); 27 | System.out.println(value); 28 | accumulator.accumulate(value); // 比较value和上一次的比较值,然后存储较大者 29 | }); 30 | ts[i].start(); 31 | } 32 | for (int i = 0; i < THREAD_NUMBER; i++) { 33 | ts[i].join(); 34 | } 35 | System.out.println("\n\n\n" + accumulator.longValue()); 36 | } 37 | 38 | public static long getMax(long value1, long value2) { 39 | return Math.max(value1, value2); 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /多线程/src/concurrent/atomic/LongAdderDemo.java: -------------------------------------------------------------------------------- 1 | package concurrent.atomic; 2 | 3 | import java.util.concurrent.CompletionService; 4 | import java.util.concurrent.ExecutionException; 5 | import java.util.concurrent.ExecutorCompletionService; 6 | import java.util.concurrent.ExecutorService; 7 | import java.util.concurrent.Executors; 8 | import java.util.concurrent.Future; 9 | import java.util.concurrent.atomic.AtomicLong; 10 | import java.util.concurrent.atomic.LongAdder; 11 | 12 | /** 13 | * @Author: wangping 14 | * @Date: 2020/4/25 2:43 下午 15 | * https://blog.csdn.net/fouy_yun/article/details/77825039 16 | * 17 | * LongAdder是JDK1.8开始出现的,所提供的API基本上可以替换掉原先的AtomicLong。 18 | * LongAdder所使用的思想就是热点分离,这一点可以类比一下ConcurrentHashMap的设计思想。 19 | * 就是将value值分离成一个数组,当多线程访问时,通过hash算法映射到其中的一个数字进行计数。 20 | * 而最终的结果,就是这些数组的求和累加。这样一来,就减小了锁的粒度。 21 | */ 22 | public class LongAdderDemo { 23 | 24 | public static final int THREAD_COUNT = 1000; 25 | static ExecutorService pool = Executors.newFixedThreadPool(THREAD_COUNT); 26 | static CompletionService completionService = new ExecutorCompletionService(pool); 27 | static final AtomicLong atomicLong = new AtomicLong(0L); 28 | static final LongAdder longAdder = new LongAdder(); 29 | 30 | public static void main(String[] args) throws InterruptedException, ExecutionException { 31 | long start = System.currentTimeMillis(); 32 | for(int i = 0; i < THREAD_COUNT; i++) { 33 | completionService.submit(() -> { 34 | for(int j = 0; j < 100000; j++) { 35 | 36 | // 使用longadder比使用atomicLong性能高,并发越大时,差距越大。 37 | atomicLong.incrementAndGet(); 38 | 39 | //longAdder.increment(); 40 | //longAdder.longValue(); 41 | } 42 | return 1L; 43 | }); 44 | } 45 | for(int i = 0; i < THREAD_COUNT; i++) { 46 | Future future = completionService.take(); 47 | future.get(); 48 | } 49 | System.out.println("耗时:" + (System.currentTimeMillis() - start)); 50 | pool.shutdown(); 51 | } 52 | } 53 | 54 | -------------------------------------------------------------------------------- /多线程/src/thread/MyThread3.java: -------------------------------------------------------------------------------- 1 | package thread; 2 | 3 | class Data 4 | { 5 | public int value = 0; 6 | } 7 | class Work 8 | { 9 | public void process(Data data, Integer... numbers) 10 | { 11 | for (int n : numbers) 12 | { 13 | data.value += n; 14 | } 15 | } 16 | } 17 | public class MyThread3 extends Thread 18 | { 19 | private Work work; 20 | 21 | public MyThread3(Work work) 22 | { 23 | this.work = work; 24 | } 25 | public void run() 26 | { 27 | java.util.Random random = new java.util.Random(); 28 | Data data = new Data(); 29 | int n1 = random.nextInt(1000); 30 | int n2 = random.nextInt(2000); 31 | int n3 = random.nextInt(3000); 32 | work.process(data, n1, n2, n3); // 使用回调函数 33 | System.out.println(String.valueOf(n1) + "+" + String.valueOf(n2) + "+" 34 | + String.valueOf(n3) + "=" + data.value); 35 | } 36 | public static void main(String[] args) 37 | { 38 | Thread thread = new MyThread3(new Work()); 39 | thread.start(); 40 | } 41 | } -------------------------------------------------------------------------------- /数据结构/src/queue/threadSafe/TwoLockLinkQueue.java: -------------------------------------------------------------------------------- 1 | package queue.threadSafe; 2 | 3 | import java.util.concurrent.ExecutorService; 4 | import java.util.concurrent.Executors; 5 | import java.util.concurrent.TimeUnit; 6 | import java.util.concurrent.atomic.AtomicInteger; 7 | import java.util.concurrent.locks.Lock; 8 | import java.util.concurrent.locks.ReentrantLock; 9 | 10 | class Node { 11 | private E value; 12 | private Node next; 13 | 14 | public Node(E e) { 15 | value = e; 16 | } 17 | 18 | public void setValue(E value) { 19 | this.value = value; 20 | } 21 | 22 | public E getValue() { 23 | return value; 24 | } 25 | 26 | public void setNext(Node next) { 27 | this.next = next; 28 | } 29 | 30 | public Node getNext() { 31 | return next; 32 | } 33 | } 34 | 35 | public class TwoLockLinkQueue { 36 | 37 | private Lock headLock = new ReentrantLock(); 38 | private Lock tailLock = new ReentrantLock(); 39 | private Node headNode; 40 | private Node tailNode; 41 | 42 | public TwoLockLinkQueue() { 43 | //使用了一个哨兵节点,所以真正poll时取出的是第二个节点(哨兵节点后一个节点)的value。 44 | // Node sentinelNode = new Node(null); 45 | // headNode = sentinelNode; 46 | // tailNode = sentinelNode; 47 | 48 | //不使用哨兵 49 | headNode = null; 50 | tailNode = null; 51 | } 52 | 53 | //不使用哨兵 54 | public boolean offer(E e) { 55 | if (e == null) { 56 | return false; 57 | } 58 | Node newNode = new Node<>(e); 59 | tailLock.lock(); 60 | try { 61 | if (tailNode != null) { 62 | tailNode.setNext(newNode); 63 | } else { 64 | headNode = newNode; 65 | } 66 | tailNode = newNode; 67 | } finally { 68 | tailLock.unlock(); 69 | } 70 | return true; 71 | } 72 | public E pool() { 73 | headLock.lock(); 74 | try { 75 | if (headNode == null) return null; 76 | else { 77 | Node now = this.headNode; 78 | this.headNode = now.getNext(); 79 | if (headNode == null) { 80 | tailNode = null; 81 | } 82 | return now.getValue(); 83 | } 84 | } finally { 85 | headLock.unlock(); 86 | } 87 | } 88 | 89 | // 使用哨兵 90 | //public boolean offer( E e ) { 91 | // if(e == null) { 92 | // return false; 93 | // } 94 | // Node newNode = new Node(e); 95 | // tailLock.lock(); 96 | // try { 97 | // tailNode.setNext(newNode); 98 | // tailNode = newNode; 99 | // } finally { 100 | // tailLock.unlock(); 101 | // } 102 | // return true; 103 | //} 104 | // public E pool() { 105 | // headLock.lock(); 106 | // try { 107 | // Node newHeadNode = headNode.getNext(); 108 | // if (newHeadNode == null) { 109 | // return null; 110 | // } else { 111 | // headNode = newHeadNode; 112 | // return newHeadNode.getValue(); 113 | // } 114 | // } finally { 115 | // headLock.unlock(); 116 | // } 117 | // } 118 | 119 | static class TestClass { 120 | static AtomicInteger count = new AtomicInteger(0); 121 | static TwoLockLinkQueue queue = new TwoLockLinkQueue(); 122 | 123 | public static void main(String[] args) { 124 | 125 | final int offerCount = 5; 126 | final int threadCount = 5; 127 | 128 | class task1 implements Runnable { 129 | private TwoLockLinkQueue queue; 130 | 131 | public task1(TwoLockLinkQueue queue) { 132 | this.queue = queue; 133 | } 134 | 135 | public void run() { 136 | for (int i = 0; i < offerCount; i++) { 137 | int value = count.addAndGet(1); 138 | queue.offer(value); 139 | System.out.println("[" + Thread.currentThread() + 140 | "]" + "offer:" + value); 141 | } 142 | } 143 | } 144 | 145 | class task2 implements Runnable { 146 | private TwoLockLinkQueue queue; 147 | 148 | public task2(TwoLockLinkQueue queue) { 149 | this.queue = queue; 150 | } 151 | 152 | public void run() { 153 | while (!Thread.interrupted()) { 154 | Integer value = queue.pool(); 155 | if (value != null) 156 | System.out.println("[" + Thread.currentThread() + 157 | "]" + "poll:" + value); 158 | } 159 | } 160 | } 161 | ExecutorService pool = Executors.newCachedThreadPool(); 162 | for (int i = 0; i < threadCount; i++) { 163 | pool.execute(new task1(queue)); 164 | pool.execute(new task2(queue)); 165 | } 166 | pool.shutdown(); 167 | 168 | try { 169 | pool.awaitTermination(1000, TimeUnit.MILLISECONDS); 170 | } catch (InterruptedException e1) { 171 | } 172 | pool.shutdownNow(); 173 | } 174 | } 175 | } -------------------------------------------------------------------------------- /缓存/cache.markdown: -------------------------------------------------------------------------------- 1 | # 缓存 2 | ### 缓存相关概念:缓存命中,cache miss,存储成本,失效,替代策略 3 | ### 参考博客: 4 | http://www.cnblogs.com/abc8023/p/4807208.html 5 | 6 | https://my.oschina.net/u/866190/blog/188712 7 | 8 | ## 缓存算法是重点 -------------------------------------------------------------------------------- /缓存/src/cache/lru/LRUCacheWithHashMap.java: -------------------------------------------------------------------------------- 1 | package cache.lru; 2 | 3 | import java.util.HashMap; 4 | import java.util.Map; 5 | 6 | /** 7 | * @author 王萍 8 | * @date 2018/2/28 0028 9 | * LRU 最近最少使用算法 10 | */ 11 | public class LRUCacheWithHashMap { 12 | 13 | class Node { 14 | Node pre; 15 | Node next; 16 | Integer key; 17 | Integer val; 18 | 19 | Node(Integer k, Integer v) { 20 | key = k; 21 | val = v; 22 | } 23 | } 24 | 25 | private Map map = new HashMap<>(); 26 | 27 | //head和tail两个都是new Node(null, null),且不会改变 28 | private final Node head = new Node(null, null); 29 | private final Node tail = new Node(null, null); 30 | private int cap; 31 | 32 | public LRUCacheWithHashMap(int capacity) { 33 | cap = capacity; 34 | head.next = tail; 35 | tail.pre = head; 36 | } 37 | 38 | public int get(int key) { 39 | Node n = map.get(key); 40 | //找到之后将其放到末尾去 41 | if (n != null) { 42 | //前驱的next置为后驱 43 | n.pre.next = n.next; 44 | //后驱的pre置为前驱 45 | n.next.pre = n.pre; 46 | appendTail(n); 47 | return n.val; 48 | } 49 | return -1; 50 | } 51 | 52 | public void set(int key, int value) { 53 | Node n = map.get(key); 54 | // 存在的话 55 | if (n != null) { 56 | //更新值 57 | n.val = value; 58 | map.put(key, n); 59 | 60 | n.pre.next = n.next; 61 | n.next.pre = n.pre; 62 | appendTail(n); 63 | return; 64 | } 65 | //不存在就添加 66 | 67 | //检查,大小是否满了,满了就删除head后的第一个节点 68 | if (map.size() == cap) { 69 | Node tmp = head.next; 70 | head.next = head.next.next; 71 | head.next.pre = head; 72 | map.remove(tmp.key); 73 | } 74 | //然后添加节点到末尾 75 | n = new Node(key, value); 76 | // youngest node append taill 77 | appendTail(n); 78 | map.put(key, n); 79 | } 80 | 81 | //添加到尾部 82 | private void appendTail(Node n) { 83 | n.next = tail; 84 | n.pre = tail.pre; 85 | tail.pre.next = n; 86 | tail.pre = n; 87 | } 88 | } 89 | -------------------------------------------------------------------------------- /缓存/src/cache/lru/LRUCacheWithLinkedHashMap.java: -------------------------------------------------------------------------------- 1 | package cache.lru; 2 | 3 | import java.util.LinkedHashMap; 4 | import java.util.Map; 5 | 6 | /** 7 | * @author 王萍 8 | * @date 2018/2/28 0028 9 | */ 10 | public class LRUCacheWithLinkedHashMap { 11 | 12 | private int capacity; 13 | private Map cache; 14 | 15 | public LRUCacheWithLinkedHashMap(int capacity) { 16 | this.capacity = capacity; 17 | this.cache = new LinkedHashMap(capacity, 0.75f, true) { 18 | // 定义put后的移除规则,大于容量就删除eldest 19 | protected boolean removeEldestEntry(Map.Entry eldest) { 20 | return size() > capacity; 21 | } 22 | }; 23 | } 24 | 25 | public int get(int key) { 26 | if (cache.containsKey(key)) { 27 | return cache.get(key); 28 | } else 29 | return -1; 30 | } 31 | 32 | public void set(int key, int value) { 33 | cache.put(key, value); 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /缓存/src/cache/simple/Cache.java: -------------------------------------------------------------------------------- 1 | package cache.simple; 2 | 3 | public class Cache { 4 | private String key;//缓存ID 5 | private Object value;//缓存数据 6 | private long timeOut;//过期时间 7 | private boolean expired; //是否终止 8 | 9 | public Cache() { 10 | super(); 11 | } 12 | 13 | public Cache(String key, Object value, long timeOut, boolean expired) { 14 | this.key = key; 15 | this.value = value; 16 | this.timeOut = timeOut; 17 | this.expired = expired; 18 | } 19 | 20 | public String getKey() { 21 | return key; 22 | } 23 | 24 | public long getTimeOut() { 25 | return timeOut; 26 | } 27 | 28 | public Object getValue() { 29 | return value; 30 | } 31 | 32 | public void setKey(String string) { 33 | key = string; 34 | } 35 | 36 | public void setTimeOut(long l) { 37 | timeOut = l; 38 | } 39 | 40 | public void setValue(Object object) { 41 | value = object; 42 | } 43 | 44 | public boolean isExpired() { 45 | return expired; 46 | } 47 | 48 | public void setExpired(boolean b) { 49 | expired = b; 50 | } 51 | } 52 | 53 | class Test { 54 | public static void main(String[] args) { 55 | // CacheManager.setSimpleFlag("wp",true); 56 | // System.out.println(CacheManager.getSimpleFlag("wp")); 57 | // System.out.println(CacheManager.getSimpleFlag("alksd")); 58 | // CacheManager.putCache("abc", new Cache()); 59 | // CacheManager.putCache("def", new Cache()); 60 | // CacheManager.putCache("ccc", new Cache()); 61 | // CacheManager.clearKey(""); 62 | // Cache c = new Cache(); 63 | // for (int i = 0; i < 10; i++) { 64 | // CacheManager.putCache("" + i, c); 65 | // } 66 | // CacheManager.putCache("aaaaaaaa", c); 67 | // CacheManager.putCache("abchcy;alskd", c); 68 | // CacheManager.putCache("cccccccc", c); 69 | // CacheManager.putCache("abcoqiwhcy", c); 70 | // System.out.println("删除前的大小:"+CacheManager.getCacheSize()); 71 | // CacheManager.getCacheAllkey(); 72 | // CacheManager.clearAll("a"); 73 | // System.out.println("删除后的大小:"+CacheManager.getCacheSize()); 74 | // CacheManager.getCacheAllkey(); 75 | 76 | 77 | 78 | } 79 | } -------------------------------------------------------------------------------- /缓存/src/cache/simple/CacheManager.java: -------------------------------------------------------------------------------- 1 | package cache.simple; 2 | 3 | import java.util.*; 4 | 5 | //Description: 管理缓存 6 | 7 | //可扩展的功能:当chche到内存溢出时必须清除掉最早期的一些缓存对象,这就要求对每个缓存对象保存创建时间 8 | 9 | public class CacheManager { 10 | private static HashMap cacheMap = new HashMap(); 11 | 12 | //单实例构造方法 13 | private CacheManager() { 14 | super(); 15 | } 16 | 17 | //获取布尔值的缓存 18 | public static boolean getSimpleFlag(String key) { 19 | try { 20 | return (Boolean) cacheMap.get(key); 21 | } catch (NullPointerException e) { 22 | System.out.println("the key is not in the map"); 23 | return false; 24 | } 25 | } 26 | 27 | public static long getServerStartdt(String key) { 28 | try { 29 | return (Long) cacheMap.get(key); 30 | } catch (Exception ex) { 31 | return 0; 32 | } 33 | } 34 | 35 | public static boolean isCached(String key) { 36 | return cacheMap.get(key) != null; 37 | } 38 | 39 | //设置布尔值的缓存 40 | public synchronized static boolean setSimpleFlag(String key, boolean flag) { 41 | if (isCached(key) && flag == getSimpleFlag(key)) {//假如为真不允许被覆盖 42 | return false; 43 | } else { 44 | cacheMap.put(key, flag); 45 | return true; 46 | } 47 | } 48 | 49 | //得到缓存。同步静态方法 50 | private synchronized static Cache getCache(String key) { 51 | return (Cache) cacheMap.get(key); 52 | } 53 | 54 | //判断是否存在一个缓存 55 | private synchronized static boolean hasCache(String key) { 56 | return cacheMap.containsKey(key); 57 | } 58 | 59 | //清除所有缓存 60 | public synchronized static void clearAll() { 61 | cacheMap.clear(); 62 | } 63 | 64 | //符合以type变量内容开头的key会被删除掉 65 | public synchronized static void clearAll(String type) { 66 | Iterator i = cacheMap.entrySet().iterator(); 67 | String key; 68 | List arr = new ArrayList(); 69 | try { 70 | while (i.hasNext()) { 71 | Map.Entry entry = (Map.Entry) i.next(); 72 | key = (String) entry.getKey(); 73 | if (key.startsWith(type)) { //如果匹配则删除掉 74 | arr.add(key); 75 | } 76 | } 77 | for (int k = 0; k < arr.size(); k++) { 78 | clearKey((String) arr.get(k)); 79 | } 80 | } catch (Exception ex) { 81 | ex.printStackTrace(); 82 | } 83 | } 84 | 85 | //清除指定的缓存 86 | public synchronized static void clearKey(String key) { 87 | cacheMap.remove(key); 88 | } 89 | 90 | //载入缓存 91 | public synchronized static void putCache(String key, Cache obj) { 92 | cacheMap.put(key, obj); 93 | } 94 | 95 | //获取缓存信息 96 | public static Cache getCacheInfo(String key) { 97 | 98 | if (hasCache(key)) { 99 | Cache cache = getCache(key); 100 | if (cacheExpired(cache)) { //调用判断是否终止方法 101 | cache.setExpired(true); 102 | } 103 | return cache; 104 | } else 105 | return null; 106 | } 107 | 108 | //载入缓存信息 109 | public static void putCacheInfo(String key, Cache obj, long dt, boolean expired) { 110 | Cache cache = new Cache(); 111 | cache.setKey(key); 112 | cache.setTimeOut(dt + System.currentTimeMillis()); //设置多久后更新缓存 113 | cache.setValue(obj); 114 | cache.setExpired(expired); //缓存默认载入时,终止状态为FALSE 115 | cacheMap.put(key, cache); 116 | } 117 | 118 | //重写载入缓存信息方法 119 | public static void putCacheInfo(String key, Cache obj, long dt) { 120 | Cache cache = new Cache(); 121 | cache.setKey(key); 122 | cache.setTimeOut(dt + System.currentTimeMillis()); 123 | cache.setValue(obj); 124 | cache.setExpired(false); 125 | cacheMap.put(key, cache); 126 | } 127 | 128 | //判断缓存是否终止 129 | public static boolean cacheExpired(Cache cache) { 130 | if (null == cache) { //传入的缓存不存在 131 | throw new NullPointerException("the cache is null"); 132 | // return false; 133 | } 134 | long now = System.currentTimeMillis(); //系统当前的毫秒数 135 | long cacheTime = cache.getTimeOut(); //缓存内的过期毫秒数 136 | 137 | if (cacheTime <= 0 || cacheTime > now) { //过期时间小于等于零时,或者过期时间大于当前时间时,则为FALSE 138 | return false; 139 | } else { //大于过期时间 即过期 140 | return true; 141 | } 142 | } 143 | 144 | //获取缓存中的大小 145 | public static int getCacheSize() { 146 | return cacheMap.size(); 147 | } 148 | 149 | //获取指定的类型的大小 150 | public static int getCacheSize(String type) { 151 | int k = 0; 152 | Iterator i = cacheMap.entrySet().iterator(); 153 | String key; 154 | try { 155 | while (i.hasNext()) { 156 | java.util.Map.Entry entry = (java.util.Map.Entry) i.next(); 157 | key = (String) entry.getKey(); 158 | if (key.indexOf(type) != -1) { //如果匹配则删除掉 159 | k++; 160 | } 161 | } 162 | } catch (Exception ex) { 163 | ex.printStackTrace(); 164 | } 165 | 166 | return k; 167 | } 168 | 169 | //获取缓存对象中的所有键值名称 170 | public static List getCacheAllkey() { 171 | List a = new ArrayList(); 172 | try { 173 | Iterator i = cacheMap.entrySet().iterator(); 174 | while (i.hasNext()) { 175 | Map.Entry entry = (Map.Entry) i.next(); 176 | a.add(entry.getKey()); 177 | } 178 | } catch (Exception ex) { 179 | } finally { 180 | return a; 181 | } 182 | } 183 | 184 | //获取缓存对象中指定类型 的键值名称 185 | public static ArrayList getCacheListkey(String type) { 186 | ArrayList a = new ArrayList(); 187 | String key; 188 | try { 189 | Iterator i = cacheMap.entrySet().iterator(); 190 | while (i.hasNext()) { 191 | java.util.Map.Entry entry = (java.util.Map.Entry) i.next(); 192 | key = (String) entry.getKey(); 193 | if (key.indexOf(type) != -1) { 194 | a.add(key); 195 | } 196 | } 197 | } catch (Exception ex) { 198 | } finally { 199 | return a; 200 | } 201 | } 202 | 203 | } -------------------------------------------------------------------------------- /缓存/src/cache/simple/SimpleCache.java: -------------------------------------------------------------------------------- 1 | package cache.simple; 2 | 3 | import java.util.*; 4 | 5 | /** 6 | * 简单的缓存map. 其中的元素如果一定时间内没有访问, 则会被删除. 7 | */ 8 | 9 | public class SimpleCache { 10 | 11 | // TODO: 2017/5/25 0025 用Map为什么还用了一个Queue数据结构?? 12 | //使用队列是使元素按照过期时间排序,最新的元素排在后面,越前面的元素是越快过期的。 13 | 14 | private long liveTime; 15 | private int limit; 16 | private Map> map; 17 | private Queue queue; 18 | 19 | public SimpleCache(long liveTime) { 20 | this(liveTime, 0); 21 | } 22 | 23 | public SimpleCache(long liveTime, int limit) { 24 | this.liveTime = liveTime; 25 | this.limit = limit > 0 ? limit : 0; 26 | int initialCapacity = limit == 0 ? 16 : (int) (limit * 0.8); 27 | this.map = new HashMap<>(initialCapacity); 28 | this.queue = new Queue<>(); 29 | } 30 | 31 | /** 32 | * 将指定key和value添加到缓存中. 如果该key已经存在, 则旧值被替换. 33 | * 34 | * @return 与key关联的旧值. 如果key没有任何映射关系,则返回 null. 35 | */ 36 | public synchronized V add(K key, V value) { 37 | 38 | //先删除掉过时的元素 39 | removeTimeOut(); 40 | 41 | Entity entity = new Entity<>(key, value, liveTime); 42 | Entity oldEntity = map.put(key, entity); 43 | 44 | if (oldEntity != null) {//删除以前key值存在的Entity 45 | queue.remove(oldEntity); 46 | } 47 | queue.append(entity); 48 | 49 | // map的容量大于了最大的容量了,删除一个元素 50 | if (limit != 0 && map.size() > limit) { 51 | removeFirst(); 52 | } 53 | 54 | return oldEntity == null ? null : oldEntity.getValue(); 55 | } 56 | 57 | /** 58 | * 获取与指定key关联的元素 59 | */ 60 | public synchronized V get(K key) { 61 | removeTimeOut(); 62 | Entity entity = map.get(key); 63 | if (entity != null) { 64 | access(entity);//更新该元素的过期时间, 以及在队列中的位置 65 | return entity.getValue(); 66 | } 67 | return null; 68 | } 69 | 70 | /** 71 | * 清空缓冲区 72 | */ 73 | public synchronized void clear() { 74 | map.clear(); 75 | queue.clear(); 76 | } 77 | 78 | /** 79 | * 获取缓存区中的元素个数 80 | */ 81 | public synchronized int size() { 82 | removeTimeOut(); 83 | return map.size(); 84 | } 85 | 86 | /** 87 | * 访问指定元素. 更新该元素的过期时间, 以及在队列中的位置 88 | */ 89 | private synchronized void access(Entity entity) { 90 | queue.remove(entity); 91 | entity.updateTimeout(liveTime); 92 | queue.append(entity); 93 | } 94 | 95 | /** 96 | * 移除所有超时的元素,遍历队列 97 | */ 98 | private synchronized void removeTimeOut() { 99 | 100 | Entity head = queue.getFirst(); 101 | while (head != null && head.isTimeout()) { 102 | removeFirst(); 103 | head = queue.getFirst(); 104 | } 105 | } 106 | 107 | /** 108 | * 移除队列中第一个元素, 并删除map中对应的元素. 注意, 调用该方法之前需要保证缓冲区中有元素 109 | */ 110 | private synchronized void removeFirst() { 111 | map.remove(queue.removeFirst().getKey()); 112 | } 113 | 114 | /** 115 | * 当队列中没有元素时,head=tail=null; 116 | * 当队列中只有一个元素时,head=tail!=null 117 | * 118 | * @param 119 | * @param 120 | */ 121 | private static class Queue { 122 | private Entity head; 123 | private Entity tail; 124 | 125 | public Queue() { 126 | head = null; 127 | tail = null; 128 | } 129 | 130 | /** 131 | * 获得第一个元素. 132 | * 133 | * @return 第一个元素. 如果没有元素, 则返回null. 134 | */ 135 | public Entity getFirst() { 136 | return head; 137 | } 138 | 139 | /** 140 | * 向队列末尾添加元素. 141 | * 142 | * @param entity 需要添加的元素 143 | */ 144 | public void append(Entity entity) { 145 | if (head == null) {//当队列为空时 146 | head = entity; 147 | tail = entity; 148 | entity.prev = null; 149 | } else {//当队列中存在元素时 150 | entity.prev = tail; 151 | tail.next = entity; 152 | tail = entity; 153 | } 154 | entity.next = null; 155 | } 156 | 157 | /** 158 | * 移除第一个元素. 159 | * 160 | * @return 第一个元素. 如果没有元素, 则返回null. 161 | */ 162 | public Entity removeFirst() { 163 | // 没有元素 164 | if (head == null) { 165 | return null; 166 | } 167 | Entity entity = head; 168 | 169 | // 只有一个元素 170 | if (head == tail) { 171 | head = null; 172 | tail = null; 173 | } else { 174 | head = entity.next; 175 | head.prev = null; 176 | } 177 | return entity; 178 | } 179 | 180 | /** 181 | * 从队列中移除指定的节点,该节点已经确定在队列中 182 | */ 183 | public Entity remove(Entity entity) { 184 | //只有一个节点 185 | if (head == tail) { 186 | head = null; 187 | tail = null; 188 | return entity; 189 | } 190 | 191 | if (entity.prev != null) {//entity不是head 192 | entity.prev.next = entity.next; 193 | } else { 194 | head = entity.next; 195 | } 196 | 197 | if (entity.next != null) {//entity不是tail 198 | entity.next.prev = entity.prev; 199 | } else { 200 | tail = entity.prev; 201 | } 202 | return entity; 203 | } 204 | 205 | public void clear() { 206 | head = null; 207 | tail = null; 208 | } 209 | 210 | } 211 | 212 | public static class Entity { 213 | private K key; 214 | private V value; 215 | private long timeout; 216 | Entity next; 217 | Entity prev; 218 | 219 | public Entity(K key, V value, long liveTime) { 220 | this.key = key; 221 | this.value = value; 222 | updateTimeout(liveTime); 223 | } 224 | 225 | public K getKey() { 226 | return key; 227 | } 228 | 229 | public void setKey(K key) { 230 | this.key = key; 231 | } 232 | 233 | public V getValue() { 234 | return value; 235 | } 236 | 237 | public void setValue(V value) { 238 | this.value = value; 239 | } 240 | 241 | public long getTimeout() { 242 | return timeout; 243 | } 244 | 245 | public boolean isTimeout() { 246 | return timeout > System.currentTimeMillis(); 247 | } 248 | 249 | void updateTimeout(long liveTime) { 250 | this.timeout = System.currentTimeMillis() + liveTime; 251 | } 252 | 253 | @Override 254 | public int hashCode() { 255 | final int prime = 31; 256 | int result = 1; 257 | result = prime * result + ((key == null) ? 0 : key.hashCode()); 258 | result = prime * result + (int) (timeout ^ (timeout >>> 32)); 259 | result = prime * result + ((value == null) ? 0 : value.hashCode()); 260 | return result; 261 | } 262 | 263 | @SuppressWarnings("rawtypes") 264 | @Override 265 | public boolean equals(Object obj) { 266 | if (this == obj) 267 | return true; 268 | if (obj == null) 269 | return false; 270 | if (getClass() != obj.getClass()) 271 | return false; 272 | Entity other = (Entity) obj; 273 | if (key == null) { 274 | if (other.key != null) 275 | return false; 276 | } else if (!key.equals(other.key)) 277 | return false; 278 | if (timeout != other.timeout) 279 | return false; 280 | if (value == null) { 281 | if (other.value != null) 282 | return false; 283 | } else if (!value.equals(other.value)) 284 | return false; 285 | return true; 286 | } 287 | 288 | @Override 289 | public String toString() { 290 | return "Entity [key=" + key + ", value=" + value + ", timeout=" + timeout + "]"; 291 | } 292 | 293 | } 294 | 295 | } 296 | --------------------------------------------------------------------------------