JAVA部分语法注意点笔记

tech2022-08-17  123

1.类成员变量有默认初始值,局部变量必须初始化 2.super()必须出现在构造函数的第一句 3.多态:继承,然后覆盖方法;成员变量不能多态 4.父类对象 isinstanceof 子类对象 返回 True 5.final修饰的类不能被继承,修饰的方法不能被重写,修饰的变量不能被改变 6.程序中成员变量赋值的执行顺序: (1)声明成员变量的默认初始化 (2)显式初始化、多个初始化块依次被执行(同级别下按先后顺序执行) (3)构造器再对成员进行初始化操作 (4)通过”对象.属性”或”对象.方法”的方式,可多次给属性赋值 7.一个类中初始化块若有修饰符,则只能被static修饰,称为静态代码块(static block),当类被载入时,类属性的声明和静态代码块先后顺序被执行,且只被执行一次。 static块通常用于初始化static ()属性 class Person { public static int total; static { total = 100;//为total赋初值 } …… //其它属性或方法声明 } 8.非静态代码块:没有static修饰的代码块 1.可以有输出语句。 2.可以对类的属性、类的声明进行初始化操作。 3.可以调用静态的变量或方法。 4.若有多个非静态的代码块,那么按照从上到下的顺序依 次执行。 5.每次创建对象的时候,都会执行一次。且先于构造器执行 静态代码块:用static 修饰的代码块 1.可以有输出语句。 2.可以对类的属性、类的声明进行初始化操作。 3.不可以对非静态的属性初始化。即:不可以调用非静态的属 性和方法。 4.若有多个静态的代码块,那么按照从上到下的顺序依次执行。 5.静态代码块的执行要先于非静态代码块。 6.静态代码块只执行一次 9.含有抽象方法的类必须被声明为抽象类 10.不能用abstract修饰属性、私有方法、构造器、静态方法、final的方法 11.接口 (1)接口中的所有成员变量都默认是由public static final修饰的。 (2)接口中的所有抽象方法都默认是由public abstract修饰的。 (3)接口中没有构造器。 (4)接口采用多继承机制 12.Java 8中关于接口的改进 Java 8中,你可以为接口添加静态方法和默认方法。从技术角度来说,这是完全合法的,只是它看起来违反了接口作为一个抽象定义的理念。 (1)静态方法:使用 static 关键字修饰。可以通过接口直接调用静态方法,并执行其方法体。我们经常在相互一起使用的类中使用静态方法。你可以在标准库中找到像Collection/Collections或者Path/Paths这样成对的接口和类。 (2)默认方法:默认方法使用 default 关键字修饰。可以通过实现类对象来调用。我们在已有的接口中提供新方法的同时,还保持了与旧版本代码的兼容性。 比如:java 8 API中对Collection、List、Comparator等接口提供了丰富的默认方法。 public interface AA { double PI = 3.14; public default void method() { System.out.println("北京"); } default String method1() { return "上海"; } public static void method2() { System.out.println(“hello lambda!"); } } 13.接口冲突的解决方式 比如有个类实现了两个接口,那两个接口都有getName方法,那么在本类中如何解决冲突? class Test implements IntfaceA,InterfaceB{ public String getName(){ return InterfaceA.super.getName(); } } 14.内部类可以使用外部类的私有数据,因为它是外部类的成员,同一个类的成员之间可相互访问。而外部类要访问内部类中的成员需要:内部类.成员或者内部类对象.成员。 15.和外部类不同,Inner class可声明为privateprotected; Inner class 可以声明为static的,但此时就不能再使用外层类的非static的成员变量; 16.Inner class作为类: 可以声明为abstract类 ,因此可以被其它的内部类继承 【注意】非static的内部类中的成员不能声明为static的,只有在外部类或static的内部类中才可声明static成员。 17.匿名内部类不能定义任何静态成员、方法和类,只能创建匿名内部类的一个实例。一个匿名内部类一定是在new的后面,用其隐含实现一个接口或实现一个类。 new 父类构造器(实参列表)|实现接口(){ //匿名内部类的类体部分 } 18.匿名内部类举例 interface A{ public abstract void fun1(); } public class Outer{ public static void main(String[] args) { new Outer().callInner(new A(){ //接口是不能new但此处比较特殊是子类对象实现接口,只不过没有为对象取名 public void fun1() { System.out.println(“implement for fun1"); } });// 两步写成一步了 } public void callInner(A a) { a.fun1(); } } 19.创建用户自定义异常类 class MyException extends Exception { static final long serialVersionUID = 1L; private int idnumber; public MyException(String message, int id) { super(message); this.idnumber = id; } public int getId() { return idnumber; } } 20.枚举类的属性 枚举类对象的属性不应允许被改动, 所以应该使用 private final 修饰 枚举类的使用 private final 修饰的属性应该在构造器中为其赋值 若枚举类显式的定义了带参数的构造器, 则在列出枚举值时也必须对应的传入参数 21.自定义 Annotation(注解) 定义新的 Annotation 类型使用 @interface 关键字 Annotation 的成员变量在 Annotation 定义中以无参数方法的形式来声明. 其方法名和返回值定义了该成员的名字和类型. 可以在定义 Annotation 的成员变量时为其指定初始值, 指定成员变量的初始值可使用 default 关键字 public @interface MyAnnotation{ String name() default “atguigu"; } 没有成员定义的 Annotation 称为标记; 包含成员变量的 Annotation 称为元数据 Annotation 22.StringBuffer类 java.lang.StringBuffer代表可变的字符序列,可以对字符串内容进行增删。 很多方法与String相同,但StringBuffer是可变长度的。 StringBuffer是一个容器。 23.自定义泛型类 class Person<T>{ //使用T类型定义变量 private T info; //使用T类型定义一般方法 public T getInfo(){ return info; } public void setInfo(T info){ this.info = info; } //使用T类型定义构造器 public Person(){} public Person(T info){ this.info = info; } //static的方法中不能声明泛型 //public static void show(T t){ //} //不能在try-catch中使用泛型定义 //try{} //catch(MyException<T> ex){} } 24.对于泛型方法 方法,也可以被泛型化,不管此时定义在其中的类是不是泛型类。在泛型方法中可以定义泛型参数,此时,参数的类型就是传入数据的类型。 泛型方法的格式: [访问权限] <泛型> 返回类型 方法名([泛型标识 参数名称]) 抛出的异常 public class DAO { public <E> E get(int id, E e){ E result = null; return result; }} 25.通配符的使用 (1)使用类型通配符:? 比如:List<?> ,Map<?,?> List<?>是List<String>、List<Object>等各种泛型List的父类。 (2)读取List<?>的对象list中的元素时,永远是安全的,因为不管list的真实类型是什么,它包含的都是Object。 (3)写入list中的元素时,不行。因为我们不知道c的元素类型,我们不能向其中添加对象。 唯一的例外是null,它是所有类型的成员。 将任意元素加入到其中不是类型安全的: Collection<?> c = new ArrayList<String>(); c.add(new Object()); // 编译时错误 因为我们不知道c的元素类型,我们不能向其中添加对象。 add方法有类型参数E作为集合的元素类型。我们传给add的任何参数都必须是一个未知类型的子类。因为我们不知道那是什么类型,所以我们无法传任何东西进去。 唯一的例外的是null,它是所有类型的成员。 另一方面,我们可以调用get()方法并使用其返回值。返回值是一个未知的类型,但是我们知道,它总是一个Object 26.有限制的通配符 <?> 允许所有泛型的引用调用 举例: <? extends Number> (无穷小 , Number] 只允许泛型为Number及Number子类的引用调用 <? super Number> [Number , 无穷大) 只允许泛型为Number及Number父类的引用调用 <? extends Comparable> 只允许泛型为实现Comparable接口的实现类的引用调用 public static void printCollection3(Collection<? extends Person> coll){ //Iterator只能用Iterator<?>或Iterator<? extends Person>.why? Iterator<?> iterator = coll.iterator(); while(iterator.hasNext()){ System.out.println(iterator.next()); } } public static void printCollection4(Collection<? super Person> coll){ Iterator<?> iterator = coll.iterator(); while(iterator.hasNext()){ System.out.println(iterator.next()); } } 27.程序中打开的文件 IO 资源不属于内存里的资源,垃圾回收机制无法回收该资源,所以应该显式关闭文件 IO 资源。 28.缓冲流要“套接”在相应的节点流之上,对读写的数据提供了缓冲的功能,提高了读写的效率,同时增加了一些新的方法 对于输出的缓冲流,写出的数据会先在内存中缓存,使用flush()将会使内存中的数据立刻写出 BufferedReader br = null; BufferedWriter bw = null; try { //step1:创建缓冲流对象:它是过滤流,是对节点流的包装 br = new BufferedReader(new FileReader("d:\\IOTest\\source.txt")); bw = new BufferedWriter(new FileWriter("d:\\IOTest\\destBF.txt")); String str = null; while ((str = br.readLine()) != null) { //一次读取字符文本文件的一行字符 bw.write(str); //一次写入一行字符串 bw.newLine(); //写入行分隔符 } bw.flush(); //step2:刷新缓冲区 } catch (IOException e) { e.printStackTrace(); } finally { // step3: 关闭IO流对象 try { if (bw != null) { bw.close(); //关闭过滤流时,会自动关闭它所包装的底层节点流 } } catch (IOException e) { e.printStackTrace(); } try { if (br != null) { br.close(); } } catch (IOException e) { e.printStackTrace(); } 29.序列化:用ObjectOutputStream类保存基本类型数据或对象的机制 反序列化:用ObjectInputStream类读取基本类型数据或对象的机制 对象序列化机制允许把内存中的Java对象转换成平台无关的二进制流,从而允许把这种二进制流持久地保存在磁盘上,或通过网络将这种二进制流传输到另一个网络节点。当其它程序获取了这种二进制流,就可以恢复成原来的Java对象 序列化的好处在于可将任何实现了Serializable接口的对象转化为字节数据,使其在保存和传输时可被还原 30.对象的序列化 凡是实现Serializable接口的类都有一个表示序列化版本标识符的静态变量: private static final long serialVersionUID; serialVersionUID用来表明类的不同版本间的兼容性 如果类没有显示定义这个静态变量,它的值是Java运行时环境根据类的内部细节自动生成的。若类的源代码作了修改,serialVersionUID 可能发生变化。故建议,显示声明 简单来说,Java的序列化机制是通过在运行时判断类的serialVersionUID来验证版本一致性的。在进行反序列化时,JVM会把传来的字节流中的serialVersionUID与本地相应实体类的serialVersionUID进行比较,如果相同就认为是一致的,可以进行反序列化,否则就会出现序列化版本不一致的异常。(InvalidCastException) 31.序列化的使用例子 序列化:将对象写入到磁盘或者进行网络传输。 要求对象必须实现序列化 ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("test3.txt")); Person p = new Person("韩梅梅",18,"中华大街",new Pet()); oos.writeObject(p); oos.flush(); oos.close(); //反序列化:将磁盘中的对象数据源读出。 ObjectInputStream ois = new ObjectInputStream(new FileInputStream("test3.txt")); Person p1 = (Person)ois.readObject(); System.out.println(p1.toString()); ois.close(); 31.转换流 InputStreamReader:用于将字节流中读取到的字节按指定字符集解码成字符。需要和InputStream“套接”。 OutputStreamWriter:用于将要写入到字节流中的字符按指定字符集编码成字节。需要和OutputStream“套接”。 public void testMyInput() throws Exception{ FileInputStream fis = new FileInputStream("dbcp.txt"); FileOutputStream fos = new FileOutputStream("dbcp5.txt"); InputStreamReader isr = new InputStreamReader(fis,"GBK"); OutputStreamWriter osw = new OutputStreamWriter(fos,"GBK"); BufferedReader br = new BufferedReader(isr); BufferedWriter bw = new BufferedWriter(osw); String str = null; while((str = br.readLine()) != null){ bw.write(str); bw.newLine(); bw.flush(); } bw.close(); br.close();} 32.Class 类 对象照镜子后可以得到的信息:某个类的属性、方法和构造器、某个类到底实现了哪些接口。对于每个类而言,JRE 都为其保留一个不变的 Class 类型的对象。一个 Class 对象包含了特定某个类的有关信息。 Class本身也是一个类 Class 对象只能由系统建立对象 一个类在 JVM 中只会有一个Class实例 一个Class对象对应的是一个加载到JVM中的一个.class文件 每个类的实例都会记得自己是由哪个 Class 实例所生成 通过Class可以完整地得到一个类中的完整结构 33.反射的应用举例 String str = "test4.Person"; Class clazz = Class.forName(str); Object obj = clazz.newInstance(); Field field = clazz.getField("name"); field.set(obj, "Peter"); Object obj2 = field.get(obj); System.out.println(obj2); 34.创建运行时类的对象 //1.根据全类名获取对应的Class对象 String name = “atguigu.java.Person"; Class clazz = null; clazz = Class.forName(name); //2.调用指定参数结构的构造器,生成Constructor的实例 Constructor con = clazz.getConstructor(String.class,Integer.class); //3.通过Constructor的实例创建对应类的对象,并初始化类属性 Person p2 = (Person) con.newInstance("Peter",20); System.out.println(p2); 35.待续
最新回复(0)