查漏补缺
[1].this语句;
this语句用于构造函数之间进行相互调用。
this语句只能定义在构造函数的第一行,因为初始化要先执行。
[2].对象的初始化过程
Person p =new Person("hei",10);
1.因为new用到了Person.class,所以先找到Person.class文件加载到内存中
2.执行类中的静态代码块,如果有的话,给Person.class类进行初始化
3.在堆内存中开辟空间,分配内存地址
4.在堆内存中建立对象的特有属性,并进行默认初始化
5.对属性进行显式初始化
6.对对象进行构造代码块初始化
7.对对象进行与之对应的构造初始化
8.将内存地址赋值给内存中的p变量
[3].对象的执行过程
静态方法调用是 类名.静态方法()
静态属性调动是 类名.属性
注:类名一般省略
非静态的方法调用是 this.方法()
非静态的属性调用是 this.属性
[4]单例
1.将构造函数私有化
2.在类中提供一个本类对象
3.对外提供一个获取本类对象的方法
[5]继承对象的初始化执行过程
package cn.soldier.oop;
class Fu {
public static int fuNum = 23;
int num = 10;
static {
System.out.println("static Fu.enclosing_method()... fuNum=" + fuNum);
}
{
System.out.println("Fu.enclosing_method().... fuNum=" + ++fuNum + " num=" + ++num);
}
// Fu() {
// num = 20;
// System.out.println("Fu.Fu() num=" + ++num);
// }
Fu(int i) {
System.out.println("Fu.Fu(int) i=" + ++i);
}
private static void show() {
System.out.println("Fu.show() fuNum=" + fuNum);
}
}
class Zi extends Fu {
public static int ziNum = 23;
static {
System.out.println("static Zi.enclosing_method()... zinum= " + ziNum);
}
{
System.out.println("Zi.enclosing_method()... zinum=" + ++ziNum + " num=" + ++num);
}
// Zi() {
// System.out.println("Zi.Zi()");
// }
Zi(String zi, int i) {
// this()
super(i);
System.out.println("Zi.Zi((String zi zi=) .... " + zi+" .... i=" + ++i);
}
}
public class hello {
public static void main(String[] args) {
// 测试zi开辟空间先还是Fu开辟空间先
int i = 0;
Zi zi = new Zi("hello", i);
}
}
//下面是打印结果
//static Fu.enclosing_method()... fuNum=23
//static Zi.enclosing_method()... zinum= 23
//Fu.enclosing_method().... fuNum=24 num=11
//Fu.Fu(int) i=1
//Zi.enclosing_method()... zinum=24 num=12
//Zi.Zi((String zi zi=) .... hello .... i=1
1.程序启动找到main方法
2.先将main方法中的i放入栈中,并为其初始化。
3.然后执行到 Zi zi = new Zi("hello", i);
1.先将局部变量 zi放入栈中
2.将Zi.class文件加载进内存,发现Zi类继承了Fu类,又将Fu.class加载进内存。
3.将Fu类的静态成员、静态方法、静态代码块放入方法区静态区域。
4.将Fu类的静态成员默认初始化,如果静态成员有被赋值的话,那么将赋值的静态成员显示初始化。
5.执行Fu类的静态代码块。所以打印的第一行是:static Fu.enclosing_method()... fuNum=23
6.将Zi类的静态成员、静态方法、静态代码块放入方法区静态区域。
7.将Zi类的静态成员默认初始化,如果静态成员有被赋值的话,那么将赋值的静态成员显示初始化。
8.执行Zi类的静态代码块。所以打印的第二行是:static Zi.enclosing_method()... zinum= 23
9.在堆内存中开辟空间,为Fu类分配内存地址.
10.在堆内存中建立Fu对象的成员,并进行默认初始化,如果成员有被赋值的话,那么将赋值的成员显示初始化。
11.将Fu类的方法放入方法区
12.执行Fu类的构造代码块,所以打印的第三行是:Fu.enclosing_method().... fuNum=24 num=11
13.执行Fu类的构造方法,Fu(int)所以打印的第四行是:Fu.Fu(int) i=1
14.在堆内存中开辟空间,为Zi类分配内存地址.
15.在堆内存中建立Zi对象的成员,并进行默认初始化,如果成员有被赋值的话,那么将赋值的成员显示初始化。
16.将zi类的方法放入方法区
17.执行zi类的构造代码块,所以打印的第三行是:Zi.enclosing_method()... zinum=24 num=12
18.执行zi类的构造方法,Fu(int)所以打印的第四行是:Zi.Zi((String zi zi=) .... hello .... i=1
4.将Zi对象内存地址指向zi变量。
5.main方法执行结束
[6]抽象类中可以不定义抽象方法,这样做仅仅是不让该类建立对象。
[7]接口中的修饰成员符是固定的(默认的)。
成员常量:public static final
成员函数:public abstract
[8]多态中的特点
成员函数的特点:
编译时期,参阅引用类型变量所属的类中是否有调用的方法。如果有,编译通过,如果没有编译失败
在运行期,参阅对象所属的类中是否有调用的方法。
成员变量的特点:
编译时期:参阅引用类型变量所属的类
在运行期:参阅引用类型变量所属的类
静态成员函数、静态成员变量的特点:
编译时期:参阅引用类型变量所属的类
在运行期:参阅引用类型变量所属的类
9.内部类,静态内部类,局部内部类,匿名内部类,没有实现接口和继承类的匿名内部类
内部类的特点:
内部类可以直接访问外部类的成员(外部类.this.成员),包括私有成员。
外部类要访问内部类中的成员必须要建立内部类的对象。
package cn.soldier.oop;
public class InnerDemo {
private String name = "InnerDemo";
private static int age = 1;
InnerDemo() {
Inner inner = new Inner();
System.out.println(inner.name);
}
// 内部类
class Inner {
private String name = "Inner";
Inner() {
System.out.println(InnerDemo.this.name);// 默认InnerDemo.this.,可以忽略不写
}
}
// 静态内部类
public static class InnerStatic {
void innerStatic() {
// 只能访问外部类的静态成员
// 非静态内部类中不可以定义静态成员
System.out.println(age);
}
}
public void method() {
final int method_age = 10;
// 局部内部类
class MethodInner {
void function() {
// 不可以被成员修饰符修饰 .
// 可以直接访问外部类中的成员和引用,但是不可以访问它所在的非final变量。
System.out.println(age);
System.out.println(name);
System.out.println(method_age);
}
}
new MethodInner().function();
}
public void method_1() {
// 匿名内部类
// 1.定义匿名内部类的前提:内部类必须继承一个类或实现接口
// 2.其实内部类就是一个匿名子类对象。而且这个对象有点胖
new AbsDemo() {
void show() {
System.out.println("InnerDemo.method_1().show()+ name=" + name);
}
void show1() {
System.out.println("InnerDemo.method_1().show1()+ name=" + name);
}
}.show();
//
new AbsDemo() {
void show() {
System.out.println("InnerDemo.method_1().show()+ name=" + name);
}
void show1() {
System.out
.println("InnerDemo.method_1().show1()+ name=" + name);
}
}.show1();
}
}
abstract class AbsDemo {
abstract void show();
}
class OuterDemo {
public static void main(String[] args) {
InnerDemo.Inner inner = new InnerDemo().new Inner();
new InnerDemo.InnerStatic().innerStatic();
new InnerDemo().method();
new InnerDemo().method_1();
}
}
// 面试题:请构造出下面的写法; *
new Method().method().method();
Method.method().method();
// 分析如下:
Method类中有一个静态方法method()
method()这个方法运算后返回结果是一个对象,而且是一个静态匿名类对象,
该静态匿名类对象继承一个类或实现一个接口,该类或接口里面有一个method()方法。
class Method {
static class _Inner implements Imethod {
public void method() {
System.out.println("Method._Inner.method(),呵呵");
}
}
static _Inner method() {
return new _Inner();
}
}
interface Imethod {
abstract void method();
}
// 面试题:写出一个没有实现接口和继承类的匿名内部类对象
new Object() {//这是Object子类对象,是没有实现接口和继承类的匿名内部类对象
public void function() {
System.out.println("OuterDemo.main()");
}
}.function();
10.
Trowable
|--Error
|-- ...
|--Exception
|--ApplicationException
|--PrintException
|--ArithmeticException
|--ArrayIndexOutOfBoundsException
|--RuntimeException
|-- ...
异常声明 throws
//throws 关键字声明了该功能有可能会出现问题。需要调用者处理。
void show() throws Exception{}
异常声明 throw
void show() throws Exception{
if(true){
throw new RuntimeException();
}
}
throws 与 throw 的区别
throws 定义在函数上 ,后面跟的是异常类,可以多个以逗号隔开。
throw 定义在函数中 ,后面跟的是异常对象。
RuntimeException 及其子类 如果在函数里被抛出可以不用再函数声明。
|--ArithmeticException
|--NullPointerException
|--IndexOutOfBoundsException
|-- ...
之所以不用声明,是因为该异常的发生,不需要让调用者处理。当发生异常时,
设计者希望程序停止,因为出现了无法继续运算的情况。希望通过程序停止后,
使用者对该问题进行修正。
异常在子父类覆盖中的处理。
1.子类覆盖父类时,如果父类的方法抛出异常,那么子类的覆盖方法,只能抛出父类的异常或者改异常的子类。
2.如果父类方法抛出了多个异常,那么子类在覆盖该方法是,只能抛出父类异常的子集(比父类少或相等)。
3.如果父类或者接口的方法中没有异常抛出,那么子类在覆盖方法是,也不可抛出异常,也就是说,如果子类方法发生了异常,只能自己消化不能抛出。
finally 只有一种情况不会执行,
当执行到 System.exit(0);finally{}时不会执行。
自定义异常
继承Exception
或者RuntimeException
//1.具备可抛性,2,具备操作异常的共性方法。
Class MyException extends Exception
{
MyException(String message)
{
super(message);
}
}
11.多线程
多线程的线程安全问题:
当多个语句在操作同一个线程共享数据时,一个线程对多条语句只执行了一部分执行完,另一个线程参与进来执行,导致共享数据的错误。
解决线程安全问题,保证共享数据的操作是线程同步的。
同步的前提:1.一个进程中,必须由两个或者两个以上的线程。
2.多个线程使用的是同一个锁
同步函数的锁是this
静态同步函数的锁是Class对象
死锁问题:同步中嵌套同步,锁不同
public class ThreadDemo {
public static void main(String[] args) {
new Thread(new Testlock(true)).start();
new Thread(new Testlock(false)).start();
}
}
class Testlock implements Runnable {
private boolean flag;
Testlock(boolean flag) {
this.flag = flag;
}
public void run() {
if (flag) {
synchronized (Mylock.locka) {
System.out.println("if locka");
synchronized (Mylock.lockb) {
System.out.println("if lockb");
}
}
} else {
synchronized (Mylock.lockb) {
System.out.println("else lockb");
synchronized (Mylock.locka) {
System.out.println("else locka");
}
}
}
}
}
class Mylock {
static Object locka = new Object();
static Object lockb = new Object();
}
线程间通讯
wait()、notify()、notifyAll()为什么要定义在Object类中?
1.这些方法存在于同步中。
2.使用这些方法是必须要标识所属的同步锁。
3.锁是可以是任意对象,所以任意对象调用的方法一定要定义在Object类中。
wait()和sleep()有什么区别
wait释放资源,释放锁
sleep释放资源,不释放锁
package cn.soldier.oop; import java.util.concurrent.locks.Condition; import java.util.concurrent.locks.Lock; import java.util.concurrent.locks.ReentrantLock; //创建Thread,小秀一手 public class ThreadDemo { public static void main(String[] args) { new TestThread("逗比 ").start(); new TestThread("呵呵 hehe").start(); // for (int i = 0; i < 100; i++) { System.out.println("ThreadDemo.main() -------- " + i); } } } class TestThread extends Thread { TestThread(String name) { super(name); } @Override public void run() { for (int i = 0; i < 100; i++) { System.out.println(this.getName() + "-------TestThread.run() -------- " + i); } } } // 实现Runnable接口,使用synchronized解决多个线程操作共享数据的安全问题 public class ThreadDemo { public static void main(String[] args) { TickeRunnable tickeRunnable = new TickeRunnable(); new Thread(tickeRunnable).start(); new Thread(tickeRunnable).start(); } } // class TickeThread extends Thread { class TickeRunnable implements Runnable { private int tick = 100; Object obj = new Object(); public void run() { boolean flag = true; while (flag) { synchronized (obj) { if (tick > 0) { try { Thread.sleep(100); } catch (InterruptedException e) { } System.out.println("Ticke: " + tick-- + "号,被 " + Thread.currentThread().getName() + " 卖了"); } else { flag = false; } } } } } public class ThreadDemo { public static void main(String[] args) { Cus cus = new Cus(); new Thread(cus).start(); new Thread(cus).start(); } } class Bank { private int sum; public void add(int n) { synchronized (this) { sum = sum + n; System.out.println(Thread.currentThread().getName() + " Bank.add()--- sum=" + sum); } } } class Cus implements Runnable { private Bank bank = new Bank(); public void run() { for (int i = 0; i < 3; i++) { bank.add(100); } } } // 延迟加载的单例模式 class Single { private static Single s = null; private Single() { } public static Single getInStance() { if (s == null) { // 这是关键,减少同步次数,提高效率 synchronized (Single.class) { // 锁。该类所属的字节码文件对象 if (s == null) { s = new Single(); } } } return s; } } // 饿汉试单例模式 class Single1 { private static final Single1 s = new Single1(); private Single1() { } public static Single1 getInStance() { return s; } } // 死锁 public class ThreadDemo { public static void main(String[] args) { new Thread(new Testlock(true)).start(); new Thread(new Testlock(false)).start(); } } class Testlock implements Runnable { private boolean flag; Testlock(boolean flag) { this.flag = flag; } public void run() { if (flag) { synchronized (Mylock.locka) { System.out.println("if locka"); synchronized (Mylock.lockb) { System.out.println("if lockb"); } } } else { synchronized (Mylock.lockb) { System.out.println("else lockb"); synchronized (Mylock.locka) { System.out.println("else locka"); } } } } } class Mylock { static Object locka = new Object(); static Object lockb = new Object(); } public class ThreadDemo { public static void main(String[] args) { Resource resource = new Resource(); Producer producer = new Producer(resource); Consumer consumer = new Consumer(resource); new Thread(producer).start(); new Thread(consumer).start(); new Thread(producer).start(); new Thread(consumer).start(); } } class Resource { private String name; private int count = 1; private boolean flag = false; public synchronized void set(String name) { while (flag) { try { this.wait(); } catch (Exception e) { } } this.name = name + "--" + count++; System.out.println(Thread.currentThread().getName() + "--生产者--" + this.name); flag = true; this.notifyAll(); } public synchronized void out() { while (!flag) { try { this.wait(); } catch (Exception e) { } } System.out.println(Thread.currentThread().getName() + "--------消费者-------" + this.name); flag = false; this.notifyAll(); } } class Producer implements Runnable { private Resource resource; Producer(Resource resource) { this.resource = resource; } public void run() { while (true) { resource.set("逗比"); } } } class Consumer implements Runnable { private Resource resource; Consumer(Resource resource) { this.resource = resource; } public void run() { while (true) { resource.out(); } } } public class ThreadDemo { public static void main(String[] args) { Resource resource = new Resource(); Producer producer = new Producer(resource); Consumer consumer = new Consumer(resource); new Thread(producer).start(); new Thread(consumer).start(); new Thread(producer).start(); new Thread(consumer).start(); } } class Resource { private final Lock lock = new ReentrantLock();// 拿到锁 private final Condition condition_producer = lock.newCondition();// 生产者的监视器 private final Condition condition_consumer = lock.newCondition();// 消费者的监视器 // private String name; private int count = 1; private boolean flag = false; public void set(String name) throws InterruptedException { lock.lock(); try { if (flag) condition_producer.await(); this.name = name + "--" + count++; System.out.println(Thread.currentThread().getName() + "--生产者--" + this.name); flag = true; condition_consumer.signal(); } finally { lock.unlock(); } } public void out() throws InterruptedException { lock.lock(); try { if (!flag) condition_consumer.await(); System.out.println(Thread.currentThread().getName() + "--------消费者-------" + this.name); flag = false; condition_producer.signal(); } finally { lock.unlock(); } } } class Producer implements Runnable { private Resource resource; Producer(Resource resource) { this.resource = resource; } public void run() { while (true) { try { resource.set("逗比"); } catch (InterruptedException e) { e.printStackTrace(); } } } } class Consumer implements Runnable { private Resource resource; Consumer(Resource resource) { this.resource = resource; } public void run() { while (true) { try { resource.out(); } catch (InterruptedException e) { e.printStackTrace(); } } } }