一.代码块
静态代码块:使用static关键字声明的代码。优先于main方法执行。在类中定义的静 态代码块会优先于构造块执行,静态代码只执行一次。不能调用非静态代码块。静态变量也有默认初始化。
构造代码块:直接写在类中的代码块,只有在实例化对象的时候才会调用,并且优先于构造方法执行。每次实例化对象时都会执行构造中的代码,会执行多次。
局部代码块:即普通代码块,是直接在方法或语句中定义的代码块。和main方法的优先级一样。可以调用静态代码块,也可以调用非静态代码块。
局部代码块就是在函数当中的一对{}
for{}
while{}
if{}
switch{}
代码说明:
class CodeBlock{
public static void main(String[] args){
Demo d1 = new Demo();
Demo d2 = new Demo();
Demo d3 = new Demo();
}
}
class Demo{
//静态代码块随着类的加载只执行一次
//在类被加载之时,对类的内容进行一些初始化
//做一些准备工作 JDBC Java DataBase Connection
//在JDBC技术中 静态代码块的作用就是事先链接数据库
static{
System.out.println("静态代码块");
}
//构造代码块随着对象的创建加载执行
//功能等同于构造函数
{
System.out.println("构造代码块");
}
}
/**执行结果
静态代码块
构造代码块
构造代码块
构造代码块
*/
JDBC简介
在JDBC技术中 静态代码块的作用就是 在代码还没运行之前,事先链接数据库。若等到主函数进栈就已经晚了。
二.单例模式
选择单例模式就是为了避免不一致状态,避免政出多头。
设计模式:20+种,它不是随着Java的诞生而诞生的
它是前辈们总结出来的一些开发技巧,适用于一些特定的场合
常用: 单例模式 、代理模式 、装饰模式 、策略模式、 工厂模式 、观察者模式
单例模式的场合:适用于全局内,对象保持唯一性
当朝皇帝,公司的老总
再简单点来说 一个类 只能被创建一个对象
- 如何创建对象?
new关键字用于创建对象
但是如果将new随意的给外界去使用的话
外界可以new很多次,这是不行的
禁止外界用new?不行!
禁止外界调用构造器?可以
构造器+private - .阻止了外部创建对象,但是对象还要存在
内部必须得创建对象,提供给外部即可
内部创建的话 成员变量不行 , 只能静态 - 虽然静态可以直接类调用,但是外界可改!
这个对象就不应改直接被外界访问
+private - 一+private 外界根部不可访问 ,需要使用getter访问!
构建方式:
- 懒汉方式(慢):指全局的单例实例在第一次被使用时构建
- 饿汉方式(急):指全局的单例实例在类装载时构建
class SingleModel{
public static void main(String[] args){
}
}
//饿汉式 急
class SingleTon{
private static SingleTon single=new SingleTon();
private SingleTon(){}
public static SingleTon getInstance(){
return single;
}
}
//懒汉式 慢
class SingleTon{
private static SingleTon single=null;
private SingleTon(){}
public static SingleTon getInstance(){
if(single==null){
single=new SingleTon();
}
return single;
}
}
单例模式要点:
- 某个类只能有一个实例
- 它必须自行创建这个实例
- .他必须自行向整个系统提供这个实例
从具体实现角度:
- 单例模式的类只提供私有的构造函数22. 类定义中含有一个该类的静态私有对象
- 该类提供了一个静态的共有的函数用于创建或获取它本身的静态私有对象
单例模式优点:
系统内存中该类只存在一个对象,节省了系统资源,对于一些需要频繁创建销毁的对象,使用单例模式可以提高系统性能。
单例模式缺点:
当想实例化一个单例类时,必须要记住使用相应的获取对象的方法,而不是使用new,可能会给其他开发人员造成困扰,特别是看不到源码的时候。
单例模式的使用场景:
- 需要频繁进行创建和销毁对象
- 创建对象时耗时过多或耗费资源过多,但又经常用到的对象
- 工具类对象
- 频繁访问数据库或文件的对象
三.继承
从代码上而言:在我们描述若干个类的时候,发现这些类中有大部分相同的成员, 所以就可以把这部分重复的内容抽取出来,用另外一个类描述
新的类就是父类
其他的就是子类
父类和子类之间的关系 继承关系 extends
从业务逻辑上而言:父类和子类之间必须是 is a 关系
is a 同一种类
Java当中的继承
- 类与类之间是 单继承
- 接口与接口之间是 多继承
- 继承之间是有传递性的
A->B->C - List item
在Java里面我们会有一个最终的父类
Object类 是任何一个类的最终父类 - 产生出我们Java当中继承体系
异常体系 IO体系 Socket体系
集合体系
子类父类之间,成员的一些特点
1. 成员变量
- 父类中有(非私有) 子类中没有 访问父类的
- 父类中没有 子类中有 访问子类的
- 父类中有(非私有) 子类中有 访问子类的
- 父类中有(非私有) 子类有同名静态变量 访问子类静态的
this存的是当前对象的地址 用于区分调用者
super指向的是其父类(的字节码)空间
局部->子类成员变量(堆)->子类静态变量(静态区) ->父类成员变量(非静态父类空间)->父类静态变量(静态区)
2.构造函数
父类的构造函数会优先于子类的构造函数运行
为什么?父类为子类准备一些数据
构造函数的第一句有一个隐藏的super(参数列表)
对于super(参数列表)调用,前提是父类必须有相应的构造函数
this(…)也在第一句 冲突不?不冲突
因为this(…)会转接到其他构造函数,其他的构造函数最终不会再转接回去,第一句只能是super(…)
3. 成员函数
子父类当中存在重名函数(非私有,参数列表也相同)
这种情况叫做函数的重写
重写的意义?保留父类的函数声明(功能),子类对功能进行改进
子类重写函数的权限 至少大于等于父类函数(非私)的权限
//一旦有private 就不考虑继承
code
class ExtendsDemo01{
public static void main(String[] args){
}
}
class Person{ //extends Object
String name="哈哈";
int age;
sleep(){}
}
class Worker extends Person{
work(){}
}
class Student extends Person{
study(){}
}
四.final关键字
- final可以修饰变量 表示该变量所存储的数据的地址不可更改
final int a=3;
final int[] arr=new int[10]; - final修饰类 该类不能被继承
- final修饰函数 该函数不能被重写
什么时候用?看具体需求
五.Object类
Object类是Java当中所有类的最终父类
Object类中有哪些常用方法?
- Class<?> getClass()
获取该类的字节码文件对象(xxx.class) - int hashCode()
哈希表 哈希函数 默认以对象的物理内存地址作为哈希值 - boolean equals(Object obj)
Obj的equ默认比对象之间的地址!
new Person 张三 10
new Person 张三 10 - Object clone()
对象的复制(浅复制) - String toString()
返回该对象的字符串表现形式 - void finalize()
当对象被垃圾回收期回收时,调用此函数
六.抽象类
抽象:不确定 不具体 模糊不清
由来:
在我们定义一些子类的是发现其中有相同行为, 那么可以将这些相同的行为抽取出到父类,有一个问题就是,这些行为只能由具体的子类去实现, 但是放到父类中,不符合基本逻辑,我们不能以偏概全, 所以父类当中中的这个函数就不能具体实现,不能有具体的函数体。所以讲该函数定义为抽象函数,函数具体如何实现 由子类决定,重写决定。 那么,具有抽象函数的类 就称之为抽象类
注意事项
1.抽象类绝对不能创建对象
如果一个子类继承自抽象类时,如果没有完全重写抽象函数,那么这个类也必须是抽象的
2.抽象类一定要有抽象函数吗?不一定
- 抽象类一定有构造函数吗?有
- 抽象类和一般类唯一的区别就在于 这家伙有抽象函数而已!
- 抽象类一般是作为父类存在的吗?是的
抽象类abstract不能和哪些关键字共存
- private :因为一个abstract方法需要被重写,所以不能修饰为private;
- final:因为一个abstract方法需要被重写。被final修饰的方法是不能被重写的,所以不能同final共存
- static:因为一个abstract方法没有方法体。静态方法需要对方法体执行内容分配空间,所以不能同static共存;(abstract是没有实现的,不能产生对象,而是static是属于类的,类本身是已经存在的对象)
- .synchronized: 是同步的,然而同步需要具体的操作才能同步,但, abstract是只有声明没有实现的(即,使用synchronized关键字的是需要有具体的实现同步的操作的,但是使用abstract是只有声明而没有实现的,这样就产生了冲突)
- native:他们本身的定义就是冲突的,native声明的方法是移交本地操作系统实现的,而abstract是移交子类对象实现的,同时修饰的话,导致不知道谁实现声明的方法
code
class AbstractDemo01{
public static void main(String[] args){
Dog d=new Dog();
d.jiao();
/*
Animal a=new Animal();
a.jiao();
*/
}
}
abstract class Animal{
String name;
int age;
Animal(){}
void sleep(){}
abstract void jiao();
}
class Dog extends Animal{
}
class Cat extends Animal{
}
七.接口
- 接口的由来:
如果一个抽象类中所有的方法都是抽象的
那么这个抽象类就可以用接口去表述
接口就是一个特殊的抽象类 - 接口的特征:
interface替代class
此时类和接口之间只能是实现关系
并且 接口此时已经不能在当做类去看待了
接口里面的函数一律是 public abstract 隐藏的默认的
接口里面的变量一律是 public static final
- 接口的作用:1.为类添加功能 2.作为一种中间传递(规范 规约)
- 类与接口之间多实现关系:给类多加功能
- 接口与接口之间多继承关系:只保留函数声明,并未指定具体执行,所以不会产生二义性
code
class InterfaceDemo{
public static void main(String[] args){
拉布拉多 卡夫卡=new 拉布拉多();
卡夫卡.叫();
卡夫卡.导盲();
卡夫卡.缉毒();
}
}
interface 导盲功能{
public void 导盲();
}
interface 缉毒功能{
public void 缉毒();
}
interface 拆家功能{
public void 拆家();
}
abstract class 动物{
public abstract void 叫();
}
class 拉布拉多 extends 动物 implements 导盲功能,缉毒功能{
@Override
public void 叫(){
System.out.println("我是拉布拉多");
}
@Override
public void 导盲(){
System.out.println("我会导盲");
}
@Override
public void 缉毒(){
System.out.println("我会缉毒");
}
}
class 黑背 extends 动物{
@Override
public void 叫(){
System.out.println("我是黑背");
}
}
class 二哈 extends 动物{
@Override
public void 叫(){
System.out.println("我是二货");
}
}
抽象类和接口的区别:
- 抽象类要被子类继承,接口要被类实现。
- 接口只能做方法声明,抽象类中可以作方法声明,也可以做方法实现。
- 接口里定义的变量只能是公共的静态的常量,抽象类中的变量是普通变量。
- 接口是设计的结果,抽象类是重构的结果。
- 抽象类和接口都是用来抽象具体对象的,但是接口的抽象级别最高。
- 抽象类可以有具体的方法和属性,接口只能有抽象方法和不可变常量。
- 抽象类主要用来抽象类别,接口主要用来抽象功能。