外观
类的加载机制
类的加载机制
类被虚拟机加载的条件:
1.产生对象,且只加载1次(子类对象的创建会引起超类的加载)
2.访问static成员也会引起类的加载(加载子类也会引起加载父类)
3.利用反射机制
反射的用法:
String className = "带包名的类名";
Class.forName(className);
作用:创建对象
接口(interface)
一种引用型的数据类型由其他东西构成
可以有成员变量(默认public static final修饰)相当于常量、内部类、抽象方法
不能有构造方法、代码块
默认abstract修饰,由常量、内部类或接口组成
(1)接口使用 interface关键字修饰;
(2)接口不可以实例化;
(3)实现类必须实现接口的所有方法(抽象类除外);
(4)实现类可以实现多个接口(java多继承);
(5)接口中的常量都是静态常量;
作用:
接口是一个规则(规范)
接口表达了某种能力
接口可以多继承
与抽象类的区别
相同
1.都表达某种规则和规范
2.都代表某种能力
3.都可以包含抽象方法
区别
1.包含的成员不同
接口:常量、抽象方法、内部类和接口
public interface InterfaceTest {
// 接口可以有常量
static final int TEST = 5;
// 接口可以有抽象方法
void fly();
// 接口具有内部类
class InnerClass{
public InnerClass() {
System.out.println("InterfaceTest.InnerClass");
}
}
// 接口可以包含接口
public interface InterfaceTest2{
static final String TEST = "InterfaceTest2";
void run();
// jdk8以后可以有默认实现的方法
default void test() {
System.out.println("default test()");
}
// jdk8以后可以有static实现的方法
static void test1() {
System.out.println("static test1()");
}
}
// {} 接口不能有代码块
// 接口不能有构造方法
// InterfaceTest(){
//
// }
// 内部类在本类实例化和外部类的实例化一样
InnerClass innerClass = new InnerClass();
}
抽象类:成员变量、成员方法、代码块、构造方法、类变量、类方法。与普通类一致
2.继承性不同
类是单继承接口是多继承多实现
一个类可以实现多个接口
3.表达的语义不同
实现类与抽象类是‘是”的关系(是......类)
实现类与接口是’有‘的关系(有......接口)
扩展
java为什么要产生接口
接口隔离原则(将一个大接口分成多个小接口)
适配器类(Adapter)
一个有接口的默认方法的抽象类
抽象类大多用来提供接口的默认实现
抽象类存在的价值:为抽象方法提供默认实现
JDK8以后接口中可以有默认实现的方法
// jdk8以后可以有默认实现的方法
default void test() {
System.out.println("default test()");
}
JDK8以后还有static方法
// jdk8以后可以有static实现的方法
static void test1() {
System.out.println("static test1()");
}
JDK9以后有私有方法(private)
面向接口编程的好处
利于大规模开发,多人配合
利于维护,利于工号实现类而不影响调用(消除了模块间的耦合性)
内部类
声明在类的内部的类
成员内部类:static内部类、普通内部类
局部内部类:匿名内部类、static局部内部类、普通局部内部类
成员内部类:在一个类的内部和外部使用无区别
作用:封装,隐藏
普通内部类的实例化:
本类内部类的实例:和外部类一样
本类的static方法内部:必须使用外部类对象.new 内部类构造方法
在另外一个类中:new 外部类构造方法.new 内部类构造方法
static的内部类
本类内部类的实例:和外部类一样
本类的static方法内部:必须使用new 外部类. 内部类构造方法
在另外一个类中:new 外部类.内部类构造方法
匿名内部类
定义一个没有名字的类,但它实现了某个接口,这个类只使用一次
public class InnerClassTest {
class InnerCalss{
public InnerCalss() {
System.out.println("InnerClass");
}
public String testInner() {
// System.out.println("testInner()");
return "testInner()";
}
}
// static修饰的内部类
static class InnerCalss1{
public InnerCalss1() {
System.out.println("InnerClass1");
}
}
// 内部类在本类实例化和外部类的实例化一样
InnerCalss innerCalss = new InnerCalss();
}
class Test{
// 另外的类实例化内部类对象需要外部类对象.内部类构造方法
InnerClassTest innerClassTest = new InnerClassTest();
InnerCalss innerCalss = innerClassTest.new InnerCalss();
// 简化以上
InnerCalss innerCalss2 = new InnerClassTest().new InnerCalss();
// static修饰的内部类的实例化需要使用外部类.static内部类构造方法
InnerCalss1 innerCalss1 = new InnerClassTest.InnerCalss1();
// 匿名内部类只使用1一次
public void testTest() {
System.out.println(
new InnerClassTest().new InnerCalss().testInner());
}
}
如何限制类的对象的个数
枚举类、单例模式
枚举类
public enum EnumTest {
// 枚举类的对象,不能有权限修饰符
object1,object2,object3;
private String name = "enum";
public static void main(String[] args) {
// 同一个类创建对象直接写常量
EnumTest enumTest1 = object1;
}
}
class Test1{
public static void main(String[] args) {
// 不同类创建enum对象使用类名.常量名
EnumTest enumTest2 = EnumTest.object2;
// 使用类名.valueOf()方法使用字符串创建对象
EnumTest enumTest3 = EnumTest.valueOf("object3");
}
}
除了可以限制对象的个数外与普通类没有区别
与普通类基本相同,但它的对象个数是由限制的,而普通类没有限制
枚举类创建对象的方法:
1.直接使用常量
在本类中EnumTest enumTest1 = object1;
在其他类中:EnumTest enumTest2 = EnumTest.object2;
2.使用类名.valueOf()方法使用字符串创建对象 EnumTest enumTest3 = EnumTest.valueOf("object3");
用处:
把整数转为可读性较好的标识
单例模式
一个类只能有一个对象
实现方式:
构造方法私有
static 工厂方法(返回一个它的对象)
public class SingleTest {
// 饿汉模式在一开始就创建对象
// SingleTest singleTest = new SingleTest();
// static变量保存唯一的对象
static SingleTest singleTest = null;
// 私有的构造方法
private SingleTest() {
}
// static工厂方法返回它的对象
public static SingleTest getObject() {
// 饱汉模式在工厂方法中先判断对象是否为空再创建对象
if (singleTest == null) {
singleTest = new SingleTest();
}
return singleTest;
}
}
class Test3{
public static void main(String[] args) {
SingleTest.getObject();
}
}
单例模式:单个实例(对象)模式,一个类保证有一个对象的开发模式
好处:
节省资源
实现方式:
1.私有的构造方法
2.static工厂方法返回它的一个对象
3.static变量保存唯一的对象
4.实例化时机:
饿汉模式:在类的第一行new对象
饱汉模式:在工厂方法中判断对象是否为null若为null则new一个对象并返回,若不为null就直接返回