• [读书笔记]java核心技术


     

    ps:有时间好好整理下格式。从别的编辑器拷贝过来啥都没了。

    ~~~~~~~~~~~~~~·

    2、java程序设计环境

    JDK 开发java使用的软件;
    JRE 运行java使用的软件;
    SE 用于桌面或简单服务器应用的java平台--废弃
    EE 用于复杂服务器应用的java平台--通用。
    ME 手机或其他小型设备的java平台--废弃
    库源文件和文档: src.zip---包含了所有公共类库的源代码。
    JDK目录结构:
    bin 编译器和工具, demo演示, docs 类库文档,include 用于编译本地方法的文件,jre运行环境文件,lib 类库文件,src类库源文件。
    命令行
    javac程序是java的编译器,把java后缀的文件编译成.class文件,并发送到java虚拟机,虚拟机执行编译器放在class文件中的字节码。
    注意大小写,编译时需要文件名,运行时需要类名。
    appletviewer程序 ,jdk自带的快速测试applet,需要提供一个HTML文件名。可在浏览器中启用applet查看。

    3、java的基本程序设计结构

    System.out.println("xxxx"); //out.print输出不换行。
    大小写敏感,类名已大写字母开头,文件名必须与公共类的名字相同,用.java扩展。强调main也public。
    /** 这种注释可以自动生成
    *文档*/ //换行时加个* 明显标识
    强类型语言,8种基本类型(4整型、2浮点、1Unicode编码的字符单元char,1boolean);
    1整型 没有小数部分的数值,可负数, int 4字节 ,short 2字节,long 8字节 , byte 1字节;
    与运行java代码的机器无关。长整型数值加后缀L,数字加下划线只为了让人更易读,编译器会去除。
    2浮点类型 float4字节,double8字节 。float类型数值有后缀F(3.14F),没有默认是double(或加D)。
    Double.NaN 不是数字?
    if(x == Double.NaN) //永远false,
    if(Double.isNaN(x)) //检查x
    浮点型不适用于禁止出现舍入误差的金融计算。 System.out.println(2.0-1.1)将打印0.89999999。
    使用BigDecimal类实现这类运算。
    3char类型 单字符,
    转义字符 退格, 制表, 换行=u000a, 回车=u000d,
    Unicode 范围从u0000-uffff。
    JDK5.0开始, 代码点(code point)与一个编码表中的某个字符对应的代码值;看不懂喽~P52~
    4boolean 类型,false和true,和整型值不能进行相互转换。
    用final指示常量,
    final double PI=3.14; //名称全大写
    用strictfp关键字指定方法必须使用严格的浮点计算来产生理想的结果。
    位运算>>>用0填充高位,>>用符号位填充高位。
    Math类注重性能,如果注重结果使用StrictMath类;
    对浮点数进行舍入运算,得到最接近的整数 Math.round(x);--round默认返回long类型。
    枚举: enum Size{ SMALL,MEDIUM,LARGE,EXTRA_LARGE}; Size s=Size.SMALL;
    字符串
    s.substring(0,3);
    String 类对象称为不可变字符串,
    s.equals(t) //是否相等。 不区分大小写用 equalsIgnoreCase;
    空串是"",长度0的字符串, if(str.length()==0) //检查空串
    if(str!=null) //检查是否null;
    char charAt(int index)
    boolean endsWith(String suffix);
    toLowerCase/toUpperCase, 小写/大写
    构建字符串 StringBuilder类比拼接(+)高效;
    StringBuilder sb=new StringBuilder(); sb.append(chOrStr); sb.toString();
    StringBuffer效率低点,但允许多线程执行 添加或删除字符;
    所在包 java.lang.StringBuilder
    void setCharAt(int i, char c);将i位置设置为c;
    StringBuilder insert(int offset, StrOrChar s);
    StringBuilder delete(int startIndex, int endIndex);
    输入输出
    System.out.println ,输出
    标准输入流 需要构造一个Scanner对象 // 所在包 import java.util.*;
    Scanner in=new Scanner(System.in);
    String name=in.nextLine();//读取一行
    String aWord=in.next();//读取直到遇到空格;
    int age=in.nextInt();
    boolean hasNext(); hasNextInt();
    Scanner类是输入可见的,不适合密码;
    Console cons=System.console(); char[] passwd = cons.readPassword("Password:");
    包:java.io.Console
    System.out.printf("%,.2f",1000.0/3.0); //打印 3,333.33
    可使用多个标志, +正负号,-左对齐,.分组分隔符,(负数加括号;
    可使用String.format方法创建一个格式化的字符串但不打印;
    时间日期 System.out.printf("%tc", new Date());
    c 完整日期和时间, F :2004-02-09 ,D 02/09/2004, T 24小时时间18:05:19,
    文件输入输出
    读入文件Scanner in=new Scanner(Paths.get("myfile.txt")); //java.util.Scanner
    写入文件PrintWriter out=new PrintWriter("myfile.txt");//如果文件不存在则创建;java.io包
    out.println("you can !");
    写入后需调用out.flush(); 刷新流;
    用户路径 String dir=System.getProperty("user.dir"); //java.nio.file.Paths
    如果用不存在的文件构造一个Scanner,或不能被创建的文件名构造一个PrintWriter,会异常;
    在方法中用throws子句标记, void sub() throws FileNotFoundException {};
    流程控制
    while(condition)statement;
    do statement while(condition);
    for(int i=1; i<=10; i++){}
    switch(x){ case 1: break; ...}
    -不建议使用switch,可在编译时加 -Xlint:fallthrough选项,强制少break警告;
    -也可在外围方法加标注@SuppressWarnings("fallthrough");消除警告;
    带标签的break和continue:标签是 name:, break/continue到标签后的语句块末尾,再检查是否正常退出语句块; 都不建议使用;
    大数值 java.math 中的 BigInteger和 BigDecimal。可任意长度;
    BigInteger a = BigInteger.valueOf(100); a.add(b);//不能用 + - * /
    int compareTo(BitInteger other);//0相等,正数是大于,负数是小于;
    数组
    int[] a=new int[100];
    System.out.println(Arrays.toString(a));//输出"[a1,a2.....]"
    数组不能改变大小, 数组列表(array list)才可以。
    for(variable: collection)statement; //实现了Iterable接口的类对象也可以。
    初始化 int[] a={2,3,4}; //不需要new
    int[] a=new int[]{2,3,4};
    数组拷贝 int[] a= Arrays.copyOf(b, x * b.length); //通常用来增加数组的大小;
    排序 Arrays.sort(a);//优化的快速排序算法;
    Math.random() 返回0到1(包括0,但不包括1)的随机浮点数;
    抽取算法:用数组最后的元素值改写抽取值,然后数组可用长度减一;
    numbers[r] = numbers[n - 1]; n--;
    static int binarySearch(type[] a, type v);//二分搜索算法查找值v
    static void fill(type[] a, type v); //数组所有填充值v;
    多维数组 int[][] x;
    System.out.println(Arrays.deepToString(x));//输出"[[3,2...],[a1,a2.....]...]"

    4 对象与类

    三主要特性: 行为、状态、标识;
    类之间的关系 依赖(uses-a)、聚合(has-a)、继承(is-a);
    对象与对象变量的区别; 一个对象变量并没有实际包含一个对象,仅仅引用;
    日历类 GregorianCalender类,
    表示时间点的Date类:时间是用距离一个固定时间点(纪元 1970-01-01 00:00:00)的毫秒数标识的,
    GregorianCalender thisTime=new GregorianCalender(); //月份从0开始计数。
    int month = thisTime.get(Calendar.MONTH); //通过常量和访问器来获取年月日等,
    thisTime.set(属性,value);thisTime.add(属性,vlaue);
    Date time=thisTime.getTime();//setTime(time); 转换。
    int firstDayOfWeek = d.getFirstDayOfWeek();//一个星期中的第一天;
    java.text.DateFormatSymbols 下面有几个格式输出方法
    String[] getShortWeekdays()/ getShortMonths();
    自定义类 在一个源文件中,只能有一个公有类;
    警告: 不要编写返回引用可变对象的访问其方法;这个引用可能在外面被改写,破坏了类的封装。
    代替用 对象的clone();
    静态域与静态方法
    static修饰的变量,所有实例共享一个静态域; 可用于标识实例;
    private static int nextId=1; private int id;
    void setId(){ id=nextId; nextId++;}
    System有setOut方法,是本地方法,可设置不同的流,不是用java实现的。不推荐。
    可使用对象名调用静态方法但不推荐;
    工厂方法: 静态方法的常见用途,构造不同对象;
    每一个类可以有个main,用作单元测试。
    方法参数:java总是按值传递,没有引用调用!对象引用进行的也是值拷贝传递;
    对象构造
    重载,多个构造器(通过不同的方法签名-方法名和参数 实现);
    默认域初始化,没有显式的构造器。不推荐,影响代码可读性;
    无参构造器,常用;
    参数名
    public Employee(String aName, int aAge){name=aName;}//用a前缀;
    public Employee(String name, int age){this.name=name;}//用this访问当前对象
    用this在构造器中调用另一个构造器,重用代码;
    public Employee(int age){ this("NewName",age);}
    初始化块
    一个类的声明中,可以包含多个代码块, {xxxx; xxx; xxxxxxx;}
    三种初始化数据域的方法:构造器中赋值,声明时赋值,初始化块中赋值。
    初始化块先于构造器执行;
    static 修饰的块只执行一次,其他的每次类实例化都执行;
    调用构造器的具体步骤
    a、所有数据域被初始化为默认值(0/false/null);
    b、按声明中出现的次序,依次执行初始化语句和初始化块;
    c、如构造器1调用了构造器2,则先执行2,再执行1。
    对象析构与 finalize方法
    Java不支持析构器;但当使用了文件或另一系统资源的句柄,使用finalize方法,它在垃圾回收器清除对象之前调用。实际中,不要依赖于该方法回收任何短缺的资源——不知道何时才回收。
    使用关闭勾:Runtime.addShutdownHook,可确保在Java关闭前调用finalize方法;
    包package
    确保类名的唯一性;嵌套的包之间没有任何关系!
    调用其他包的类,可在类名之前加包名,或 用import语句;
    静态导入 用import可导入静态方法和静态域;
    import static java.lang.System.*; //可使用System的静态方法和静态域;
    out.println("xxxx"); exit(0);
    包作用域 不显示声明private的类、方法、变量,可被同一包的所有方法访问;破坏封装。
    类路径 类路径必须与包名匹配;
    JAR(Java归档)文件,可以用压缩文件工具打开查看JAVA文件;
    共享类需要: P156的4.8类路径,暂时不懂。
    文档注释
    工具javadoc,由源文件生成一个HTML文档;
    以专用的定界符/**开始的注释, 和代码同步;
    javadoc的程序utility抽取信息(包、公有类和接口等),信息是自由格式文本,标记有@开始, 文本第一句是概要性句子;
    方法注释 @param 标量描述, @return描述,@throws类描述,表示有可能抛出异常。
    @author 姓名 --类注释,作者
    @version 文本 --版本条目
    @since 文本 始于条目,引入特性的版本
    @see 引用 超级链接,可选三种
    @see package.class#feature label
    @see <a href="www.baidu.com">label</a>
    @see "text"
    包注释 需在每一个包目录中添加一个单独的文件,
    以package.html命名的文件,或package-info.java命名的java文件。P162.
    注释抽取 javadoc -d docDirectory nameOfPackage
    类设计技巧
    保证数据私有(不破坏封装);对数据初始化;不在类中使用过多基本类型;缩减set或get访问器;分解过多的职责到其他类;类名和方法名提现职责;
    java不对局部变量初始化,但对对象的实例域初始化。
    比如用Address类代替 String street/city/state等。

    5 继承

    5.1类、超类、子类
    继承是 is-A 关系,关键字extends ,(父类、超类、基类),子类;
    置换法则:出现基类对象的地方都可以用子类置换。 //能置换,所以方法不能降低可见性;
    调用基类方法:super.xxx(); //this是对象引用,super只指示编译器调用超类方法。
    类似super();//调用超类对应构造器;放在自身构造器的第一条语句;
    覆盖 override,
    多态:一个对象变量可指示多种实际类型的现象,运行时自动选择调用哪个方法,称为动态绑定。
    --申明为基类的引用,实际可引用基类实例,也可引用子类实例,虚拟机根据实际的引用来调用相关(公有的,非子类特有新增的)方法。 申明为基类的引用,肯定不能调用子类的方法。
    subA[] aList=new subA[3]; baseA[] sList=aList; //这时aList和sList将指向同一对象;
    aList.subDo(); //ok
    sList.subDo();//ERROR!虽然指向同一个对象。

    方法是private /static/ final 的或构造器,调用它们是静态绑定。
    虚拟机为每个类创建了一个方法表,调用时直接查表;

    阻止继承: final类和方法
    类的特定方法可被声明为final,这样子类不能覆盖它;final类的所有方法自动的称为final方法。
    有些认为:不使用多态的都声明为final。
    早期java中,避免动态绑定带来系统开销而使用final关键字。
    一个方法没有被覆盖且很短,编译器优化(内联 inlining),e.getName()被转换为e.name域,提升效率;
    强制类型转换
    当一个基类声明中引用的确实是子类的对象实例时,可以强制类型转换为子类,或者说,用一个子类的声明去指向这个基类所引用的对象实例;
    BaseA aBaseA=new SubA(); SubA a = (SubA)aBaseA;
    //暂时忽视申明类型,使用对象的全部功能。
    可用 instanceof 关键字 测试 if(a instanceof SubA){dosomething;}
    抽象类 : abstract修饰,且包含一个或多个抽象方法的类本身必须被声明为抽象。
    抽象类还可以包含具体数据和具体方法。
    抽象类不能被实例化,但可以有构造器,在子类的构造器中 用super()调用它;
    使用通配符 编译多文件 :javac *.java; 或javac -d . A.java B.java ,生成到下一级目录。

    受保护访问:protected,仅子类可访问;--修改可能影响子类,违背OOP的封装原则;--对同包其他类都可见。
    控制可见性
    1、仅本类-private; 2 对所有类-public; 3、对本包和所有子类可见-protected; 4、对本包--默认,不需修饰符。
    5.2 Object:所有类的超类
    Object obj=new Employee("name",age);//Object类型的变量可引用任何类型的对象。
    只有基本类型不是对象;数组类型(哪怕基本类型的数组)都扩展于Object类。
    equals 对于对象是判断俩对象是否具有相同的引用。
    通常对类来说是无意义的,所以每个类要实现自己的equals。
    编写一个完美equals的建议:
    0、参数命名otherObject, 显式转换后为other;类型是Object,这样才能完全覆盖超类。
    1、判断引用是否相同 this==otherObject; return true;
    2、判断是否null otherObject==null return false;
    3、判断类型一致 getClass()!=otherObject.getClass() //false
    4、将otherObject强制转换为当前类的对象,判断状态。
    Employee other= (Employee)otherObject;
    Objects.equals(other.name,this.name);
    static Objects.equals(a,b);若a,b都为null,则true,若一个null,返回false;
    static Objects.equals(type[] a,type[] b); 数组长度相同,且对应位置元素也相同,则true;
    子类中定义equals方法时,要先调用超类的equals。
    相等测试与继承 instanceof 判断可能是继承关系,所以不适合这种判断。
    如果equals的语义在子类中有所改变,则用getClass,
    如果没改变,用instanceof,且将超类的eauals声明为final 。
    equals 对任何非空引用,满足 自反性,对称性,传递性,一致性。对于空引用,返回false;
    hashCode方法
    散列码 是由对象导出的一个整型值。Object类的对象默认为其存储地址。
    如果重定义equals,必须重新定义hashCode,以便用户将对象插入得到散列表中。
    一般: Objects.hash(p1,p2,p3);//组合类的多个属性,生成散列码。
    (java.lang.Object 1.0包) int hashCode() 返回散列码,相等的对象要求返回相等的散列码。
    int Objects.hash(o1,o2,o3....) 由提供的所有对象的散列码组合得到新的散列码
    int Objects.hashCode(Object a) 如果a为null则返回0,否则返回a.hashCode()。
    (java.util.Arrays 包) static int hashCode(type[] a) 数组的散列码
    toString方法
    对象的toString可自定义。建议 类名加方括号的域值,如 java.awt.Point[x=20,y=30] ;
    类名用 a.getClass().getName();获取;
    技巧:在需要调用x.toString()的地方,用""+x替代。 这样x是基本类型时也能够执行。
    只要对象与字符串通过"+"连接 ,Java编译就自动调用toString方法。
    也可以用System.out.println(x);//是对象时默认x.toString();
    Object的toString,是输出对象的所属类名和散列码。
    数组用Arrays.toString(a); 多维用Arrays.deepToString(b);
    调试信息: System.out.println("Current ObjectX =" + obj); //需要对象实现自己的toString();
    强烈建议为自定义的每一个类增加toString()方法;
    java.lang.Object包 Class getClass() 返回包含对象信息的类对象;
    java.lang.Class 包 Class getSuperclass()返回类的超类信息;
    5.3泛型数组列表
    Java允许在运行时确定数组大小,int size=100; Employee[] staff=new Employee[size];
    泛型里面的类型参数必须是 Object 的子类。
    ArrayList是采用 类型参数的泛型类, <Employee>指定类型,
    ArrayList<Employee> staff=new ArrayList<>();
    //Vector类是老版本的动态数组, 老版本中的ArrayList类元素是Object,没有泛型。
    数组列表管理着内部数组的引用,若数组已满,则自动创建更大的数组并copy元素到新数组中。
    如已清楚或能估算穿数组元素数量,可调用ensureCapacity方法,分配一个包含指定数量元素的内部数组。
    也可以 ArrayList<Employee> staff=new ArrayList<>(100); //指定数量
    .size()返回实际元素数目。
    .add(x)添加元素, .add(index,x); .remove(n);
    .trimToSize()确认元素不会再增删后,将数组列表的存储容量消减到当前尺寸,剩下的空间以便垃圾回收器回收。
    new ArrayList<T>(); 构造空数组列表;
    new ArrayList<T>(initialCapacity);用指定容量构造一个空数组列表。
    staff.set(i,harry); //set和get 访问元素,注意实际的size;
    5.4对象包装器与自动装箱
    需要将基本类型转换为对象时用到。int-Integer,包装器(wrapper)是final的。
    对象包装器是不可变的!不允许更改便装在其中的值。
    如:ArrayList<int> aInt=new ArrayList<int>();
    报错: Syntax error, insert "Dimensions" to complete ReferenceType。
    泛型数组列表里面的类型参数必须是 Object 的子类,因此不能使用 int,而应该使用 int 的包装器类型 Integer。
    ArrayList<Integer> aInt=new ArrayList<Integer>();
    list.add(3) 自动转换为 list.add(Integer.valueOf(3)); ---自动装箱(autoboxing)。
    int n=list.get(i); 自动转为list.get(i).intValue():自动拆箱;
    类似:Integer n=3; n++; ---- 先拆箱,再自增,再装箱。
    包装器对象比较,调用equals();
    装箱和拆箱是编译器的工作,是语法糖。虚拟机执行的是编译器编译的字节码。
    包装器还可以包含一些数值/字符串 转换方法。
    int x=Integer.parseInt(s);
    System.out.println(Integer.toString(System.out.hashCode(),16));
    toString(int i, int radix) //返回数值i的给定参数进制的表示;
    intValue() 返回包装器的值。
    int x=Integer.parseInt(s,int radix);//radix是说明字符串s的进制表现形式。
    5.5参数数量可变的方法
    Java SE5.0以后提供的,
    如printf,一个格式化字符串,一个Object[]
    public static double max(double...values){
    for(double v : values) if(x)doSomething();} //...是无限参数
    5.6枚举类
    public enum Size{SMALL,MEDIUM,LARGE,EXTRA_LARGE};
    是有4个实例的类; Enum类的子类是Size。
    比较俩枚举值时不需要调用equals,直接==;
    x.toString()将返回字符串;
    Enum Enum.valueOf(Size.class,"SMALL")是逆方法,
    Size.values()返回包含全部枚举值的数组;
    ordinal()返回枚举的位置,从0开始基数。
    int compareTo(E other) 在前为负值,this==other则0,在后则正值。
    5.7反射
    反射库(reflection library),JavaBeans中大量使用。
    能够分析类能力的程序称为反射(reflective)。
    运行中分析类的能力;运行中查看对象;---使用它的主要是工具构造者。
    1、Class类)
    程序运行期间,Java运行时系统为所有对象维护一个被称为运行时的类型标识。
    记录着对象所属的类。
    Object类的getClass()返回一个Class类型的实例;
    Class.forName(className);返回类名对应的Class对象;
    也可以用T.class来获取类对象;
    一个Class对象实际上表示一个类型,但未必一定是类,如int.class。
    可以用==比较类对象;
    x.getClass().newInstance();快速创建一个类的实例;(需要一个无参的构造器)
    forName和newInstance配合使用,可由字符串中的类名创建一个对象。
    String s="java.util.Date";
    Object m=Class.forName(s).newInstance();
    2、捕获异常)
    异常类型: 未检查异常和已检查异常。
    try{ dosomethings();}catch(Exception e){}
    Throwable类(Exception的超类)的printStackTrace()打印出栈的轨迹;
    3利用反射分析类的能力)--暂忽略
    java.lang.reflect包中Field/Method/Constructior分别描述类的域、方法、构造器。
    还有Modifier类的静态方法;
    4运行时使用反射,5使用反射编写泛型数组代码、6调用任意方法)暂忽略
    5.8继承设计的技巧
    1公共操作和域放在超类;
    2不使用受保护的域;
    (子类无限制,谁都可以写个派生类并访问protected实例域,破坏封装)
    (java中,同一个包中的所有类都可以访问proteced域。)
    3使用继承实现 is-a关系;(钟点工不是特殊的雇员,不是is-a关系,不能继承)
    4除非所有继承的方法都有意义,否则也不要使用继承。
    5覆盖方法不产生非预期行为;-覆盖基类的方法时,不偏离最初的设计想法。
    6使用多态,而非类型信息;
    7不过多使用反射;

    6 接口和内部类 

    接口interface-对象克隆-内部类inner class-代理proxy
    6.1接口 对类的一组需求描述,类要遵从接口描述。
    接口中所有方法自动属于public。所有域是public static final。
    更重要的是知道接口不能提供哪些功能。
    接口可以定义常量,但不能含有实例域,也不能有方法实现。
    implements关键字。
    java.lang.Comparable<T>的int compareTo(T other); 小于则负值,相等0,大于正值。
    强制的是 “实现接口”,而不是实现方法。----------一定注意。
    java.util.Arrays包的 static void sort(Object[] a)
    对数组a的元素排序,要求元素必须属于实现了Comparable接口的类。
    如果父子类对象比较的含义不一样,那属于不同对象的非法比较。或者比较定义在超类且final。

    1接口特性)不是类,不能new实例化。但能声明变量,变量引用实现了接口的类对象。
    使用instance检查一个对象是否实现了某个特定接口
    if(anObject instanceof XInterface){}
    接口可以继承接口 interface X extnds xBase;
    接口可以只定义常量,但有点偏离初衷,建议NO。
    6.2对象克隆
    Object类的clone方法默认是浅拷贝。
    对于每一个类,进行如下判断:
    1默认的clone是否满足,2默认的clone是否能通过调用子对象的clone得到修补,3是否不应该使用clone。
    对于不满足1和2的, 实现Cloneable接口,使用public重新定义clone。
    Cloneable接口的出现和接口的正常使用没有任何关系。clone方法是从Object类集成而来。
    接口只作为标记,表明类设计者知道要进行克隆处理。
    ------标记接口tagging interface或者marker interface。用途是可以使用instanceof进行检查。
    即便默认实现(浅拷贝)满足,也该实现Cloneable接口,且定义public并调用super.clone();
    public X clone throws CloneNotSupportedException
    { return (x)super.clone();}
    所有数组类型均包含clone方法,且为public,可以创建一个新数组。
    int[] cloned= luckyNumbers.clone();
    6.3接口与回调 callback
    回调,指出某特定事件发生时采取的动作。
    Java标准类库传递一个对象给定时器,定时器调用其方法;要求对象所属类实现了java.awt.event包的ActionListener接口。里面一个方法void actionPerformed(ActionEvent event);
    定时器调用actionPerformed方法。
    一个例子-明天运行一下。且整理笔记。
    6.4内部类
    已读,笔记待整理。

  • 相关阅读:
    JSTL XML标签库 使用
    JSTL SQL标签库 使用
    JSTL I18N 格式标签库
    基于struts2的ajaxfileupload异步上传插件的使用
    Spring 使用注解方式进行事务管理
    vi编辑器的使用方式
    js基础知识介绍
    选择语句
    数组
    0411作业
  • 原文地址:https://www.cnblogs.com/dacude/p/7487807.html
Copyright © 2020-2023  润新知