-
19Java进阶练习题整理(1)
1. 检查时异常、非检查时异常、运行时异常。
Throwable是一切异常、错误类的超类,Throwable有两个子类,Error(错误)和Exception(异常)。
Exception异常又分为RuntimeException运行时异常(非检查时异常)、检查时异常和非检查时异常。
运行时异常是在开发中测试功能时程序终止,控制台出现的异常。
运行时异常有:空指针异常、下标越界异常、类转换异常、数据存储异常、缓存缓存异常、非法参数异常、算术运算异常、数组存储异常、大小为负数的数组错误异常、数字格式异常、不支持的操作异常、安全异常。
InputMismatchException:Scanner输入不符合类型的运行时异常。
ClassCastException:强制转换时不通过的运行时异常
运行时异常表示虚拟机的通常操作中可能遇到的异常。
检查时异常是RuntimeException以外的异常,从程序语法角度讲师必须进行处理的异常,如果不处理,程序就不能编译通过。检查时异常就是写代码时出现红线,需要try-catch 或者throws时出现的异常。
检查时异常有IO异常、SQL异常。
非检查时异常:
ClassNotFoundException:是非检查时异常。反射时出现的类型找不到异常。当动态加载Class的时候找不到类会抛出该异常 。一般在执行Class.forName()、ClassLoader.loadClass()或ClassLoader.findSystemClass()的时候抛出
序列化的含义:
讲一个对象的状态(各个属性量)保存起来,然后再适当的时候再获得。
所以static和transient修饰的变量不能被序列化。原因是static修饰的是变量描述类的状态,transient修饰变量不能被持久化(序列化),代表临时数据。
序列化的过程:
部分一:序列化:将数据分为字节流,以便存储在文件或网络上传输。
部分二:反序列化:打开字节流,并重构对象。
序列化的限制:
(1)只能对对象的状态进行保存,而不管对象的方法。
(2)当父类实现序列化,子类自动实现序列化,不需要显示实现Serializable接口。
这就解释了为什么Exception的定义中,没有实现Serialize接口,但是有序列化ID的原因。因为父类Throwable实现了Serialize接口。
public class Exception extends Throwable { static final long serialVersionUID = -3387516993124229948L;...} public class Throwable implements Serializable { /** use serialVersionUID from JDK 1.0.2 for interoperability */ private static final long serialVersionUID = -3042686055658047285L;}
3.异常代码题
class MyException extends Exception { MyException() { } } class AB { public void format() throws MyException { System.out.println("format()"); } public int formatstr(String str) throws MyException { format(); int i = Integer.valueOf(str); return i; } } public class Test18 { public static void main(String[] args) { new AB().formatstr("1"); } }
因为所给的代码中,Integer.valueOf()的字符串参数是1,不会抛出运行时异常NumberFormatException。所以只有一个会引起异常的点,就是调用抛出了MyExcepption 异常的formatstr()的方法也要抛出MyException。
A段:
public class TestRegularExperssion { public void printA(float a,float b) throws SQLException{} } public class TestRegularExpressionA extends TestRegularExperssion{ public void printA(float a,float b) throws NullPointerException{} }
空指针异常是运行时异常,不是编译时异常所以编译器不会检查。相当于子类没有抛出检查时异常。所以可以看作,父类抛出了检查时异常,父类抛出异常类型大于子类异常类型。
B段:
public class TestRegularExperssion { public void printA(float a,float b)throws NullPointerException{} } class TestRegularExpressionA extends TestRegularExperssion{ public void printA(float a,float b)throws SQLException{} }
父类的方法抛出异常类型必须大于等于子类抛出异常类型。
所以应该在后面写上:
class TestRegularExperssion {
public void printA(float a, float b) throws NullPointerException, SQLException {
}
}
class TestRegularExperssion { public void printA(float a, float b) throws NullPointerException, SQLException { } }
C段:
public class TestRegularExperssion { public void printA(float a,float b){} } public class TestRegularExpressionA extends TestRegularExperssion{ public void printA(float a,float b)throws Exception{ super.printA(a,b); } }
子类异常类型不能大于父类异常类型。
D段:
public class TestRegularExperssion { public void printA(float a,float b)throws Exception{} } public class TestRegularExpressionA extends TestRegularExperssion{ public void printA(float a,float b){ super.printA(a,b); } }
super方法中抛出了异常,而调用方没有抛出,编译错误。
子类和父类重写方法的异常关系:
如果子类抛出了检查时异常,那么父类的检查时异常类必须大于子类。
比如
class TestRegularExperssion { public void printA(float a, float b) throws Exception { } } class TestRegularExpressionA extends TestRegularExperssion { public void printA(float a, float b) throws SQLException { } }
如果父类/子类抛出的是运行时异常,不需要遵守这条规则。
4.集合
语法糖的含义和意义:
语法糖,意思是语法糖衣,是指添加某种语法,这种语法不会影响编程语言的功能。语法糖一般是为程序员提供方便,而不会提供实质性的功能改进。
泛型是什么:
泛型是javaJDK1.5的新特性,它是参数化类型,可以用在类,接口,方法中分别称为泛型类,泛型接口,泛型方法;
泛型的存在时期:
泛型存在于源代码中,编译后会变成原生类型/裸类型
List和List经过编译后就变成了List和List(List和List)
所以说泛型技术就是一颗语法糖。
java中实现泛型的方法被称为擦除类型,也叫做伪类型;
泛型擦除的意义:
Java 引入泛型擦除的原因是避免因为引入泛型而导致运行时创建不必要的类,避免过多的创建类而造成的运行时的过度消耗。
当泛型方法重载:
public void method(List<Integer> list) { System.out.println("Integer"); } public void method(List<String> list) { System.out.println("String"); }
编译会报错,因为编译期变成一样的方法。
public int method(List<Integer> list) { System.out.println("Integer"); return 1; } public String method(List<String> list) { System.out.println("String"); return ""; }
编译生成的字节码文件中,只要描述符不一样两个方法就可以共存。所以不会报错。
5.集合代码题
List<String> list = new ArrayList<String>(); list.add("str1"); list.add(2, "str2"); String s = list.get(1); System.out.println(s); IndexOutOfBoundsException: Index: 2, Size: 1
list的add(int idx,String str)方法必须在<size的地方放元素。不然会报下标越界异常。下标越界异常是运行时异常。
import java.util.List; public class Test { public int getIndexofArray(float[] f){ int rtn=-1; float objf=3.4; List list=null; for(int i=0;i<f.size( );i++){ list.add(f[i]); } for(int i=0;i<list.size( );i++){ float tmp=(float)list.get(i); if(objf==tmp){rtn=i; } } return rtn; } }
其中共有()处错误
编译时异常:2处
float objf=3.4; 应该是float objf=3.4f;
f.size( ); 应该是f.length
运行时异常:1处
空指针异常
public class Test { public static void main(String[] args) { String[] argg={"a","1","b","8"}; Set s=new TreeSet(); s.addAll(Arrays.asList(argg)); System.out.println(s); } }
默认升序(字典序、自然排序规则):
数字、大写字母、小写字母升序
(和Unicode码的ASCII码部分有关)
[(, 1, 8, :, A, B, a, b]
(为40,:为58
public class Test19{ public static void main(String[] args) { List<String> list=new ArrayList<String>(); list.add("hello"); list.add("world"); list.add("world"); list.add("."); for(Iterator i=list.iterator();i.hasNext();){ String s=i.next(); System.out.print(s); } } }
如果是Iterator i = list.iterator();,返回的迭代器中的元素就是Object类型的。
所以上面的String s=i.next();会发生编译错误,大转小。
如果是Iterator i = list.iterator();,返回的迭代器中的元素就是E类型的。
Comparable重写的compareTo()方法也是这样的原理。
6.IO
Reader类的read()方法是从流中取出一个字符读。
InputStream类的read()方法是从流中取出一个字节读。
Reader类重载的read()方法有:
read(char[] cbuf, int off, int len) read(CharBuffer target) read(java.nio.CharBuffer target) read(char cbuf[])
并没有B选项的方法。
InputStream类重载的read()方法有:
read(byte[] b, int off, int len) read(byte b[])
Writer类重载的write()方法有:
write(int c) write(char cbuf[]) write(char[] cbuf, int off, int len) write(String str) write(String str, int off, int len)
OutPutStream类重载的write()方法有:
write(int b) write(byte b[]) write(byte b[], int off, int len)
适配器模式:使两个接口不匹配而无法在一起工作的两个类能够在一起工作。
装饰器模式:在原来接口的基础上增加功能。
InputStreamReader是适配器模式,因为它把字节流转换成了字符流
而BufferedInputStream是装饰器模式,因为他在字节流的基础上添加了缓存的功能。
当读到流结尾时,会抛出EOFException。
Exception in thread “main” java.io.FileNotFoundException: d:\text1.txt (文件名、目录名或卷标语法不正确。)
字节流一次读一个字节,字符流一次读Unicode码元(大小2字节)。
7.IO代码题
public static void main(String[ ] args) { String str = "Hello World"; FileWriter fw = null; try { fw = new FileWriter("c:\\hello.txt"); // 1 fw.write(str); // 2 } catch (IOException e) { e.printStackTrace(); // 3 } finally { fw.close(); // 4 } }
4处会出现编译错误,因为fw.close();方法会抛出IO异常,所以要加上try块包围,在后面加上catch(IOException e){…}
public static void main(String[] args) throws IOException { BufferedReader br = new BufferedReader(new FileReader("d:/text1.txt")); BufferedWriter bw = new BufferedWriter(new FileWriter("d:/text2.txt")); String str = br.readLine(); while (str != null) { bw.write(str); bw.newLine();//根据操作系统选择不同的换行符 str = br.readLine(); } br.close(); bw.close(); }
节点流:可以从或向一个特定的地方(节点)读写数据。如FileReader
处理流:是对一个已存在的流的连接和封装,通过所封装的流的功能调用实现数据读写。
如BufferedReader。处理流的构造方法总是要带一个其他的流对象做参数。一个流对象经过其他流的多次包装,称为流的链接。
Reader、Writer、InputStream、OutputStream
常用节点流:
FileOutputStream…——从文件的结点中读写
ByteArrayInputStream…——从数组的节点中读写
StringReader——从字符串的节点中读写(文件节点流只有字符流)
PipedInputStream——从管道的节点中读写
常用处理流:
InputStreamReader…——转换流
DataOutputStream…——数据流
PrintWriter、PrintStream——打印流
ObjectOutputStream——对象流
import java.io.*; public class A{ public static void main(String[] x){ String s="1234567890abcdefghijklmnopq"; byte[] b=s.getBytes(); try{ File f=new File("B.txt"); FileOutputStream out=new FileOutputStream(f); out.write(b,10,10); out.write(b,0,5); }catch (IOException e){ System.out.println(e.getMessage()); } } }
构造方法 FileOutputStream(f,true)表示本次输出(流关闭之前),流中的数据向文件中的内容追加。
追加与否,只考虑文件原来的内容是否会保留。本次write()操作执行多少次,都会一直写。
8.代理
静态代理类:由程序员创建或由特定工具自动生成源代码,再对其编译。在程序运行前,代理类的.class文件就已经存在了。
动态代理类:在程序运行时,运用反射机制动态创建而成。
代理类与被代理类具有相同的接口。
代理类是public、final的,不是abstract的
java.lang.reflect 包中的 Proxy 类提供了创建动态代理类的方法
E:动态代理有一个静态public方法newProxyInstance(),负责创建动态代理类的实例,有一个InvocationHandler 类型的参数。
9.序列化
10.反射代码题
首先,获得制定反射方法对象的参数列表类型一定要完全一样。
其次,Method.invoke()返回的是一个Object类型的返回值。
出处:https://www.cnblogs.com/Justhis610/p/15117119.html