【笔记】Java核心技术卷一读书笔记

第三章

  1. Java是一种强类型语言。
    https://blog.csdn.net/qq_3619...
  2. 在Java中,整型的范围与机器无关。
    int 4字节
    short 2字节
    long 8字节
    byte 1字节
  3. 子串:Substring
    拼接:String.join
    String类对象是不可变字符,可经过substring+”” 改变字符串变量
    不能用==来比较字符串,应该用equals。一个常量和一个变量比较,推荐把常量写在前面
  4. 任何一个Java对象均可以转换成字符串
  5. 输入输出
    首先要构造一个Scanner对象。
    Scanner类有各类方法,nextLine()读取一行,next()读取一个单词,nextInt()读取一个整数,nextDouble()读取一个浮点数。
  6. Java提供了一种带标签的break语句。只能跳出语句块,而不能跳入语句块。
  7. 大数值BigInteger类
  8. for each循环(加强for)html

    for(int element:a)
        System.out.println(element);
        public class Main {
        public static void main(String[] args) {
            System.out.println("Hello World");
        }
    }
  9. 底层使用的是迭代器,因此在遍历的过程当中,不能对集合中的元素进行增删。目标只能是Collection或者是数组。
  10. Arrays.copyOf能够拷贝数组,若是直接b=a,拷贝的是数组地址值,改变b会改变a

第四章、对象和类

  1. 类之间最多见的关系有
    依赖(uses-a):一个类的方法操纵另外一个类的对象。尽量的将相互依赖的类减至最小。
    聚合(has-a):觉得着类A的对象包含类B的对象
    继承(is-a):
  2. 构造器(构造方法)用来构造并初始化对象。经过new关键字构造一个新对象。构造器与其余方法有一个重要的不一样,构造器老是伴随new操做符的执行被调用,而不能对一个已经存在的对象调用构造器来打到从新设置实例域的目的。构造器没有返回值
  3. 一个对象变量并无实际包含一个对象,而仅仅引用一个对象,如:java

    Date deadline = new Date();

    有两个部分。New Date()构造了一个Date类型的对象,它的值是新建立的对象的引用。这个引用储存在deadline中。segmentfault

  4. 静态域、静态方法(用static修饰)伴随着类一直存在。静态方法经过类名调用。调用静态方法不须要建立实例(这也是main是静态方法的缘由)。
    https://www.cnblogs.com/LZL-s...

    静态方法只能访问静态域。数组

  5. 在下面两种状况下使用静态方法:
    一个方法不须要访问对象状态,其所需参数都是经过显示参数提供(如:Math.pow)
    一个方法只须要访问类的静态域
  6. Java中方法参数的总结(Java中都是值传递,而不是引用传递):
    https://segmentfault.com/a/11...
    一个方法不能修改一个基本数据类型的参数(数值型或布尔型)
    一个方法能够改变一个对象参数的状态
    一个方法不能让对象参数引用一个新的对象(Java中值传递的体现)
  7. 当且仅当类没有提供任何构造器时,系统才会提供一个默认的构造器。
  8. 类设计技巧:P144

第五章、继承

  1. this的两个主要用途:一是引用隐式参数,二是调用该类其余的构造器;
    super的两个主要用途:一是调用超类的方法,二是调用超类的构造器。
    调用构造器时,二者很类似,调用构造器的语句只能做为另外一个构造器的第一条语句出现。
  2. Java不支持多继承。Java中多继承可经过接口实现。
  3. 多态、向上转型和向下转型:
    https://www.cnblogs.com/bette...
  4. 父子类构造方法:子类构造方法必须调用父类构造方法。不写则有一个默认super()自动调用父类无参构造方法,若是父类没有无参构造方法,会报错,这时需在子类重载父类已有的有参数的构造方法便可。并且super重载必须是子类构造方法的第一句。
  5. 子类重写方法的返回值范围必须【小于等于】父类方法的返回值。例如父类返回值是void,子类是int,报错;父类返回值是Object,子类是String,不报错。
    子类方法的权限必须【大于等于】父类方法的权限修饰符
  6. 关于静态绑定和动态绑定:
    https://www.cnblogs.com/bette...
  7. final:一个方法被声明为final,子类不能覆盖重写这个方法。一个域被声明为final,构造对象以后不能改变值。一个类声明为final,只是其中的方法自动成为final,不包括类中的域。
  8. 内联:若是一个方法没有被覆盖而且很短,编译器就可以对它进行优化处理,这个过程称为内联。(挖个坑,之后学到JVM时来填)
  9. 抽象方法必须在抽象类中
  10. 抽象类除了抽象方法,还能够包含具体数据和具体方法。例如Person类能够保存姓名和一个返回姓名的具体方法ide

    public abstract class Person
    {
        private String name;
        public Person(String name)
        {
            this.name = name;
        }
    
        public abstract String getDescription();
    
        public String getNmame();
        {
            return name;
        }
    }

    尽可能将通用的域和方法(不论是否是抽象的)放在超类(不论是否是抽象类)中。工具

  11. 类即便不含抽象方法,也能够将类声明为抽象类。
    抽象类不能被实例化,若是将一个类声明为abstract,就不能建立这个类的对象
    注意:能够定义一个抽象类的对象变量,可是它只能引用非抽象子类的对象。例如优化

    Person p = new Student("Vince Vu", "Economics");
    //p是一个抽象类Person的变量,Person引用了一个非抽象子类Student的实例

    能够理解为多态/向上转型this

  12. 只有基本类型不是对象,例如:数值、字符、布尔类型的值。
  13. Object中的equals方法,若是是基本类型比较的是值,若是是对象比较的是地址值。String重写了equals方法,比较的是两字符串的内容是否相等。
    https://www.cnblogs.com/dolph...

    数组可使用静态的Arrays.equals检测相应的数组元素是否相等。重写equals来比较两个对象的建议:P169。IDEA直接能够自动生成重写的equals和toString方法。。。
    重写equals,记得参数列表为(Object other)。(重写:在继承中,方法的名称同样,参数列表也同样;重载:方法名称同样,参数列表不同)
    getClass()是使用反射技术来判断对象所属的类。.net

  14. 不一样的两个对象可能会有相同的散列码,因此重写equals就必须重写hashCode方法。P170。
    https://www.cnblogs.com/dolph...
  15. toString是一种很好的调试工具。数组可经过Arrays.toString。建议每个类都添加toString方法
  16. ArrayList:
    https://www.cnblogs.com/bette...
  17. 自动装箱和拆箱:
    有一个颇有用的特性,便于添加int的元素到ArrayList<Integer>:设计

    list.add(3);

    将自动变换成

    list.add(Integer.valueOf(3));

    这种变化称为自动装箱(autoboxing)(基本类型的数据->包装类)

    相反地,当一个Integer对象赋给一个int值时,将会自动的拆箱(包装类->基本类型的数据),包装类没法直接参与运算

    int n = list.get(i);

    自动变成

    int n = list.get(i).intValue();

    在算数表达式中也可以自动的装箱和拆箱

    Integer n = 3;
    n++;

    编译器将自动地插入一条对象拆箱的指令,而后进行自增计算,最后再将结果装箱。
    比较两个包装器对象时要调用equals,若是用==可能会出错。

  18. 包装器中包含了一些基本方法,如一个整数字符串转换成数值

    int x = Integer.parseInt(s);

    这里与Integer对象没有任何关系,parseInt是一个静态方法,Interger类只是放置这个方法的地方。
    Integer.toString()能够把一个整数转换成字符串

  19. Integer对象是不可变的:包含在包装器中的内容不会改变。因此

    public static void triple(Integer x) // won't work
    {
        ...
    }

    不会改变参数值。
    org.omg.CORBA包中定义持有者(holder)类型,能够访问储存在其中的值,进而改变参数值。

  20. 参数数量可变的方法

    // 一个方法只能有一个可变参数;
    // 若是方法的参数有多个,那么可变参数要写在参数的末尾
    public static int max(int... values){
        int lagest=0;
        for (int i = 0; i < values.length ; i++) {
            if(values[i]>lagest)
                lagest=values[i];
        }
        return lagest;
    }
    //可变参数的特殊(终极)写法
    public static void method(Object...obj){
    }
  21. 枚举类型其实是一个类,例如

    public enum Size {SMALL, MEDIUM, LARGE, EXTRA_LARGE };

    这个声明定义的类型是一个类,它恰好有4个实例。
    比较两个枚举类型的值,永远不要用equals,用==。
    枚举类型中能够添加一些构造器、方法和域。

  22. 反射(以后再回来看)
  23. Class类:Object中的getClass()方法能够返回一个Class类型的实例。
  24. 继承的设计技巧:P208

第六章、接口、lambda表达式与内部类

  1. 接口中的全部方法自动地属于public,声明时可省略。可是在实现接口时,必须把方法生命为public
  2. 接口中的变量实际上是常量,接口不容许有实例域(常量)
  3. 实现Arrays中的sort方法:https://blog.csdn.net/qq_3785...
  4. 接口中的方法自动被设置为public,接口中的域自动设为public static final。java语言规范建议不要书写这些多余的关键字。
  5. 引用接口,而不是只用抽象类的缘由是一个类只能继承一个类,可是能够实现多个接口
  6. 接口的默认方法与静态方法:https://www.cnblogs.com/dustc...
    接口的默认方法能够经过接口实现类对象,直接调用
    接口的默认方法能够被接口实现类覆盖重写
    默认方法的主要优点是拓展接口的方法,而不破坏现有代码。
  7. 解决默认方法冲突:

    • 超类优先:若是继承了一个类,实现了一个接口,那么超类优先
    • 接口冲突:若是实现了两个接口有想通的方法,必须经过覆盖来解决冲突
  8. lambda
  9. 内部类包括成员内部类、局部内部类和匿名内部类
  10. 如何使用成员内部类:
    间接方式:
      在外部类的方法中,使用内部类,在外部类方法中建立内部类对象,经过内部类对象调用内部类方法,main只是调用外部类的方法。经过外部类的对象,调用外部类的方法,里面间接再使用内部类

    public class Outer
    {
    
        public class Inner{
            public void show(){
                System.out.println("内部类的方法");
            }
        }
    
        public void method(){
            System.out.println("外部类的方法");
            Inner inner = new Inner();            //建立内部类对象
            inner.show();                                //经过内部类对象调用内部类方法
        }
    
    }
    //经过调用外部类对象,调用外部类的方法
    public class Main
    {
        public static void main(String[] args) {
            Outer outer = new Outer();
            outer.method();
        }
    }

    直接方式:

    //类名称  对象名  =  new  类名称();
    //【外部类名称.内部类名称  对象名  =  new  外部类名称().new  内部类名称();】
    public class Main
    {
        public static void main(String[] args) {
            Outer.Inner inner = new Outer().new Inner();
            inner.show();
        }
    }
  11. 内部类既能够访问自身的数据域,也能够访问建立它的外围类对象的数据域。(内用外,随意访问;外用内,须要先创建内部类对象,经过内部类对象访问)
    没重名可直接调用外部类数据域,若是重名,经过【外部类名称.this.外部类成员变量名】来调用。

    public class Outer
    {
    
        private int num = 100;
        public class Inner{
            final int num = 200;
            public void show(){
                int num = 300;
                System.out.println(num);//300
                System.out.println(this.num);//200
                System.out.println(Outer.this.num);//100
            }
    
        }
    }
  12. 局部内部类定义:若是一个类是定义在一个方法内部的,那么这就是一个局部内部类。“局部”:只有当前所属的方法才能使用它,除了这个方法外面就不能用了。
    访问局部内部类,是经过调用外部类包含该内部类的方法

    public class Outer
    {
    
        public void methodOuter(){
            class Inner {
                int num = 10;
                public void methodInner() {
                    System.out.println(num);
                }
            }
    
            Inner inner = new Inner();
            inner.methodInner();
        }
    
        public static void main(String[] args) {
            Outer obj = new Outer();
            obj.methodOuter();
        }
    }
  13. 类的权限修饰符:
    public > protected > (default) >private
    定义一个类的时候,权限修饰符:

    • 外部类:public / (default)
    • 成员内部类:public / protected / (default) / private
    • 局部内部类:什么都不能写
  14. 局部内部类想访问所在方法的局部变量,这个局部变量必须是【有效final的】,即final或者没有更改过的

    class Outer
    {
        public void methodOuter(){
            final int num = 5;
    //        num = 9;   错误
            class Inner {
            
                public void methodInner() {
    
                    System.out.println(num);
                }
            }
     
        }
    }
  15. 匿名内部类:若是接口的实现类,(或者是父类的子类)只须要使用惟一的一次,那么这种状况下就能够省略该类的定义,二改成使用【匿名内部类】。

    /*
    匿名内部类格式
    接口名称  对象名  =  new  接口名称(){
    //覆盖重写全部抽象方法
    };   //注意要有分号
    */
    public static void main(String[] args){
        //匿名内部类
        MyInterface obj = new MyInterface(){    //new表明建立对象的动做                                                              //接口名称是匿名内部类须要实现的接口
            @Override                                            //大括号中的内容才是匿名内部类的内容
            public void method(){
    
            }
        };
        obj.method();
    }
    /*
    注意:
    1.匿名内部类,在【建立对象】的时候,只能使用惟一一次。若是但愿屡次建立对象,并且类的内容同样的话,那么就必须使用单独定义的实现类了。
    2.匿名对象,在【调用方法】的时候,只能调用惟一一次。若是但愿同一个对象,调用屡次方法,那么必须给对象起一个名字。
    3.匿名内部类是省略了【实现类/子类名称】,可是匿名对象是省略了【对象名称】。匿名内部类和匿名对象不是一码事!!

    匿名内部类做用:不用专门写一个类来实现接口,直接使用匿名内部类调用接口。

    若是想重复使用,就不要用任何匿名的东西。不论是匿名内部类仍是匿名对象。

    //若是有两个对象,要写两遍
    //使用匿名内部类
    MyInterface objA = new MyInterface(){
        @Override
        public void method(){
            System.out.println("匿名内部类实现了方法!");
        }
    };
    objA.method();
    
    MyInterface objB = new MyInterface(){
        @Override
        public void method(){
            System.out.println("匿名内部类实现了方法!");
        }
    };
    objB.method();

    匿名对象:

    //使用了匿名内部类,并且省略了对象名称,也是匿名对象
    new MyInterface(){
        @Override
        public void method1(){
            System.out.println("匿名对象匿名内部类实现了方法1");
        }
    
        @Override
        public void method2(){
            System.out.println("匿名对象匿名内部类实现了方法2");
            }
    }.method1();
    //匿名对象只能调用一次方法
    //若是还想调用method2还要建立一个新的匿名对象
    new MyInterface(){
        @Override
        public void method1(){
            System.out.println("匿名对象匿名内部类实现了方法1");
        }
    
        @Override
        public void method2(){
            System.out.println("匿名对象匿名内部类实现了方法2");
            }
    }.method2();
    //若是想重复使用,就不要用任何匿名的东西
  16. 内部类是一种编译器现象,与虚拟机无关
相关文章
相关标签/搜索