Thinking in Thinking in Java
in Java with 0 comment

Thinking in Thinking in Java

in Java with 0 comment

而世之奇伟、瑰怪、非常之观,常在于险远,而人之所罕至焉

对象导论 书上的总结,写给自己看的,对于别人没有任何营养

对象

当试图开发一个程序时,最好的办法之一就是把对象当作服务提供者,一个对象只做一件事情。 创建者应该只提供接口给端程序员,隐藏实现细节,让端程序员减少混乱。 我们举个例子,商店是一个类,商店只提供出售这个接口,商店本身有进货,雇员工等方法。 但是商店并不需要提供这些细节给客户,客户在买东西的时候并不需要知道这些细节。

复用

复用是OOP最了不起的优点之一。我们一般有组合和继承两种方法来实现复用。(组合优于继承) 在考虑应该选择复合还是继承时我们需要先造个句

只是总结一些我对java知识点的遗漏

对象储存的位置

Java中可以动态分配内存来new对象,那么对象会被放在什么地方呢 计算机中有堆和堆栈,对象被储存在堆栈中

Java doc

Java doc开始于/**,结束于*/ 注意,javadoc只为public和protected成员进行文档注释。private和包内可见的注释会被忽略掉。用-private参数可以导出。

常量与运算符

equals默认实现是比较引用指向的对象是否是同一个。 指数计数法 1.3X10^5可以计为1.3e5 位移操作符

对char byte short运用操作运算符会转成int

方法的变量不会自动初始化,类的域会。但是还是不要让他自动初始化了= =。

Java中并没有goto,取而代之的是break label和continue label。 标签只能声明在循环上一行。方便我们跳出循环。 ##构造对象 多个构造函数用不同的参数来区分,甚至顺序不同也是可以区分出来,但正常情况下不要用,会让代码难懂

this构造方法

this()可以调用构造方法。可以减少重复代码。

this还可以在内部类中用来引用外部类。

#!java
public class Student {
    private String name;
    private String id;

    Student(String name) {
        this.name = name;
    }

    Student(String name, String id) {
        this(name);
        this.id = id;
    }
}

垃圾回收杂谈

首先我们要搞清楚一个概念,当一个对象可以被回收时,对象并不会被马上回收甚至都不一定会被回收,只有当内存不够用或者程序退出的时候才会回收。 我们看一下几种垃圾回收的方法。 ###引用计数 每一个对象持有一个计数器,当引用连接时计数器+1,当引用离开作用域时或者被置为null时-1 垃圾回收器会把全部的对象遍历一遍,回收引用为0的对象。因为这种方式比较慢所以java不用它。(喂那你说他干什么) ###自适应 自适应垃圾回收技术会在两种模式之间切换。

枚举类型

枚举类型中的变量每一个都可以看作是一个单独的类。由于枚举和switch都是从有限中的数量来选择的,所以枚举和switch是绝配。

对象初始化之时

static对象只有在第一次被引用或者持有他的对象被引用的时候会被初始化 A类中有static B,当A被引用的时候,B才会new出来。 在类中对象没有初始化会被置为默认值,在方法中没有初始化则不会有默认值,而且引用会使编译通不过。

#!java
public class Test {
    static String a;
    public static void main(String[] args) {
        System.out.print(a); //返回null
    }
}

#!java
// 编译失败
public class Test {
    public static void main(String[] args) {
        String a;
        System.out.print(a); 
    }
}

###数组的初始化 初始化数组 最后一个数组中,可以多出逗号。

#!java
int[] a = new int[50];
int b[] = new int[50];
int[] c = new int[] {1,2,};

初始化有四种写法---孔乙己

  1. 在定义对象的地方,会在构造器被调用之前初始化
  2. 在类的构造器中
  3. 惰性初始化,在被使用之前初始化。用法:if(xxx==null) {初始化}
  4. 用实例初始化(在大括号中初始化)

#重写后父类的方法被覆盖,即使向上转型也是调用子类重写后的方法,想要调用父类原来的方法也只能采用反射 写了这么久java连这个都没搞清楚的我= =

#!java
public class Student extends Person {
    @Override
    void sleep() {
        System.out.print("Student sleep");
    }
}

class Person {
    void sleep() {
        System.out.print("person sleep");
    }
    static void sleepPerson(Person person) {
        person.sleep();
    }
}

关于代理和装饰器模式

代理和装饰者是相反的,代理限制类的方法访问,减少提供的功能。装饰器则是增加了类的功能 待填坑

final

Java中final保证能在引用前被初始化。 final方法在java早期中,会被作为内嵌方法,但是现在的jvm中会自动识别,所以没说没卵用。 final方法只有当你的方法不想被重载时才需要用到。

访问权限控制

访问权限控制本质上是把动的事物和静的事物分开来。作为一名类库设计人员,你要尽可能把一切设置为private,只提供愿意让客户端程序员访问的方法。 打个比方,你设计一只猫,当它饿了的时候会喵喵叫

#!java
public class Cat {
    public boolean hungry = false;
    public String meow= "喵喵喵";
    public void meow() {
        System.out.println(meow);
    }
}

你的本意是好的,但是由于你设计有问题,如果有傻逼程序员这样用你的代码

#!java
System.out.println(new Cat().meow);

这样运行也没有什么问题。 但是你突然发现了一个bug!忘记判断是否饿了了 于是你加上去

#!java
public class Cat {
    public boolean hungry = false;
    public String meow= "喵喵喵";
    public void meow() {
        if(hungry)
            System.out.println(meow);
    }
}

但是之前那个傻逼程序员的程序运行就不正常了。 如果你一开始设计猫的叫声为不可访问,程序员就必须通过meow()方法来调用猫叫了,你可以随心所欲的修复问题而不担心别人的程序被破坏。 这里动的事物是内部实现,而静的事物是对外提供的方法。

类不能是 private 或者 protected 的,内部类例外,如果你不想类被别人创造,则用private构造器即可

##多态 Java中除了static方法和final方法,其他的方法都是后期绑定的。,这里注意方法,域不是动态绑定的,访问域的操作由编译器解析。

#!java
public class Point {
    public int i = 0;
    protected int get() {
        return i;
    }
}
class Poi extends Point {
    public int i = 1;
    @Override
    protected int get() {
        return i;
    }
}

main方法

        Poi poi = new Poi();
        System.out.println(poi.get()); // 1子类的方法
        System.out.println(poi.i); // 1子类的域
        Point point = (Point)poi;
        System.out.println(point.i);  // 0父类的域
        System.out.println(point.get()); // 1子类的方法

由此可以看出,只是方法才会被动态绑定。

当有父类方法在构造方法中调用被覆盖的方法,初始化子类的时候会怎样呢?

  1. 覆盖父类方法
  2. 调用父类初始化方法,期中调用的方法是子类的方法
  3. 子类的域被初始化
  4. 调用子类构造方法

Java SE5中,有一个Son继承Father, Father有一个返回Father对象的方法,当Son覆盖这个方法时可以返回Son对象

接口

抽象类

如果一个类包含一个或者多个抽象方法,则一定要被声明为抽象的。当然不是所有的方法都必须是抽象的。 ###接口的域 接口中所有定义的待实现方法都是public的,无论你写不写public。 接口可以带有域和方法,不过他们都是static和final的。

实现多个接口

一个类可以实现多个接口并且转型为每个接口,每个接口都是一个单独的类型。

Java中类不能多重继承,但是接口可以哟

interface A extend B,C,D,E,F,G {
}

适配器模式 https://www.cnblogs.com/denisyxc/archive/2009/07/29/1533734.html 接口实现策略模式 https://blog.csdn.net/chenjie19891104/article/details/6396458 接口实现回调 https://www.cnblogs.com/xrq730/p/6424471.html

Java中的容器

Collection的方法

contains判断是否含有这个元素,containsAll可以求出两个Collection是否为包含关系 retainAll可以求出两个Collection之间的交集。 ---上面的方法和顺序都没有关系--- shuffle打乱Collection,sort排序。

toArray方法可以转成一个数组

对于List来说,有subList可以取出子集。

Collection的初始化

Collection有

Map比较特殊,除了接受另外一个Map外没有其他的初始化形式。

各种Collection之间的区别

List

ArrayList 底层由数组实现,一开始创建10个元素的数组,当不够用的时候会自动扩容并且把原来的元素复制过去,随机访问元素较快,插入和删除慢。 LinkedList 底层是由链表实现的,所以插入和删除元素较快,提供了顺序访问的优化。

LinkedList的特殊用法 通过查看源码,我们可以看得出来,LinkedList实现了Deque接口,Deque继承了Queue接口。 那么就是说,我们可以把LinkedList向上转型成Queue来使用。

转型成queue后

返回null或者false抛出异常
插入offeradd
查看队首peekelement
查看并且删除队首pollremove

PriorityQueue 好像没什么可以讲的

Set

迭代器

迭代器是我非常喜欢的一个东西,在Java中仅次于toString了。 这里注意一下数组不会自动转成Iterable类型。 当类实现了迭代器会非常顺手。Collection都实现了Iterable接口,我们可以写一个方法,它不需要知道容器类型

#!java
    static <T> void display(Iterable<T> iterable) {
        for(T i:iterable) {
            System.out.println(i);
        }
    }

可以说,迭代器统一了容器的访问形式。

自定义迭代器

一般想用for each来遍历我们的类,我们可以实现Iterable接口,在接口中实现iterator方法,返回一个Iterator对象

class My<T> implements Iterable<T> {
        @Override
        public Iterator iterator() {
            return new Iterator() {
                @Override
                public boolean hasNext() {
                    return false;
                }

                @Override
                public Object next() {
                    return null;
                }
            };
        }
    }

当然,当需要多种顺序的时候,我们可以提供getIterable方法, 在方法中返回实现了Iterable的内部类即可。

interface Interface {
    void doSomething();
}

class RealObject implements Interface {

    @Override
    public void doSomething() {
        System.out.println("do something");
    }
}

class Proxy implements Interface {
    private Interface proxied;

    public Proxy(Interface proxied) {
        this.proxied = proxied;
    }

    @Override
    public void doSomething() {
        System.out.println("dododo");
        proxied.doSomething();

    }
}

public class Main {
    public static void main(String[] args) {
        RealObject object = new RealObject();
        Proxy proxy = new Proxy(object);
        proxy.doSomething();
    }

}

剩下的分篇整理在本地文件里了。