当前位置:网站首页>面试知识点
面试知识点
2022-07-26 10:42:00 【qq_41482600】
1、抽象类与接口的区别
1.1、成员的区别:
抽象类:
构造方法:有构造方法,用于子类实例化使用。
成员变量:可以是变量,也可以是常量。
成员方法:可以是抽象的,也可以是非抽象的。
接口:
构造方法:没有构造方法
成员变量:只能是常量。默认修饰符:public static final
成员方法:jdk1.7只能是抽象的。默认修饰符:public abstract (推荐:默认修饰符请自己永远手动给出),jdk1.8可以写以default和static开头的具体方法
1.2、类和接口的关系区别:
类与类:
继承关系,只能单继承。可以多层继承。
类与接口:
实现关系,可以单实现,也可以多实现。
类还可以在继承一个类的同时实现多个接口。
接口与接口:
继承关系,可以单继承,也可以多继承。
1.3、体现理念不同:
抽象类里面定义的都是一个继承体系中的共性内容。
接口是功能的集合,是一个体系额外的功能,是暴露出来的规则
当你关注一个事物的本质的时候,用抽象类;当你关注一个操作的时候,用接口。
2、内部类是什么,使用场景
2.1、什么是内部类
将一个类定义在一个类里面或一个方法里面
2.2、内部类的种类
成员内部类、静态内部类、匿名内部类、局部内部类
2.2.1 成员内部类
成员内部类是最普通的内部类,成员内部类可以访问外部类的所有属性和方法,但外部类访问内部类的属性和方法,必须实例化内部类,成员内部类不能包含静态的属性和方法。
public class InnerClassTest {
public int outField1 = 1;
protected int outField2 = 2;
int outField3 = 3;
private int outField4 = 4;
public InnerClassTest() {
// 在外部类对象内部,直接通过 new InnerClass(); 创建内部类对象
InnerClassA innerObj = new InnerClassA();
System.out.println("创建 " + this.getClass().getSimpleName() + " 对象");
System.out.println("其内部类的 field1 字段的值为: " + innerObj.field1);
System.out.println("其内部类的 field2 字段的值为: " + innerObj.field2);
System.out.println("其内部类的 field3 字段的值为: " + innerObj.field3);
System.out.println("其内部类的 field4 字段的值为: " + innerObj.field4);
}
public class InnerClassA {
public int field1 = 5;
protected int field2 = 6;
int field3 = 7;
private int field4 = 8;
// static int field5 = 5; // 编译错误!普通内部类中不能定义 static 属性
public InnerClassA() {
System.out.println("创建 " + this.getClass().getSimpleName() + " 对象");
System.out.println("其外部类的 outField1 字段的值为: " + outField1);
System.out.println("其外部类的 outField2 字段的值为: " + outField2);
System.out.println("其外部类的 outField3 字段的值为: " + outField3);
System.out.println("其外部类的 outField4 字段的值为: " + outField4);
}
}
public static void main(String[] args) {
InnerClassTest outerObj = new InnerClassTest();
// 不在外部类内部,使用:外部类对象. new 内部类构造器(); 的方式创建内部类对象
// InnerClassA innerObj = outerObj.new InnerClassA();
}
}
2.2.2 静态内部类
静态内部类就是在成员内部类多加了一个 static 关键字。静态内部类只能访问外部类的静态成员变量和方法(包括私有静态)
public class InnerClassTest {
public int field1 = 1;
public InnerClassTest() {
System.out.println("创建 " + this.getClass().getSimpleName() + " 对象");
// 创建静态内部类对象
StaticClass innerObj = new StaticClass();
System.out.println("其内部类的 field1 字段的值为: " + innerObj.field1);
System.out.println("其内部类的 field2 字段的值为: " + innerObj.field2);
System.out.println("其内部类的 field3 字段的值为: " + innerObj.field3);
System.out.println("其内部类的 field4 字段的值为: " + innerObj.field4);
}
static class StaticClass {
public int field1 = 1;
protected int field2 = 2;
int field3 = 3;
private int field4 = 4;
// 静态内部类中可以定义 static 属性
static int field5 = 5;
public StaticClass() {
System.out.println("创建 " + StaticClass.class.getSimpleName() + " 对象");
// System.out.println("其外部类的 field1 字段的值为: " + field1); // 编译错误!!
}
}
public static void main(String[] args) {
// 无需依赖外部类对象,直接创建内部类对象
// InnerClassTest.StaticClass staticClassObj = new InnerClassTest.StaticClass();
InnerClassTest outerObj = new InnerClassTest();
}
}
2.2.3 匿名内部类
匿名内部类有多种形式,其中最常见的一种形式莫过于在方法参数中新建一个接口对象 / 类对象,并且实现这个接口声明 / 类中原有的方法了:
线程池执行方法execute里面 new Runnable,Runnable就是匿名内部类
public class InnerClassTest {
public int field1 = 1;
protected int field2 = 2;
int field3 = 3;
private int field4 = 4;
public InnerClassTest() {
System.out.println("创建 " + this.getClass().getSimpleName() + " 对象");
}
// 自定义接口
interface OnClickListener {
void onClick(Object obj);
}
private void anonymousClassTest() {
// 在这个过程中会新建一个匿名内部类对象,
// 这个匿名内部类实现了 OnClickListener 接口并重写 onClick 方法
OnClickListener clickListener = new OnClickListener() {
// 可以在内部类中定义属性,但是只能在当前内部类中使用,
// 无法在外部类中使用,因为外部类无法获取当前匿名内部类的类名,
// 也就无法创建匿名内部类的对象
int field = 1;
@Override
public void onClick(Object obj) {
System.out.println("对象 " + obj + " 被点击");
System.out.println("其外部类的 field1 字段的值为: " + field1);
System.out.println("其外部类的 field2 字段的值为: " + field2);
System.out.println("其外部类的 field3 字段的值为: " + field3);
System.out.println("其外部类的 field4 字段的值为: " + field4);
}
};
// new Object() 过程会新建一个匿名内部类,继承于 Object 类,
// 并重写了 toString() 方法
clickListener.onClick(new Object() {
@Override
public String toString() {
return "obj1";
}
});
}
public static void main(String[] args) {
InnerClassTest outObj = new InnerClassTest();
outObj.anonymousClassTest();
}
}
2.2.4 局部内部类
局部内部类使用的比较少,其声明在一个方法体 / 一段代码块的内部,而且不在定义类的定义域之内便无法使用,其提供的功能使用匿名内部类都可以实现,而本身匿名内部类可以写得比它更简洁,因此局部内部类用的比较少。来看一个局部内部类的小例子:
public class InnerClassTest {
public int field1 = 1;
protected int field2 = 2;
int field3 = 3;
private int field4 = 4;
public InnerClassTest() {
System.out.println("创建 " + this.getClass().getSimpleName() + " 对象");
}
private void localInnerClassTest() {
// 局部内部类 A,只能在当前方法中使用
class A {
// static int field = 1; // 编译错误!局部内部类中不能定义 static 字段
public A() {
System.out.println("创建 " + A.class.getSimpleName() + " 对象");
System.out.println("其外部类的 field1 字段的值为: " + field1);
System.out.println("其外部类的 field2 字段的值为: " + field2);
System.out.println("其外部类的 field3 字段的值为: " + field3);
System.out.println("其外部类的 field4 字段的值为: " + field4);
}
}
A a = new A();
if (true) {
// 局部内部类 B,只能在当前代码块中使用
class B {
public B() {
System.out.println("创建 " + B.class.getSimpleName() + " 对象");
System.out.println("其外部类的 field1 字段的值为: " + field1);
System.out.println("其外部类的 field2 字段的值为: " + field2);
System.out.println("其外部类的 field3 字段的值为: " + field3);
System.out.println("其外部类的 field4 字段的值为: " + field4);
}
}
B b = new B();
}
// B b1 = new B(); // 编译错误!不在类 B 的定义域内,找不到类 B,
}
public static void main(String[] args) {
InnerClassTest outObj = new InnerClassTest();
outObj.localInnerClassTest();
}
}
3、内部类作用
3.1、内部类可以很好的实现隐藏。
非内部类是不可以使用 private和 protected修饰的,但是内部类却可以,从而达到隐藏的作用。同时也可以将一定逻辑关系的类组织在一起,增强可读性。
3.2、间接的实现多继承。
每个内部类都能独立地继承自一个(接口的)实现,所以无论外部类是否已经继承了某个(接口的)实现,对于内部类都没有影响。如果没有内部类提供的可以继承多个具体的或抽象的类的能力,一些设计与编程问题就很难解决。所以说内部类间接的实现了多继承。
边栏推荐
猜你喜欢

.net5wtm (asp.net core) PgSQL unpacking operation

Oracle cannot start tnslistener service cannot start

IAR sprintf 浮点 在UCOS 总格式化成0.0的问题

Uniapp uses the simple method signalr (only for web debugging, cannot package apps)

抽象工厂及其改进示例

el-table实现可编辑表格
![[leetcode daily question 2021/2/18] [detailed explanation] minimum number of turns of 995. K continuous bits](/img/de/62fca587cde95110c2a967ca93eea5.png)
[leetcode daily question 2021/2/18] [detailed explanation] minimum number of turns of 995. K continuous bits

20210807#1 C语言程序结构

The problem of formatting IAR sprintf floating point to 0.0 in UCOS assembly

$router和$route的区别
随机推荐
MD5 encryption
[leetcode daily question 2021/2/13]448. Find all the missing numbers in the array
Redis docker instance and data structure
el-table实现可编辑表格
Error[pe147]: declaration is incompatible with 'error problem
[leetcode每日一题2021/4/23]368. 最大整除子集
sigmod 函数与softmax 函数对比
json_ object_ put: Assertion `jso->_ ref_ count > 0‘ failed. Aborted (core dumped)
按二进制数中1的个数分类
.net operation redis set unordered collection
抽象工厂及其改进示例
.net operation redis list list
Analysis of the transaction problem of chained method call
Sql Server 数据库之完整性约束
[leetcode daily question 2021/8/30]528. Choose randomly by weight [medium]
从蚂蚁的觅食过程看团队研发(转载)
如何实现临时的图形要素现实
10 let operator= return a reference to *this
Sql Server之查询总结
鹏哥C语言第四课(3)