一、代码块
1、代码块的定义
2、代码块的分类
(1)普通代码块
1)位置:位于方法中;
2)作用:限制变量的生命周期,提高效率。
(2)构造代码块
1)位置:类中,方法外
2)作用:调用构造器之前执行,先行将对象相同的内容进行初始化(设置默认值);
3)程序执行顺序:
a.创建对象;
b.执行构造块;
c.调用构造方法;
d.对象初始化,并返回引用地址。
(3)静态代码块
1)位置:位于类中,方法外,用static修饰;
2)作用:从属于类,伴随类的加载而加载一次,可用来初始化类的静态属性。
(4)同步代码块(后期学了之后补充)
为了解决并发操作可能造成的异常,java的多线程支持引入了同步监视器来解决这个问题,使用同步监视器的通用方法就是同步代码块:
synchronized(obj){
//同步代码块
}
线程开始执行同步代码块之前,必须先获得对同步代码块的锁定。任何时刻只能有一个线程可以获得对同步监视器的锁定,当同步代码块执行完成后,该线程会释放对该同步监视器的锁定。虽然java程序允许使用任何对象作为同步监视器,但是同步监视器的目的就是为了阻止两个线程对同一个共享资源进行并发访问,因此通常推荐使用可能被并发访问的共享资源充当同步监视器。
二、抽象类和抽象方法
1、定义
抽象类:用abstract修饰的类叫做抽象类;
抽象方法:用abstract修饰的方法叫做抽象方法。
2、使用意义
(1)抽象方法:当父类无法具体实现某些方法时,可定义为抽象方法,让子类重写父类方法。
(2)抽象类:一个类中包含有抽象方法时,这个类必定是抽象类。
(3)使用抽象类可以对类的设计做相应的规范和约束。
3、语法
(1)抽象类:访问修饰符 abstract class 类名{ } ;
(2)抽象方法:访问修饰符 abstract返回值类型 方法名() ;
4、注意点
(1)抽象类中不一定有抽象方法;但是有抽象方法的类一定是抽象类;
(2)抽象类中可以有普通方法;
(3)抽象方法没有方法体,只是方法的声明;
(4)子类必须重写父类的抽象方法;
(5)抽象类不能被实例化;
(6)abstract和fianl不能一起用。
三、接口
1、定义
2、语法
[public /default(默认)]interface 接口名{
[public/default(默认)] static 常量名 = 值;
抽象方法;
}
3、意义
4、注意点
(1)接口中只有抽象方法和公共类静态常量;
(2)接口的访问修饰符只有public和default(默认)两种(不写也是这个);
(3)接口中的常量默认为:公共的静态常量(默认);
(4)接口不能被实例化,只能被类实现,关键字为implements;
(5)接口和类之间的关系
1)接口与接口之间:继承—-可以多继承;例如:interface A extends B,C{ }
2)接口与类之间:实现—一个类可以实现多个接口;例如:class A implements B,C{ }
实现接口的类必须重写所实现的所有接口中的所有抽象方法。
5、接口和抽象类的区别
参数 | 抽象类 | 接口 |
---|---|---|
默认的方法实现 | 可以有具体的方法实现 | 全部都是抽象方法 |
实现 | 使用extends关键字来继承抽象类。如果子类不是抽象类的话,子类需事先抽象类中所有的方法 | 使键字implements来实现接口。如果不是接口或抽象类,需要直线接口中所有的方法 |
构造器 | 抽象类可以有构造器 | 接口不能有构造器 |
与普通Java类的区别 | 不能实例化抽象类 | 接口是完全不同的类型,但也不能实例化 |
访问修饰符 | 抽象方法可以有public、protected和default、private这些修饰符 | 接口方法默认修饰符是public。不写也是public |
main方法 | 抽象方法可以有main方法并且可以运行 | 接口没有main方法,不能运行。 |
多继承 | 抽象方法可以继承一个类和实现多个接口 | 接口只可以继承多个其它接口 |
速度 | 比接口速度要快 | 接口是稍微有点慢的,因为需要时间去寻找在类中实现的方法。 |
添加新方法 | 如果你往抽象类中添加新的方法,你可以给它提供默认的实现。因此你不需要改变你现在的代码。 | 如果你往接口中添加方法,那么你必须改变实现该接口的类。 |
成员变量 | 可以定义成员变量 | 接口中的成员变量都是常量 |
静态方法 | 包含静态方法 | 不能有静态方法 |
1、定义
2、分类
(1)局部内部类
(2)成员内部类
类似于成员方法,从属于对象,定义在类中,方法外;
(3)静态内部类
类似于类的静态属性,从属于类,定义在类重,方法外,用static修饰;
(4)匿名内部类(需了解)
1)定义:没有名字的内部类。<br />2)用法:只需一个子类对象,不需要麻烦得去设计子类时可使用匿名内部类;<br />使用前提:必须有继承父类或实现接口<br />语法: new 父类对象(实现的接口){<br /> 内部类类体;<br />}<br /> 3)使用注意点<br /> a.内部类必须继承一个父类或实现一个接口;<br /> b.匿名内部类中不能定义构造器;<br /> c.匿名内部类中不能定义静态的属性和方法。<br />例题:
//定义鸟类:Bird(抽象类)
abstract class Bird{
privateString name;
//功能:飞行
publicabstract void fly();
publicString getName() {
returnname;
}
publicvoid setName(String name) {
this.name= name;
}
}
publicstatic void main(String[] args) {
test1(newBird() {//创建一个鸟的对象:通过匿名内部类来实现
//这个匿名内部类其实就是鸟类的一个实现类
@Override
publicvoid fly() {
System.out.println("大鹏一日同风起,扶摇直上九万里");
}
//重写鸟类的get方法
@Override
publicString getName() {
return"大鹏";
}
});
}
//测试匿名内部类:使用鸟的飞行功能
publicstatic void test1(Bird bird) {
System.out.println("鸟的名字:"+bird.getName());
//飞行的功能
bird.fly();
}
五、字符串常量池
1、常量池
常量池:位于方法区,用于存放常量;
作用:为了避免频繁地创建和销毁对象而影响系统得效率;
2、字符串分类
(1)不可变字符串:String;
(2)可变字符串:StringBuilder,存储得字符串内容可修改,线程不安全;
(3)可变字符串:StringBuffer,存储得字符串内容可修改,线程安全。
3、字符串常量池
字符串常量池:用于存放创建得字符串对象;
作用:已经存在于字符床常量池中得字符串内容可直接使用,不许再创建。
4、创建字符串的两种方式
(1)直接赋值:String str1= “薛之谦”;
(2)用new关键字创建:String str2 = new String(“薛之谦”);
(3)两种方式得区别:
1)方式(1):如果字符串常量池中不存在字符串“薛之谦”,则直接在字符串常量池中创建字符串对象“薛之谦”,并返回引用地址;如果存在,则直接使用;
2)方式(2):先在堆中创建一个String对象,然后再去字符串常量池查找是否存在“薛之谦”这个字符串,如果不存在,则在字符串常量池中创建一个字符串“薛之谦”;如果存在,则直接使用。
例1:判断下列程序创建了几个对象
Stringstr1 = “abc”;//一个或者没有(得看字符串常量池中是否存在字串”abc”)
Stringstr2 = new String(“abc”);//1个
Stringstr3 = new String(“bcd”);//1个或者2两个
例2:字符串创建内存分析