Java 笔记

2018-01-01

Java 笔记


Hello World

System.out.println("Hello World")

- Javac

javac -yourJava.java

产生的.class 是由 字节码 组成的
接下来会交给 JVM。

- 操作符

public class Equivalence{
    public static void main(String[] args){
        Interger n1 = new Integer(47);
        Interger n2 = new Integer(47);
        System.out.println(n1 == n2);
        System.out.println(n1 != n2);
    }
} /* Output:
false
true
*///:~

==与!=比较的是对象的引用,所以是 false,如果我们想像操作基本类型那样,我们就需要使用 equals() 方法。

 System.out.println(n1.quals(n2));

[Top]

初始化与清理

构造器:没有返回值(这与 void 是明显不同的)
但他是可以接受参数的,但必须有相同的名字(类名),即 方法重载。

构造器的初始化

    class Window{
        Window(int marker){print("Window("+marker+")")}
    }
    class House{
        Window w1 = new Window(1);
        House(){
            print("House()");
            w3 = new Window(33);
        }
        Window w2 = new Window(2);
        void f(){print("f()");}
        Window w3 = new Window(3);
    }
    public class OrderOfInitialization{
        psvm(){
            House h = bew House();
            h.f();
        }
    } /* Output
    Windows(1)
    Windows(2)
    Windows(3)
    House()
    Windows(33)
    f()
    *///:~

w3 引用被初始化了 2 次,第一次的会被丢弃回收。

从概念是讲,初始化创建是彼此独立的,你找不到initialize()的明确调用的。在 Java 中,两者是捆绑在一起的,无法分离。

垃圾回收

由于 GC 只知道释放那些 new 的内存,所以我们有一个finalize()的方法来回收内存,但注意他与 C++中的析构函数是不一样的,对象不一定会被回收,对象可能不被 GC 回收。(and 不要用它 p90

[Top]

数据结构

数组初始化

int[] a1;
int a1[];

//等价于new的
int[] a1={1,2,3,4,5};

//数组是可以相互赋值的,但只是赋值了一个引用
a1=a2;

//初始化在赋值时才结束的
Integer[] a = new Integer[rand.nextInt(20)]
...
a[i] = rend.nextInt(20)


//Object数组
static void printArray(Object... args){
    for(Object obj : arfs)
        System.out.print(obj+" ");
    System.out.println();
}

psvm{
    printArry(47.3.14F,11.11)
    //在没有新特性之前我们要显示式申明数组,这样
    printArry((new Integer(47),....)
}

enum 和 switch 是好基友。

[Top]

访问权限控制器

package 是定义包的位置
import 是要导入的包

- final 关键字

这个单词意思是,这是无法改变的。

· 修饰基础数据成员的 final

其含义相当于 C/C++的 const,即该成员被修饰为常量,意味着不可修改。

· 修饰类或对象的引用的 final

public final A a = new A();

事实上 a 指向的对象的数据依然可以被修改,不能修改的是 a 本身的引用值,即你不能再对 a 进行重赋值。

· 修饰方法的 final

修饰方法的 final 含义不是“不可修改” !
而是指该方法不可被继承成员重新定义。
final 也可以提高效率,不过这是 SE5 之前的故事了…

[Top]

接口

package com.lin;

interface USB{                              //USB接口
    public void work();
    public void read();
    public void write();
    public void speed();
}

class PC{                                   //PC设备
    public void comm(USB device){           //communicate方法
        device.work();                      //调用usb接口设备的工作方法
        device.read();
    }
}
class Socket{                               //插座设备
    public void comm(USB device){           //communicate方法
        device.work();                      //调用usb接口设备的工作方法
    }
}
class Fan implements USB{                   //风扇实现USB接口功能
    public void work(){
        System.out.println("转转转~");
    }

	public void read() {
		// TODO Auto-generated method stub
		System.out.println("风扇是不读取数据的");
	}

	public void write() {
		// TODO Auto-generated method stub
		System.out.println("风扇是不写入数据的");
	}

	public void speed() {
		// TODO Auto-generated method stub
		System.out.println("风扇是不在意速度的");
	}
}
class Type_c implements USB{                //新式type-c实现USB接口功能
    public void work(){
        System.out.println("Type_c~");
    }

	public void read() {
		// TODO Auto-generated method stub
		System.out.println("Type_c读取很快");
	}

	public void write() {
		// TODO Auto-generated method stub
		System.out.println("Type_c写入很快");
	}

	public void speed() {
		// TODO Auto-generated method stub
		System.out.println("Type_c速度很快");
	}
}
class Micro_usb implements USB{             //旧式micro_usb实现USB接口功能
    public void work(){
        System.out.println("micro_usb~");
    }

	public void read() {
		// TODO Auto-generated method stub
		System.out.println("micro_usb读取很慢");
	}

	public void write() {
		// TODO Auto-generated method stub
		System.out.println("micro_usb写入很慢");
	}

	public void speed() {
		// TODO Auto-generated method stub
		System.out.println("micro_usb速度很慢");
	}
}

class USBDemo{
    public static void main(String[] args){    //主函数
        //买设备
        PC pc = new PC();//pc上的USB使用
        Socket socket=new Socket();//插座也有USB接口
        Fan fan = new Fan();
        Type_c typec = new Type_c();
        Micro_usb microusb = new Micro_usb();
        //pc通过communicate方法,调用相应USB设备功能.
        pc.comm(fan);
        pc.comm(typec);
        pc.comm(microusb);
        socket.comm(typec);
        socket.comm(microusb);
    }
}

所以没有 USBj 接口,我们就要不停的换插头了。

[Top]

重写

例如,父类为 Class animal,并且具有吃肉,吃草等方法。而子类分别为猫,狗,牛等,但是牛是不吃肉的,所以他不会重写吃肉这个方法。但是万一我们的子类太多,我们记不清是否重写了某个类,这时候这种写法就显得很有用了。 这时我们用 Animal a = new niu()来实例化的话,我们先查找吃草的方法时,由于牛这个类中重写了吃草的方法,所以调用的是牛.吃草()的方法,如果我们找吃肉的方法,那么这时调用的就是 animal.吃肉()的方法。

[Top]

内部类

似乎是为了满足闭包性,隐藏方法。
实现多重继承。
可以避免修改接口而实现同一个类中两种同名方法的调用。

[Top]

Collection

List

必须按照插入顺序保存
ArrayList 更适合读取数据,LinkedList 适合添加删除(链表)
Vector(多线程)

Set

无序无下标,不重复
HashSet equals 与==,
SortedSet、ThreeSet

Map (键值对)

object-object HashMap 操作快,允许 null
LinkedMap …

Queue (队列)

FIFO…略

迭代器 Iterator & ListIterator

和 foreach 思维不同的是,他可以修改对象
单项移动 & 双向

一个有趣的的…

public class list {
    public static void main(String[] args) {
        for (Map.Entry entry : System.getenv().entrySet()) {
            System.out.println((entry.getKey() + ": " + entry.getValue()));
        }
    }
}

打印系统环境变量,.getenv 返回一个 Map。entrySet()产生一个由 Map.Entry 的 元素 构成的 Set,并且这个 Set 是一个 Iterble(Iterator 的接口)

[Top]

异常处理

try catch throw finally、 鸡肋 Excaption 和 C#一样

[Top]

字符串

String final 的
StringBuilder 其实用这个更好
其实还有个多线程的
StringReader …

[Top]

重写

- 关于重写 equals & hashCode

可以看另一篇 <关于重写 equals & hashCode>

[Top]

多线程

Q:为啥使用多线程?
A:CPU 是多核的,为啥不用呢。可以防止程序阻塞。

多线程实现有两种

<li>继承 Thread 类,覆盖 run()方法

public class TicketThread extends  Thread{
    private static int tick=100;
    public void  run(){
        while(true){
            if(tick>0)
                System.out.println(Thread.currentThread().getName()+" sale:"+tick--);
        }
    }
}
public class Treads {
    public static void main(String[] args) {
        TicketThread t1=new TicketThread();
        TicketThread t2=new TicketThread();
        TicketThread t3=new TicketThread();
        t1.start();
        t2.start();
        t3.start();
    }
}

在 Thread 中有 start() & run() 方法
区别: 只有调用了 start()方法,才会表现出多线程的特性,不同线程的 run()方法里面的代码交替执行。如果只是调用 run()方法,那么代码还是同步执行的,必须等待一个线程的 run()方法里面的代码全部执行完毕之后,另外一个线程才可以执行其 run()方法里面的代码。

<li>实现 Runnable 接口

Runnable 只有run(),没有 start()
所以,即使实现了 Runnable 接口,那也无法启动线程,必须依托其他类。
实现 Runnable 接口,并不能启动或者说实现一个线程。Runnable 接口,并不能代表一个线程。
而 Thread 类,有一个构造方法,参数是 Runnable 对象,也就是说可以通过 Thread 类来启动 Runnable 实现的多线程.

public Thread(Runnable target) {
     init(null, target, "Thread-" + nextThreadNum(), 0);
}
//实现Runnable接口后,需要使用Thread类来启动
public class MyRunnable implements Runnable {
    private static int tick=100;

@Override
public void run() {
    while(true){
        if(tick>0)
            System.out.println(Thread.currentThread().getName()+" sale:"+tick--);
    }
}
//启动线程还是调用Thread类的start()方法
public class Test1 {
    public static void main(String[] args){
        MyRunnable r1=new MyRunnable();
        MyRunnable r2=new MyRunnable();
        MyRunnable r3=new MyRunnable();

        Thread myT1=new Thread(r1);
        Thread myT2=new Thread(r2);
        Thread myT3=new Thread(r3);
        myT1.start();
        myT2.start();
        myT3.start();
    }
}

<li>关于 Runnable 接口和 Callable 接口的区别

Runnable 只是纯粹的去执行 run()返回值为 void。
Callable 有返回值,是一个泛型,可以帮助我们获取异步执行的结果。

参考文档:http://www.importnew.com/18459.html

sleep()
join()
wait()释放锁标记,等待
notify()唤醒等待

[Top]

I/O

可以看另一篇 <JAVA I/O>

[Top]

反射

可以看另一篇 [](http://rumia.xyz/Java-Reflection/)

-和 C#的不同

//判断类型
if(a instanceof Cat)

//使用父类方法
super.method()

//并没有override,只是注释作用
@Override

//内部类