文章目录
标识符命名规则
1.由26个英文字母大小写,0-9,_或$组成
2.数字不能开头,不难有空格
包名:xxxyyyzzz
类:XxxYyyZzz
变量和方法:xxxYyyZzz
常量名:XXX_YYY_ZZZ
内存空间
堆:函数体内声明的8种局部基本变量,byte,char,short,int,long,float,double,bool
栈:new生成的对象
方法区:静态域存放类的static属性
变量和属性
属性没有显示初始化时会用0值默认初始化,且可以使用。
变量没有显示初始化不能使用。
一个.java文件只能有一个public类
import 和 package
package:
1.方便文件管理
2.同一个包不能有同名类和接口
import:
1. xxx.*导入包下所有结构除了子包
2.java.lang不用导入
3.本包的类和接口不用import
4.在源文件中使用不同包下的同名类,则至少有一个类需要全命名的方式显示。
5.import static 导入指定类或接口中的静态结构
自动类型转换
自动提示,表示的数字的范围小的向大的提升。
float 表示的数字大于 long。
byte->short->int->long->float->double
特别:char,short,byte三种类型做运算结果为int
显示类型转换
需要使用强制类型转换符号: (type),可能会有精度损失。
double a = 12.9;
int i = (int)a;
操作符权限
private:类内可见
默认(缺省):包内可见
protected:子类可见
public:全局可见
下面包含上面。
重载(2同1不同)静态绑定
同一个类或者子类与父类中,相同的函数名,参数列表不同。
重写:动态绑定
方法的声明:
权限修饰符 返回值类型 方法名 (参数列表){}
or
权限修饰符+(final;static;abstract) 返回值类型 方法名 (参数列表)throws 异常类型{}
1.子类重写方法的方法名和参数列表和父类相同
2.子类重写方法的权限要大于等于父类(只有大于等于父类方法才能覆盖父类方法)。若子类方法为private,则对父类不可见,没有重写发生。
3.返回值类型:
(1)父类被重写的方法的返回值为void,则子类也只能是void
(2)若父类被重写的方法的返回值是A类型,则子类重写的方法能返回A类或A类的子类。
(3)若父类被重写的方法的返回值是 基本数据类型,则子类重写的方法只能返回相同的类型。
4.子类重写的方法抛出的异常类型不大于父类被重写的方法抛出的异常类型
子类和父类同名同参的方法,要么都声明为非static(重写),要么都声明为static(不是重写)
super
1.理解为父类的
2.可以调用父类的属性,方法,构造器
3.使用
(1)可以在子类中用 super.属性 或 super.方法 显示调用父类中的属性或方法,通常省略,类似this。
(2)特别的:当父类和子类使用类同名的属性,想在子类使用父类的属性就需要显示的调用,super.属性
(3)特别的:当父类和子类使用类同名的方法,想在子类中使用父类的方法就需要显示的调用,super.方法
(4)在子类构造器中:
可以使用:super(参数列表)的方法调用父类中指定的构造器;super(参数列表)和this(参数),都只能放在构造器的首行,也就是说父类构造器和子类构造器只能选一个;如果首行都没有显示声明super()或this(),则会默认使用super();当父类没有空参数构造器,编译会不通过。 也可以在子类中显示调用父类有参构造器,编译就不会报错。
总之可以理解为子类构造器必须显示或隐式调用一个父类构造器,否则编译不能通过。
(5)类的n个构造器中,至少有一个构造器使用super(形参表),调用父类构造器。因为至多有n-1个this(参数列表),有n个this(形参表)调用本类构造器会导致构造器成环互相调用,无法终止。
(6)子类构造器调用父类构造器并不会创建多个对象,只会创建一个子类对象,因为只有一个地址暴露出来。
多态
Person p = new Man();
父类引用指向子类对象,
编译期,只能调用父类中声明的方法;运行期,实际执行子类中的方法。
编译看父类,运行看子类。
前提:继承,重写。
instanceof 本类和父类为真。
没有子父类关系编译就不能通过。
向下转型:把指向子类对象的父类引用变为指向子类对象的子类引用。
也就是如下:
父类对象:Person
子类对象:Man
父类引用必须指向new出来的转换目标的子类或者子类的子类:Person p = new Man();
Person p = new Man();
Man m = (Man)p;
总结:功能少的不能转换成功能多的,功能不同的不能转换。
但是强制类型转换有风险,因此引入instanceof关键字,表达式返回boolen值:a instanceif A(a是A类或者a是A类的父类都是真,即类似集合中A包含a的关系)
p instanceof Man =>true
p instanceof Woman =>false;根据new的时候来。new为man了,man和woman么关系。
toString和equals方法
1.System.out.printlin(Object obj)会自动调用Object类中的toString方法,想要正确输出类信息就必须重写,否则仅仅是Object中方法输出的地址内容等。
2.equals方法在object类中仅比较地址,想让子类比较对象是否相同,需要在子类中重写equals。
单元测试
1.先在lib中添加依赖JUNIT
2.创建java类,进行单元测试,要求此类为public且有空参数构造器。
3.类内测试方法要为public,void且没有参数。
4.方法上注明@Test,为JUNIT的一个类,并导入JUNIT
包装类(特别的Integer,Character)
将基本数据类型转化为功能强大的包装类,但不能±*/等。
包装类转化为基本数据类型才可以参与基本运算: object.xxxValue
Integer in1 = new Integer(12);//目前已经废除
int a = in1.intValue
JDK5.0 自动装箱和自动拆箱
包装类会自动转换为基本类型,基本类型又会自动转化为包装类。
JDK9.0 不再支持new包装类,均由自动装箱和自动拆箱实现,包括基本运算。
String和基本数据类型互相接收
通过String接收基本数据类型方法:String. valueOf(a); a为基本数据类型
通过基本数据类型接收String: Integer.parseInt(str); str为String对象。
Integercache
Integer有个静态Integer数组,保存了Integer.value在-128到127的对象。
自动装箱
Integer i = 1;
Integer j = 1;
i == j =>true;
Integer m = 128;
Integer n = 128;
m == n =>false;
对象比较地址,因为Integerchched的存在,-128到127==相等,其余为false。
Vector类
存放的是Object类型,放入时可以直接放入int类型,会先装箱为Integer,再通过多态性让父类指针可以指向子类。
取出使用时需要把Object类强制类型转换为子类Integer等或基本数据类型。
static
static修饰的属性,方法,代码块,内部类都在类加载的时间加载。
1.静态属性属于类,所有对象和类共享。
类不能调用非静态属性,而对象都能调用。
2.静态方法也属于类,所有对象和类共享,且只能调用static修饰的结构。方法中不能使用对象的this和super结构。
类中哪些部分应该声明为static
1.所有对象共享的属性和类中常量
2.只 使用static 属性的方法
3.工具类的方法(Arrays, Math等)
单例设计模式
希望类只有一个实例,借助static关键字实现
饿汉式(线程安全):类家载时直接创建
package singleton;
public class SingletonTest {
public static void main(String[] args) {
4.外部通过类的静态方法获取类内创建的实例。
Bank ban1 = Bank.getInstance();
}
}
class Bank{
1.私有构造函数,不让外部创建实例
private Bank(){
}
2.内部创建静态类实例
private static Bank instance = new Bank();
3.通过static方法返回实例
public static Bank getInstance(){
return instance;
}
}
懒汉式(线程不安全):需要时才在方法中创建,延迟创建,效率高。
在创建时,当第一个线程判断完准备创建实例时发生线程切换,第二个线程也进行判断,也准备创建实例,这就会导致产生两个实例。
package singleton;
public class SingletonTest2 {
public static void main(String[] args) {
Order order1 = Order.getInstance();
Order order2 = Order.getInstance();
System.out.println(order1 == order2);
}
}
class Order{
private Order(){
}
private static Order instance = null;
//只有到需要使用时才会创建实例
public static Order getInstance(){
if(instance == null) instance = new Order();
return instance;
}
}
代码块
类的成员:属性,方法,代码块,构造器,除了构造器都可以声明为static
代码块:
1.用来初始化类和对象
2.想修饰的话只能用static修饰
3.静态代码块随着类的加载执行,而非静态随着每个类对象的实例化加载执行。
Class A{
//静态代码块
static{
System.out.println("static");
}
//非静态代码块
{
System.out.println("no-static");
}
属性赋值的地方和顺序:1 -> 2/5 -> 3 -> 4
1.默认初始化
2.显示初始化
3.构造器
4.对象.属性(方法)
5.代码块中赋值
final和finalize
Object类的方法finalize()垃圾回收释放对象,一般jvm会自己掉用,如果显示调用结果不可知。
final可以修饰类,方法,变量。
1.final修饰类,最终类不可以被继承
2.final修饰方法,最终方法不可以重写
3.final修饰变量,表示变量为常量不能修改;如果声明中没有显示赋值,之后一旦赋值就不能修改。
3.1.修饰属性默认初始化,会报错
3.2。显示初始化,代码块初始化,构造器初始化
显示初始化适合所有对象共享的初始值。
代码块初始化适合较为复杂的初始值,对象等。
构造器初始化适合每个对象特有的属性值。
3.3.修饰局部变量,局部变量为常量不能修改
static final 修饰属性=>全局常量
Abstract
可以用了修饰类和方法
1.修饰类(抽象类):不能实例化,一定有构造器,便于子类调用。
2.修饰方法(抽象方法):
只有方法的声明,没有方法体;
包含抽象方法的类一定是抽象类,抽象类不一定包含抽象方法;
只有当子类重写了父类所有的抽象方法,子类才能实例化,否则子类仍然是抽象类。
注意点:根据抽象类和方法需要被重写推出。
1.不能修饰:属性,构造器等。
构造器需要有实体,不能重写。
2.不能修饰:static方法,private 方法,final方法。
private和static都不能被子类重写,final方法也不能被重写。
匿名对象和匿名类
创建了类peron的匿名对象,并传递给函数f(Person p);
f(new Person());
在花括号中重写父类抽象方法,创建了一个匿名子类,并用父类引用p接收。
Person p = new Person() {
@Override
public void method() {
}
};
模版方法
抽象类父类中实现了总体的流程,但是其中有些部分被写成抽象方法,在父类中并不难具体的实现,需要子类去实现这些抽象方法,然后利用多态,用父类引用接收子类对象,然后去调用方法。
模版和接口的区别:
模版定义好了一套流程
接口只定义各种API,能有不同的组合实现不同的功能。
接口(interface)和类并列
1.不能定义构造器,不能实例化。
2.JDK7.0:
只能定义全局常量(public static final修饰的变量,定义普通的也会默认设为全局常量)和抽象方法(public abstract修饰的方法,不声明也会默认设定)
3.JDK8.0:还可以定义静态方法和默认方法。
4.接口通过类实现的方式使用。
class A implements B_interface{
}
如果实现类实现了接口中的所有抽象方法,则此实现类可以实例化;没有实现接口中的所有方法则此实现类仍为抽象类
- 类可以实现多接口,格式:
class A extends 父类 implements B_interface, C_interface{
}
6.接口和接口之间可以继承,而且可以多继承。
7.接口的使用体现多态性。
接口不能实例化,但可以用接口的类型的引用指向实现接口的类型的对象。例如:USB是接口,Printer是实现类,USB usb = new Printer();
类似类的多态性,接口类似多态中的父类,父类引用指向子类;接口引用指向实现类;运行时再根据new出的对象的类型决定调用的方法。
例如:USB接口,U盘,打印机都有USB接口。
具体使用时,U盘和打印机都实现了USB接口,然后根据new对象是U盘还是打印机,决定调用的方法。
8.接口可以看成一种规范。
比如USB接口有数据传输的规范,所有想使用USB接口的实现类U盘,打印机,电脑都要遵守。
接口应用:代理模式(Proxy)
例如:
1.Network为接口类,提供网络连接。
2.Server作为被代理类和Network的实现类。
3.ProxyServer作为代理类和Network的实现类,并提供更加完善的功能。
在main中用Network引用指向ProxyServer对象。
工厂模式
简单工程模式:用来生产同一等级结构中任意产品。(新添加的,需要修改已有代码)
工厂就是一个类,内部实现new各种产品的方法,代码已经固定,新添加需要修改代码。
工厂方法模式:用来生产同一等级结构中任意产品。(可添加任意产品)
用接口实现生产方法,各实现类实现抽象方法接口;添加产品就是添加实现类,可以随意添加。
抽象工厂模式:类似工厂方法,只是产品更为复杂; 用来生产不同产品族的全部产品。(对于新添加的产品无能为力,支持添加产品族)
java 8.0接口
可以定义静态方法和默认default方法
1.静态方法只能由接口调用。
2.通过实现类对象,可以调用接口的默认方法。
3.如果子类或实现类,继承的父类和接口中有同名同参的方法且实现类 没有重写,则实现类调用父类的方法。
4.如果实现类实现了多个接口,接口中有同名同参的方法且实现类没有重写,则接错冲突编译不通过。
5.调用实现的多个接口中同名同参的默认方法,
Interface_A.super.method();
Interface_B.super.method();
其中Interface_A和Interface_B都是接口类型,super表示当前实现类的父类,可以理解为接口就是父类,因此会在父类中找到对应的默认方法。
内部类
允许在A类的声明中声明B类,A外部类,B内部类。
局部内部类(方法,构造器,代码块)
成员内部类(静态,非静态)
class Person{
static class Dog{
}
class Bird{
}
}
创建静态成员内部类对象:
Person.Dog dog1 = new Person.Dog();
创建非静态成员内部类对象:
Person p = new Person();
Person.Bird bird1 = p.new Bird();
异常处理
异常:Error,Exception,RuntimeException
处理: try-catch-finally自己尝试解决;throws向上汇报。
规则:
1.try内部发生异常,try内部异常的后续代码就不再执行了,只有finally中的会执行;throws修饰方法直接返回由调用函数处理异常,方法中的代码不再执行。
2.类继承中,被重写方法抛出的异常不能大于父类方法抛出的异常。
如果父类被重写的方法没有throws异常,则子类重写方法时需要try-catch-finally处理异常,不能抛出异常。
3.方法a中先后调用了几个按递进关系(方法有依赖关系,2方法需要1方法的结果)执行的几个方法,则这几个方法用throws抛出异常,而方法a使用try-catch处理异常。
常用异常结构
java.lang.Throwable
java.lang.Error
java.lang.Exception
checked(编译时异常,必须处理)
java.lang.IOException
java.lang.ClassNotFoundException
uncheced, RuntimeException(运行时异常,可以不处理)
java.lang.NullPointerException
java.lang.ArrayIndexOutOfBoundsException
java.lang.ClassCaseException
java.lang.NumberFormatException
...
抓抛模型
1.抛:一旦发生异常,就在异常代码出创建一个对应异常类的对象。并将异常抛出,之后的代码不执行。
2.抓:异常处理的方式,try-catch-finally、throws
try{
//可能出现异常的代码
}catch(异常类型1 变量名1){
//异常处理方式
}catch(异常类型2 变量名2){
//异常处理方式
}
......
finally{ //可选项
//一定会执行的代码
}
try-catch-finally
1.finally可选
2.try将可能出现异常的代码包起来,一旦出现异常就去catah中匹配。
3.匹配成功就执行catch中的内容,执行完退出try-catch结构
4.子类异常一定要写在父类异常上面,不然子类异常catch就无法执行。
5.常用异常处理方式:
(1)String getMessage()//打印异常信息
(2)printStackTrace()//查看异常位置
6.try结构内的声明的变量,出了结构不能用,变量生存期为{}。
7.使用try-catch-finally处理编译时异常,但仍可能发生运行时异常
8.try-catch-finally可以互相嵌套。
9.finally中的代码一定会被执行,先于return。常用于释放JVM无法自动回收的资源:数据库连接,输入输出,网络socket等。
体会1:使用try-catch-finally处理编译时异常,使得程序编译时不再报错,但仍可能有运行时异常,就是我们将编译时异常推迟到运行时。
体会2:实际开发中由于运行时异常很常见,我们就不再对运行时异常使用try-catch-finally;而对编译时异常一定要考虑异常处理。
throws(写在函数声明中)
throws向调用函数抛出异常,调用函数内写try-catch-finally对异常进行处理,或者继续向调用函数的调用函数throws异常直到main函数就不应该再向上抛。
throw(写在函数体中:throw new Exception)
1.throw只是抛出异常,并没有处理异常,一般手动生成(Exception和RuntimeException),其中RuntimeException可以不处理。
2.try-catch和throws都是异常处理的方式,会自动生成异常。
自定义异常
1.继承Exception或者RuntimeException。
2.提供重载构造器
3.提供全局常量 long类型进行表识。