Java系列-Java高级,
Java系列-Java高级,
1、关闭一个窗体可以用 dispose() 2、jvm默认的内存大小为64M 3、equals比较应该这样 String a=null; a.equals("abc"); 这样会出现空指针异常 "abc".equals(a);这样就不会 4、jad -o -a -s xxx.java xxx.class 反编译class字节码文件【使用jad反编译的好处之一就是可以同时生成字节码和源代码】 5、String与StringBuffer、StringBuilder比较 如果使用普通的字符串拼接形式【+】,jvm在编译时会把+转换成StringBuilder对象,然后在调用append方法,所以当要频繁拼接时应当使用StringBuilder,且不应把+与StringBuilder混合使用,这样只会产生更多的对象,对于StringBuffer与StringBuilder大致一样,只是StringBuffer是线程安全的,StringBuilder是效益更高的6、java中模拟发送http协议可以用URL类与HttpURLConnection类来发送,如果要发送文件到web应用可用,socket来代替HttpURLConnection,因为HttpURLConnection内部使用了缓存
---------------------------集合-------------------------
1、基本每个集合类【不包含Map接口下的类】都提供了一个iterator的迭代器用来遍历,在遍历过程中只能通过Iteractor接口提供的remove来删除元素
2、list与set区别:
1、set集合不允许包含相同的元素
2、list判断二个对象相同是根据equals来的,set接口中的元素是无序的,循环来遍历时也是无序的,而list集合则反之
3、HashSet集合判断两个元素相等的标准是两个对象通过equals()来比较,并且两个对象的hashCode()方法返回值也相等【hashCode的值决定该对象在HashSet的存储位置】
4、TreeSet里的对象必须实现Compareble接口,而且对象必须是同一个类的
判断两个元素相等的标准是:通过Comparator比较两个元素返回了0,这样TreeSet不会把第二个元素添加到集合去了
5、List判断两个对象相等只要通过equals方法比较返回true即可
6、ArrayList与Vector类都是基于数组实现的List类
7、HaspMap判断key的标准跟HashSet一样,两个对象通过equals()来比较,并且两个对象的hashCode()方法返回值也相等【可以直接根据key的地址获得value的地址】
8、Properties可以用来读写属性文件
9、java为所有集合类提供了一个Collections工具包
10、集合里只能存对象,所以当把一个基本类型传进来时会自动装箱
11、Array 读快写慢 LinkedList改快读慢 Hash 两者之间
12、与Arrylist相比:LinkedList 适用在频繁修改的情况用
Vector 适用于线程同步
13、源码心得:
1、HashMap与HashTable的区别:
1、HashMap能存在空键值对,而Hashtable不能
2、HashMap没有contains()方法,而Hashtable有
3、HashMap是线程不安全的
2、LinkedList是基于一个Entry对象双向链表实现的,他的第一个元素的值[element]永远是null,而且他的第一个元素的next与最后一个的previous是关联,且LinkedList的listIterator迭代器可以向前或向后
3、一般的集合做修改时都有返回修改前的oldvlaue值
4、HashMap是无序的,LinkedHashMap是有序的
===================IO start=================== 1、file exists 文件是否存在createNewFile 创建文件
mkdir 创建文件夹【如果filePath为多级文件夹则不会创建成功】
mkdris 创建多级文件夹
isDirectory 是否为一个目录 list(FileNameFilter fileter) 可通过匿名内部类遍历文件 RandomAccessFile 可以读写,应用场景多线程下载
2、流 按方向:输入流 输出流 按单位:字节流 字符流
FileInputStream read FileOutputStream write 3、一个输入流只能读一次 4、文本文件用字符流来处理,资源文件用字节流来处理 5、处理流,构造器数据不是一个物理节点,而是已经存在的流 6、InputStreaReader转换流一般配合System.in使用 7、对象序列化:一个对象要想能够实现序列化,必须实现Serializable接口或在变量前加上transient不加入序列化 8、PrintWriter流可以装饰流也可以传入文件,不用close也可以打印【二参构造器如果设为true,则自动刷新内存】 9、为什么JAVA只提供了InpuStreamReader,而没有提供ReaderStreamInput: 众所周知,字节流比字符流使用范围更广,但字符流比字节流操作方便,如果有个流已经是字符流了,也就是说一个用起来更方便的流,为什么要转换字节流,反之, 如果现在有一个字节流,但我们知道流的内容是文本内容,那些把它转换成字符流来处理会更方便一些 10、重定向标准输入/输出 11、JAVA虚拟机读写其他进程的数据【Process对象】 12、RandomAccessFile类随机访问 13、对象序列化: 1、必须实现Serializable接口或Externalizable接口【自定义序列化】 2、反序列化机制无须通过构造器来初始化Java对象
3、Field前面加transient则指定该Field不被序列化
3、序列化算法 1、所有保存到磁盘中的对象都有一个序列化编号 2、当程序试图序列化一个对象时,程序将先检查该对象是否已经被序列过,只有对象从未(在本次虚拟机中)被序列化,否则将直接输出一个序列化编号
4、自定义序列化 1、可通过自定义三个方法【必须是private】【writeObject(),readObject(),readeObjectNoData()】自定义序列化的算法【保证Field的安全】,反序列化方式【readObject的顺序应该和writeObject顺序一致】 2、还有一种更彻底的自定义序列化,可以把一个对象序列化成想要的类型,需重写 writeReplace()方法 5、关于serialVersionUID,用于标识该Java类的序列化版本,以防类的成员被修改反序列化不成功
--------------------------多线程【轻量级进程】------------------------------------- 1、实现多线程的三种方法: 1、实现Runnable接口【推荐,因为是接口,线程类可以去继承其他类,可以操作同一份资源】 获得当前线程只能Thread.currentThread() 2、实现Callable接口 3、继承Thread类【此方式创建的线程类之间不能共享线程类的实例变量】
2、关闭线程 一般都用一个tag变量来控制循环 10、线程间交换数据用PipedReader与PipedWriter 11、守护线程【后台线程】【如JVM回收线程】 【如果所有前台线程死亡,后台线程会自动死亡】 在线程就绪状态之前(调用start()之前)调用 线程.setDaemon(true) 12、类锁:将类的静态成员函数声明为 synchronized ,以控制其对类的静态成员变量的访问 14、并发性:在同一时刻只能有一条指令执行,但多个进程指令被快速轮换执行,使得在宏观上具有多个进程同时执行的效果 并行性:在同一时刻,有多条指令在多个处理器上同时执行
15、生命周期:新建 -> 就绪 -> 运行 -> 阻塞 -> 死亡 新建:new关键字时创建一个线程,此时的线程对象没有表现出任何纯种的动态特征
就绪:当线程对象调用了start()方法之后,处于这个状态中的线程并没有开始运行,只是表示该线程可以运行了
运行:处于就绪状态的线程获得了CPU,开始执行run()方法的线程执行体
阻塞:当线程调用了sleep()、调用了阻塞式IO方法、 等待同步锁、等待某个通知、调用了suspend()挂起,且阻塞线程被解除后会在合适的时候重新进入就绪状态
16、不要试图对一个线程对象调用二次以上start( ) 17、线程控制: 1、join线程:让一个线程等待另一个线程完成后在执行的方法 2、sleep( ):线程进入阻塞状态【只会给其他线程执行的机会,不会理会其他线程的优先级】 3、yield():与sleep相似,但该方法只是让正在执行的线程暂停,转入就绪状态【只会给优先级相同或优先级更高的线程执行机会】
18、线程同步的几种方式:线程会进入等待池,然后进入锁池,然后进入就绪状态 1、同步代码块 synchronized (obj|class){ } 任何时刻只能有一个线程可以获得对同步监视器的锁定【获得锁旗标】,代码块结束后,该线程会自动释放 synchronized 代码块里要调用外部成员,外部成员必须是final的 2、同步方法:因为监视器监视的对象就是this,所以只要有一个线程还在调用synchronized方法,其它线程就不允许访问这个类的所有的synchronized方法 3、同步锁:Lock【自定义对象的锁定与释放】
19、线程通信的几种方式: 1、传统的线程通信:Object的wait() notify() notifyAll(),这三个方法可以由同步监视器对象来调用,一个是同步方法的this , 一个是同步代码块括号的obj【且只能在同步监视器内调用】 2、PipeInputStream/PipeOutputStream 20、线程局部变量[ThreadLocal]:为每一个使用该变量的线程都提供一个变量值的副本,使每一个线程都可以独立地改变自己的副本,而不会和其他线程的副本冲突 21、JDK提供的String,StringBuffer就是为了照顾单线程和多线程环境所提供的类
-----------------------------------泛型[菱形]-------------------------------------------
1、并不存在泛型类,通过反射机制可以绕过 List<String> li=new ArrayList<>(); List<Integer> li2 =new ArrayList<>(); Boolean bl=li.getClass() ==li2.getClass(); //返回true 通过上面这段代码可得知,系统并没有为List<String>生成新的class文件,而且也不会把AraayList<String>当成新类来处理 因此在静态方法、静态初始化块、静态变量的声明和初始化中不允许使用泛型,instanceof运算符后也不能使用2、通配符上限:<? extends Object>表示所有Object的子类与Objce都可以 <? extends Number & Object> 通配符下限:<? super List> 表示是List的基类与List都可以
3、方法泛型, public <T> void test(T a,List<T> list){} test(new String(),new List<Integer>()); 上面的new List<Integer>()与定义的test(T a,List<T> list)进行比较【只比较泛型参数】,该T类型形参代表的实际类型是Integer
4、泛型构造器 class MyClass<E>{
public <T> MyClass(T t) {
System.out.println("t参数的值为:" + t); } } // MyClass类声明中的E形参是String类型。// 泛型构造器中声明的T形参是Integer类型
MyClass<String> mc1 = new MyClass<>(5); // 显式指定泛型构造器中声明的T形参是Integer类型,
MyClass<String> mc2 = new <Integer> MyClass<String>(5);
// MyClass类声明中的E形参是String类型。
// 如果显式指定泛型构造器中声明的T形参是Integer类型
// 此时就不能使用"菱形"语法,下面代码是错的。 //MyClass<String> mc3 = new <Integer> MyClass<>(5);
5、泛型与方法的重载 6、泛型擦除:当把一个具有泛型信息的对象付给给另一个没有泛型信息的变量时,所有在尖括号之间的类型信息都将被扔掉【默认是声明该参数时指定的第一个上限类型】 List<Integer> li = new ArrayList<>(); li.add(6); li.add(9); List list = li; // 下面代码引起“未经检查的转换”的警告,编译、运行时完全正常 List<String> ls = list; // ① // 但只要访问ls里的元素,如下面代码将引起运行时异常。 System.out.println(ls.get(0)); 7、java不支持泛型数组,且支持引用类型
8、等号两边实际的参数类型必须相等,即使是继承关系也不行 List<Object> list=new ArrayList<String>()
------------------------------JDBC----------------------------------- 步骤 1、加载驱动 Class.forName("driver位置"); 2、获得连接对象 DriverManager.getConnection("url","用户名","密码"); url:serversql 为 jdbc:sqlserver://localhost:1433; databaseName=student mysql 为 jdbc:mysql://localhost:3306/mysql?useUnicode=true&characterEncoding=utf-8,【设置编码,与数据库一致】 Oracle 为 jdbc:oracle:thin:@localhost:1521:orcl 3、创建语句对象 连接对象.createStetament(); 4、执行语句 语句对象.executUpdate("执行语句");
语句对象.executQuery("执行语句"); [返回ResultSet结果集] 1、createStatement() 执行对象 2、prepareStatement() 语句格式化 3、prepareCall() 调用存储过程 4、addBatch() 批处理 5、PreparedStatement参数格式化,可防SQL注入
6、可滚动结果集 con.prepareStatement(sql, ResultSet.TYPE_SCROLL_SENSITIVE, ResultSet.CONCUR_UPDATABLE);
--------------------------反射------------------------------------- 1、反射构造方法 Class c=Class.forName("反射.Person"); cs=c.getConstructor(int.class);//调用有参数的,传入相应的参数类型 cs.newInstance(1); //传入参数的值
2、在反射中,可以通过 setAccessible(true)访问暴力访问私有的成员 3、反射调用方法 //public int run() 第一种:
Method[] m=c.getMethods(); //获得所有方法的对象 for(int i=0;i<m.length;i++){ if(m[i].getName().equalsIgnoreCase("run")){ //反射方法的名字 int res=(int)m[i].invoke(p, null); //调用 } } 第二种:
Method me=c.getMethod("run", null);//方法名 参数类型 int res=(int)me.invoke(p, null);//p为对象,null为无参数 //public int run(String name) me=c.getMethod("run", String.class); me.invoke(p, "这是调用方法传入的参数"); 反射静态成员,只要把传入的对象变为null就行了 反射私有成员,只要把对象的setAccessible(true)就行 反射main方法时,传入参数用m1.invoke(null,(Object)new String[]{"aa","bb"});来传参数
5、类初始化步骤: 1、类加载:将类的class文件读入内存,并为之创建一个java.lang.Class对象 1、BootStrap 加载Java\jdk1.7.0_01\jre\lib\rt.jar中用到的类 2、ExClassLoader 加载Java\jdk1.7.0_01\jre\lib\ext\*.jar所有用到的类 3、AppClassLoader 加载用户自定义的类 4、自定义加载器 2、连接:验证、准备、解析
3、成员初始化
6、委托机制
7、 获得泛型的类型
Type type = UserService.class.getGenericSuperclass(); if (type instanceof ParameterizedType) { ParameterizedType ptype = (ParameterizedType) type; System.out.println(ptype.getActualTypeArguments()[0]); }
--------------------------Annotation注解------------------------------------ 1、分为二大类 1、标记Annotation,仅利用自身的存在与否来为我们提供信息
2、元数据Annotation,包含成员变量,能更多的描述这个Annotation的信息
2、一个Annotation标记要想在运行时被保留得在Annotation类中加上 @ Retention(RetentionPolicy.RUNTIME) //指定Annotation注解可以保留到运行时(JVM会提取Annotation)
3、Retention用于保留 Target用于修饰
===================正则 start===================[软件包 java.util.regex ] 1、String类里有个默认的matches方法 2、Matcher matches 匹配整个字符串
find() 尝试查找与该模式匹配的输入序列的下一个子序列 reset() 重置匹配器 start() 返回查找到的位置 3、替换 replaceAll(str) appendReplacement()针对每次找到的子序列进行替换 4、分组[在匹配符中用()来分组] 用group()来获得整个分组
用group(num)来获得第num个分组的匹配子序列
--匹配符 . 代表任意一个字符 * 代表出现零次或者多次 + 代表出现一次或者多次 ? 零个或者一个 C{n} C正好出现n次 C{n,} C至少出现n次 C{n,m} C至少出现n次,但不超过m次
边界
^ | 行的开头 |
$ | 行的结尾 |
\b | 单词边界 |
\B | 非单词边界 |
范围 [abc123] 取a,b,c,1,2,3的一个 [^abc] 取除了abc的一个 [a-zA-Z] or [a-z] | [A-Z] or [a-z[A-Z]] 取a-z或A-Z中间的一个 [A-Z&&[RFG]] 取A-Z中间并且只能为RFG
\d 一个数字 \D 非数字 \w 一个字母 \W 非字母
非捕获 (?i) 相当于Pattern.compile("java",Pattern.CASE_INSENSITIVE); 不区分大小写
相关文章
- 暂无相关文章
用户点评