未经做者容许,不可转载,若有错误,欢迎指正o( ̄▽ ̄)ojava
建议本身写个小的测试demo体会一下,下面是个人测试代码c++
public class Test1 { public static void main(String[] args) { VIP vip = new VIP(); SuperVIP superVIP = new SuperVIP(); Owner owner = new Owner(); //这里owner对象的custom成员变量所属的类是两个VIP类的超类 owner.setCustom(superVIP); owner.settlement(); //custom本质上是一个SuperVIP的对象的引用 Custom custom = owner.getCustom(); //这里调用的是子类重写后的方法 custom.buyBook(); //这个num是父类的public成员变量,可是没法获取custom的私有成员变量 //private修饰的成员变量只能在同一个类中直接访问,一般用该类的public方法访问 System.out.println(custom.num); //System.out.println(custom.getName());也没法获取子类的私有成员属性 SuperVIP superVIP1 = (SuperVIP) custom; //之因此能强制类型转化是由于custom本质上就是SuperVIP对象引用 //因此说继承是多态的前提 System.out.println(superVIP1.getName()); } } class Custom { private int money = 50; public int num = 100; public void buyBook() { System.out.println("店主买书不花钱"); } } class VIP extends Custom { public void buyBook() { System.out.println("普通会员买书打八折"); } } class SuperVIP extends Custom { private String name = "我是SVIP"; public void buyBook() { System.out.println("超级会员买书打六折"); } public String getName() { return name; } } class Owner { private Custom custom; public Custom getCustom() { return custom; } public void setCustom(Custom custom) { this.custom = custom; } public void settlement() { custom.buyBook(); } }
对应8个基本数据类型有8个包装器类,这些类能够用于新建对应8个基本数据类型的对象,而且有着自动装箱,拆箱的功能(如:不少时候一些方法的参数时Obj类型的对象,可是咱们直接传入基本数据类型的参数能够完成调用),在这些类中还定义了许多静态方法用于基本数据类型和包装器类之间的转换,这里感受力扣上刷点题应该就会熟悉这些API了程序员
有一种说法:接口其实就是抽象类,极度抽象的抽象类,接口中不能存在非抽象方法,接口中的全部方法必须所有是抽象方法。在接口使用时有如下一些要求:编程
修饰一个方法:该方法能够被继承但没法被重写ide
修饰一个类:该类为最终类,没法被继承函数
修饰一个基本数据类型:该值为常量没法被修改学习
在八位二进制下,原码左侧第一位为符号位,除符号位外其他位取反为反码,反码+1为补码,计算机中以补码形式存储数据,其中要注意0的存储与-128的存储测试
下面是一个byte型的1左移6位,7位,8位后的结果测试:this
public class Test1 { public static void main(String[] args) { byte test = 1; test <<= 6; System.out.println(test); test = 1; test <<= 7; System.out.println(test); test = 1; test <<= 8; System.out.println(test); //如下两个是int左移7位和31位,这里是用于区分的,由于默认是int System.out.println(1<<7); System.out.println(1<<31); } }
异常类是一个树形的族谱结构,如下两个异常为Throwable类的两个子类.net
try { //可能会抛出异常的代码 } catch { //对异常进行处理 } finally { //必定会执行的代码 }
throws关键字的做用:
接下来时三种throws的使用状况
1.下面的代码是异常抛出方法自己不处理,而且调用者依旧选择不处理,将其交给JVM中断程序处理
public class Test1 { public static void main(String[] args) throws Exception { int[] array = {1, 2, 3}; //此时main方法中并未对这个抛出异常对象的方法进行捕获操做,选择交给JVM中断处理程序 test(array, -1); } public static void test(int[] array, int index) throws Exception { if (index < 0 || index >= 3) //这句抛出就必须处理这个异常对象,此时在方法后用throws至关于 //将这个抛出的异常交给方法的调用者main方法处理 throw new Exception("下标越界"); System.out.println(array[index]); } }
2.下面代码是test方法不处理,调用者main方法选择本身try-catch捕获抛出的异常,本身处理
public class Test1 { public static void main(String[] args) { int[] array = {1, 2, 3}; //此时方法调用者main选择捕获这个抛出异常的方法 try { test(array, -1); } catch (Exception e) { e.printStackTrace(); } } public static void test(int[] array, int index) throws Exception { if (index < 0 || index >= 3) //这句抛出就必须处理这个异常对象,此时在方法后用throws至关于 //将这个抛出的异常交给方法的调用者main方法处理 throw new Exception("下标越界"); System.out.println(array[index]); } }
3.下面的代码时test方法选择本身直接捕获本身抛出的异常,并进行处理
public class Test1 { public static void main(String[] args) { int[] array = {1, 2, 3}; test(array, -1); } public static void test(int[] array, int index) { if (index < 0 || index >= 3) //此时test本方法直接本身处理本身抛出的异常对象 try { throw new Exception("下标越界"); } catch (Exception e) { e.printStackTrace(); } System.out.println(array[index]); } }
下面是一个例子实现了两种不一样的开启线程的方式
public class Test1 { public static void main(String[] args) { //经过实现接口的方式能够解耦合 MyRunnable myRunnable = new MyRunnable(); //调用Thread类的构造函数传入线程须要执行的任务(业务逻辑) Thread thread = new Thread(myRunnable); //开启线程等待资源分配,而后执行run方法业务 thread.start(); //经过继承的方式 MyThread myThread = new MyThread(); myThread.start(); for (int i = 0; i < 1000; i++) System.out.println("++++++++++主线程++++++++"); } } class MyRunnable implements Runnable { //Runnable是一个接口,内部只有一个抽象的run方法(表明开启线程后须要执行的业务逻辑) @Override public void run() { for (int i = 0; i < 1000; i++) { System.out.println("--------MyRunnable--------"); } } } class MyThread extends Thread { //经过继承Thread类的方式,因为Thread类自己就继承了Runnable接口 // 所以所建立的Thread类的实例内部有run方法 //这里是重写父类的run方法,替换为本身想要执行的任务 @Override public void run() { for (int i = 0; i < 1000; i++) System.out.println("=========MyThread============"); } }
建立——》就绪、就绪《——》运行、运行——》阻塞、阻塞——》就绪、运行——》终止
注意点:在外部调用时,sleep休眠要放在启动以前;不然就是在内部调用sleep则能够随时休眠,下面是一个小的例子
public class Test1 { public static void main(String[] args) { try { Thread.sleep(5000); } catch (InterruptedException e) { e.printStackTrace(); } //下面开启子线程的代码也是包含在main主线程中的,因此主线程挂起后 //下面的代码也没法继续执行 MyRunnable myRunnable = new MyRunnable(); Thread thread = new Thread(myRunnable); thread.start(); } } class MyRunnable implements Runnable { @Override public void run() { for (int i = 0; i < 1000; i++) System.out.println("-----MyRunnable------"); } } class MyThread extends Thread { @Override public void run() { for (int i = 0; i < 100; i++) System.out.println("++++++++MyThread+++++++++"); } }
这里我作了一个测试,若是由三个线程:主线程、甲线程、乙线程,在主线程中某个位置调用甲线程.join(),会使得除主线程外的另外两个线程继续争夺CPU的资源,直到甲结束,主线程才会回到就绪态去竞争CPU的使用权,若是此时乙线程尚未结束(我估计在测试代码中将乙线程的循环写的很长),则会继续与主线程进行CPU资源的竞争
public class Test1 { public static void main(String[] args) { MyRunnable myRunnable = new MyRunnable(); Thread thread = new Thread(myRunnable); thread.start(); MyThread myThread = new MyThread(); myThread.start(); for (int i = 0; i < 100; i++) { System.out.println(i + "========main========"); if (i == 50) { try { Thread.sleep(2000); myThread.join(); } catch (InterruptedException e) { e.printStackTrace(); } } } } } class MyRunnable implements Runnable { @Override public void run() { for (int i = 0; i < 1000000; i++) System.out.println(i + "-----MyRunnable------"); } } class MyThread extends Thread { @Override public void run() { for (int i = 0; i < 100; i++) System.out.println(i + "++++++++MyThread+++++++++"); } }
线程礼让:yield是一个静态方法,经过调用该方法,是在某个特定的时间点让线程暂停抢占CPU资源的行为,只是暂时的礼让
线程中断:不少状况致使线程中止运行,如线程执行完毕自动中止,线程执行过程当中遇到错误抛出异常并中止,或者线程执行过程当中根据需求手动中止,有以下三个实例方法
一些获取当前线程信息的实例方法:
new SuperType(construction parameters) { inner class methods and data }
其中,SuperType能够是接口,若是是这样,内部类就要实现这个接口,Super Type也能够是一个类,若是是这样,内部类就要扩展这个类。