一、关键词final
(1)四种用法
修饰类(该类不能被继承,没有子类)
修饰成员方法(该方法不能被重写)
修饰成员变量 (因为成员变量有默认值,所以在申明成员变量时直接赋值,或者在所有构造函数中赋值,两者选其一)
修饰局部变量 (赋值一次,终身不能改变)
注:final修饰引用类型,变量地址值不能变,但是指向的对象属性可以改变
(2)final,finally,finalize三者之间的区别
final是java的关键字,修饰符,表示不可变。
finally是java异常处理模型的最佳补充,finally结构使代码总会执行,而不管无异常发生。
finalize 使用这个方法在垃圾收集器将对象从内从中清除出去前,做必要的清理工作。这个方法是由垃圾收集器在确定这个 对象没被引用时对这个对象调用的。他是Object类中定义的。因此所有的类都继承了它。
二、基本数据结构
byte字节型 1个字节short短整型2个字节char字符型2个字节int整型4个字节float浮点型4个字节long长整型8个字节double双精度浮点型8个字节boolean布尔类型1个字节
三、 java面向对象的三大特性
(1) 封装,继承,多态
继承是多态的基础,多态就是基类的引用指向子类的实现。
(2)继承
子类构造方法当中有一个默认隐含的super()调用,所以一定是先调用父类构造函数,后执行子类构造函数。如果父类中自定义了构造函数,所以系统不提供无参构造函数,子类构造函数需要手动super调用父类有参构造函数,
super第一位执行,并且执行一次
public class Person { public Person(String name) { Log.d("aaa", "父类构造函数"); } } public class Student extends Person{ public Student() { super(""); Log.d("aaa", "子类构造函数"); } } 单继承,但是可以多级继承如果多个父类有相同的方法,子类不知选择执行哪个方法
(3)多态
成员变量的访问看等号左边是谁,优先用谁,没有则向上找
Fu fu=new Zi();
fu.num; //打印父类的num值
成员方法的访问看等号右边是谁,优先用谁,没有则向上找
public class Person { public int age = 10; public void action() { Log.d("aaa", "父类方法"); } } public class Student extends Person { public int age = 20; public void action() { Log.d("aaa", "子类方法"); } } Person person = new Student(); Log.d("aaa", "" + person.age); person.action(); //结果 10 子类方法(4)重写override和重载overload的区别
重写:发生在继承,方法名,参数都要和父类一致;返回值要求子类类型小于等于父类类型,如父返回string,子可以同样返回string,不能返回object
权限修饰符:子类的修饰符大于等于父类的,以便在外部通过父类的引用可以调用子类的方法。
抛出的异常:子类抛出的异常要与父类抛出的异常一致或者父类异常的子类,这应该是与向上转型有关
重载:发生在同一类之间,方法名一致,方法参数必须不一致(个数,类型,参数),其他的都可以修改。注:参数都一样,只有返回类型不同,这不是重载。
参数和返回类型都不同,这个是重载。
四、抽象类
抽象方法加上abstract关键字,去掉大括号,没有方法体
抽象方法所在的类,必须是抽象类
抽象类用abstract关键字修饰类
不能直接new创建抽象类对象,但是可以有构造方法,是供子类创建对象时,初始化父类成员使用的
子类继承父类,子类必须覆盖重写父类的所有抽象方法,除非子类也是抽象类。
抽象类不一定有抽象方法,但是有抽象方法的类必是抽象类
五、接口 interface
接口的内容包含如果是Java 7,那么接口中可以包含的内容有:
常量 public static final 数据类型 常量名称=数据值;
抽象方法 public abstract 返回值类型 方法名称(参数列表);修饰符必须是固定的关键字:public abstract,可以省略 不写
如果是Java 8,那么接口中可以包含的内容有:
默认方法 public default 返回值类型 方法名称(参数列表){方法体};public 可以省略,但不能改变
静态方法 public static 返回值类型 方法名称(参数列表){方法体};public 可以省略,但不能改变
如果是Java 9,还可以额外包含有:
私有方法 普通私有方法 解决多个默认方法之间重复代码问题 private 返回值类型 方法名称(参数列表){方法体}
静态私有方法 解决多个静态方法之间重复代码问题 private static 返回值类型 方法名称(参数列表) {方 法体}
接口不能包含静态代码块,也不能包含构造函数
接口之间继承extends,并且可以多继承 public interface InterfaceA extends InterfaceB,InterfaceC{ }六、java权限修饰符
public 用public修饰的类,类属变量及方法,包内及保外的任何类(包括子类和普通类)均可以访问protected 用protected修饰的类,类属变量及方法,包内的任何类及包外那些继承了该类的子类才能访问,重点突出继承defalut 如果一个类,类属变量及方法没有用任何修饰符,包内的任何类(包括此类的子类)都可以访问它,而对于包外的任 何类都不能访问它(包含包外继承了此类的子类),重点突出包;private 只有本类可以访问,而保内包外的任何类均不能访问。
七、内部类
(1)成员内部类
1、成员内部类使用外部类,随意使用;外部类使用内部类,需要借助内部类对象
2、外部类名称.内部类名称 对象名=new 外部类名称().new 内部类名称();
Body.Heart heart=new Body().new Heart();
3、访问同名变量
public class Outer{ int num=10; public class Inner{ int num=20; public void methodInner(){ int num=30; System.out.println(num);//局部变量 System.out.println(this.num);//内部类的成员变量 System.out.println(Outer.this.num);//外部类的成员变量 } } }(2)局部内部类
在方法中定义内部类
(3)匿名内部类
八、static静态
static变量静态变量,静态变量和非静态变量的区别是:静态变量被所有的对象所共享,在内存中只有一个副本,它当且仅当在类初次加载时会被初始化。而非静态变量时对象所拥有的,在创建对象的时候被初始化,存在多个副本,各个对象拥有的副本互不影响。
注:非静态方法可以使用静态变量
static方法静态方法,由于静态方法不依赖任何对象就可以进行访问,因此对于静态方法来说,是没有this的,因为它不依附于任何对象,既然都没有对象,就谈不上this了。
注:在静态方法中不能访问类的非静态成员变量和非静态成员方法。
在非静态成员方法以及静态成员方法中可以访问静态成员方法和变量
static代码块用来形成静态代码块以优化程序性能,static块可以置于类中的任何地方,类中可以有多个static块,在类初次被加载的时候,会按照static块的顺序来执行每个static块,并且只会执行一次。
注:静态代码块不能访问非静态方法和非静态成员变量。
静态代码块能访问静态方法和静态成员变量。
九、类初始化顺序
public class Person { Teacher teacher = new Teacher("父类"); static { Log.d("aaa", "父类static"); } { Log.d("aaa", "父类构造代码块"); } public Person() { Log.d("aaa", "父类构造函数"); } public static void main(String[] args) { new Student(); } } public class Student extends Person{ Teacher teacher=new Teacher("子类"); static { Log.d("aaa", "子类static"); } { Log.d("aaa", "子类构造代码块"); } public Student() { Log.d("aaa", "子类构造函数"); } } public class Teacher { static { Log.d("aaa", "参数类static"); } { Log.d("aaa", "参数类构造代码块"); } public Teacher(String name) { Log.d("aaa", "参数类构造函数___"+name); } }输出:
父类static 子类static 参数类static 参数类构造代码块 参数类构造函数___父类 父类构造代码块 父类构造函数 参数类构造代码块 参数类构造函数___子类 子类构造代码块 子类构造函数类加载顺序,如果有父类,需要先加载父类,执行父类的静态代码块,执行子类静态代码块,静态代码块只会运行一次
类初始化顺序,如果有父类,先初始化父类静态变量,成员变量,构造代码块,构造方法,然后子类静态变量,成员变量,构造代码块,构造方法
十、强引用,软引用,弱引用,虚引用
强引用只要引用存在,垃圾回收期就永远不会回收 Obiect obj=new Obiect();
软引用非必须引用,内存溢出之前进行回收
Object obj=new Object(); SoftReference<Object> sf=new SoftReference<Object>(obj); obj=null; sf.get();//有时返回null 弱引用第二次垃圾回收时回收
Object obj = new Object(); WeakReference<Object> wf = new WeakReference<Object>(obj); obj = null; wf.get();//有时候会返回null wf.isEnQueued();//返回是否被垃圾回收器标记为即将回收的垃圾弱引用是在第二次垃圾回收时回收,短时间内通过弱引用取对应的数据,可以取到,当执行过第二次垃圾回收时,将返回null。弱引用主要用于监控对象是否已经被垃圾回收器标记为即将回收的垃圾,可以通过弱引用的isEnQueued方法返回对象是否被垃圾回收器标记
虚引用垃圾回收时回收,无法通过引用对象值,只能通过如下代码实现。
Object obj = new Object(); PhantomReference<Object> pf = new PhantomReference<Object>(obj); obj=null; pf.get();//永远返回null pf.isEnQueued();//返回是否从内存中已经删除虚引用是每次垃圾回收的时候都会被回收,通过虚引用的get方法永远获取到的数据为null,因此也被成为幽灵引用。 虚引用主要用于检测对象是否已经从内存中删除。
十一、java之深拷贝浅拷贝
https://www.cnblogs.com/dolphin0520/p/3700693.html
https://blog.csdn.net/u014727260/article/details/55003402
十二、泛型
当我们不确定数据类型的时候,可以使用泛型
定义和使用含有泛型的类访问修饰符 class 类名<E>
public class Person<E>{ private E name; public booelan add(E e){} public E get(){} } 定义含有泛型的方法,泛型定义在方法的修饰符和返回值类型之间访问修饰符 <E> 返回值 方法名(参数列表(使用泛型)){
方法体
}
public <E> void method(E e){ System.out.println(e); } 含有泛型的接口 public interface InterPerson<E>{ public abstract void getName(E e); } 4、泛型通配符十三、java常用API
API之Scanner Scanner sc=new Scanner(SYstem.in);//键盘录入 int num=sc.nextInt(); String str=sc.next(); API之Random Random r=new Rondom(); int num=r.nextInt();//随机int数字,正负两种 int num=r.nextInt(10);左闭右开 [0-10} Math Math.sqrt(16) //计算平方根4.0 Math.pow(3,2) //计算3的2次方 Math.max(a,b) //a和b的最大值 Math.min(a,b) //a和b的最小值 Math.abs(a) //a的绝对值 Math.ceil(a) //a的天花板,返回大的值 Math.floor(a) //a的地板,返回小的值 Math.random() //[0.0,1.0) Math.round(a) //四舍五入 float时返回int值,double时返回long值十四、字符串
字符串的内容永不可变,所以字符串是可以共享使用的。
字符串效果上相当于char[]字符数组,但是底层原理是byte[]字节数组
String str="abc"; String str=new String("abc"); String str=new String(new char[]{'a','b','c'}); 字符串的常量池程序中直接写上双引号的字符串,就在字符串常量池中。
String str1="helloworld"; String str2="hello"+"world"; String str3="hello"; String str4=str3+"world"; String str5=new String("helloworld"); System.out.println(str1==str2); //true System.out.println(str1==str4); //false System.out.println(str1==str5); //false 字符串的format //formatStr输出为"小李今年30岁" String formatStr2=String.format(Locale.ENGLISH,"%s今年%d岁","小李",30) String formatStr=String.foramt("%s今年%d岁","小李",30) //补齐空格并右对齐 String.format("s,world","hello") 输出" hello,world" String.format("