面向对象编程
static关键字详解
static修饰的方法与变量与类一同加载,而非静态的需要new一个对象才加载
static修饰变量
static 关键字用来声明独立于对象的静态变量,可以直接通过类名来访问,而非static修饰的变量不能直接用类名访问,只能先新建一个对象再访问
static修饰方法
与变量相似,静态方法可以直接调用非静态方法和静态方法,而非静态方法只能调用非静态方法,原因就是加载的顺序不同
代码块
public class Person {
{
//代码块(匿名代码块)我们可以在此赋值
}
static{
//静态代码块
}
}
匿名代码块在构造器之前就创建了,但再静态代码块之前执行,可多次执行。
静态代码块在类加载就已存在,且只能执行一次。
如图所示:静态代码块先执行,再执行匿名代码块,再执行构造器
如图所示,静态代码块只执行一次
静态导入包
在Java中有一个Math类里有一个random()方法可以生成一个随机数,我们可以使用类来调用
public class test {
public static void main(String[] args) {
System.out.println(Math.random());
}
}
而如果我们静态导入包中的方法,就可以直接调用
import static java.lang.Math.random;
public class test {
public static void main(String[] args) {
System.out.println(random());
}
}
final
- 通过final修饰的类不能被继承,相当于到最后了
- 父类的final方法可以被继承,但不能被子类重写
- final修饰的变量不能被修改,被 final 修饰的实例变量(即非静态变量)必须显式指定初始值。
抽象类
使用方法:添加abstract修饰符
用abstract修饰的类是抽象类,用abstract修饰的方法是抽象方法,没有方法体,可以被别人实现
让A类继承抽象的Action类,我们可以看到图中给了我们两个选项,要么把A改为抽象类,要么重写doSomething方法
特点总结:
- 不能new抽象类,只能由子类去实现它,因此它是一种约束,即不能实例化,只能实例化他的非抽象类子类
- 抽象类里可以写非抽象方法,抽象方法必须在抽象类中
- 抽象类有构造方法,只是不能直接创建抽象类的实例对象而已。在继承了抽象类的子类中通过super()或super(参数列表)可以调用抽象类中的构造方法。
接口的定义与实现
接口可以实现多继承!
对比
- 普通类:只有具体实现
- 抽象类:具体实现和规范(抽象方法)都有
- 接口:只有规范!自己无法写方法,可以实现约束和实现分离
接口的简单说明
- 接口就是规范,定义的是一组规则,比如说你是汽车,就必须能跑;你是好人,就必须干掉坏人等等
- 接口的本质是契约,就像法律一样,制定后大家都遵守
- 面向对象的精髓,是对对象的抽象,最能体现这一点的就是接口
创建接口:新建一个class文件,把class改为interface
如图,idea很智能,抽象类,父类,子类,接口等文件前面的图标都不同
接口里的方法会默认加上public和abstract,如果我们加上,他还会提醒我们,接口里写方法也不能写方法体!接口定义的变量会默认加上public、static和final,即默认为常量,但一般不在接口里定义常量。
接口里都不写方法体,那这些方法如何实现呢?答案:实现类!
实现类
一般一个实现类对应一个接口,命名为接口名+Impl,后面加上implements+空格+接口名,表示实现的接口
如图,即成功建成了一个实现类,但报错了,原因是我们还未重写方法,这里可以用ctrl+insert快捷键选择插入,也可以用ctrl+i直接插入
实现了接口的类,就要重写接口中的方法!
一个实现类可以实现多个接口,直接在实现的第一个接口名后+’,’+另一个接口名,这样,我们就侧面实现了多继承
接口小结
- 接口里定义一些方法,让不同的人实现
- 接口实际上是一种约束
- 接口不能实例化,因为接口中甚至没有构造方法
- 必须要重写接口里的方法
- 接口可以实现多继承
- 接口里的方法默认为抽象方法,变量默认为常量
N种内部类(扩展)
成员内部类(只能有一个public类)
- 写在外部类中
如图所示,Outer为外部类,Inner即为成员内部类,新建一个内部类的对象并实现方法的调用
神奇的是,这个成员内部类创建的对象可以访问外部类的私有属性
同理,也能获得外部类的私有方法
如图,内部类中用一个Print方法调用out方法,在用inner调用Print方法
- 写在class类外,可以在里面加main方法搞测试
静态内部类
静态内部类加载的较快,与外部类一同加载,而此时id还未加载,因此无法调用getid方法输出id
局部内部类
写在方法中,与局部变量有相似的性质
匿名内部类
即没有名字的类
如图,我们没有用名字初始化类,不用将实例保存在变量中即可调用eat()方法,这就是匿名内部类的使用
看一段代码
public class Test {
public static void main(String[] args) {
new Apple().eat();
/*下面就是匿名内部类的使用
非匿名时的使用:Userservice userservice=new Userservice()
*/
new Userservice(){
@Override
public void hello() {
}
};
}
}
class Apple{
public void eat(){
System.out.println("1");
}
}
interface Userservice{
void hello();
}
这里面看不懂其实还不要紧,以后我们在多线程中会系统学习这些类及使用