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是多核的,为啥不用呢。可以防止程序阻塞。


多线程实现有两种

  • 继承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()方法里面的代码。


  • 实现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();
        }    
    }  
    

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

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

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

    [Top]

    I/O

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

    [Top]

    反射

    可以看另一篇 <JAVA 反射>

    -和C#的不同

    //判断类型  
    if(a instanceof Cat)
    
    //使用父类方法  
    super.method()
    
    //并没有override,只是注释作用  
    @Override
    
    //内部类