5.5 interface接口
//声明接口
public interface DbApi{
}
1>接口 api 程序接口 app = web前端 + 后端(程序 数据库) api
2>java 编程接口是一种编程规范对象 interface
3>声明接口,是一种编程规范,约束程序人员编写类
java 8 以前接口只能包括如下内容:
- 全局静态常量
- 抽象方法
java 8 开始接口包括内容如下:
-
全局静态常量
int i = 3; public final static int i = 3;
-
抽象方法
-
void conn();
-
public abstract void conn();//自动
-
-
静态实现方法 static
public static void conn(){ } //使用的时候可以直接通过接口 Db.conn()
-
默认实现方法 default
public default int pf(itn i){ return i*i; } //使用的时候,通过接口的实现类的对象实例来调用执行。
-
函数式接口(接口中有且只有一个抽象方法的接口)
使用的时候,是通过lambda表达式使用
()->{}java lambda表达式 ()=>{}javascript
public interface Db{
}
public interface A{
}
//B.java 编译后也是B.class
public interface B{
}
//接口允许多继承多实现
public interface MyAll extends Db,A,B{
}
使用接口,一般用的是接口的实现类,在java8开始可以通过接口名直接调用执行接口的静态实现方法。
interface Db{
static int pf(int i){
return i*i;
}
}
接口一般情况是不直接实例化使用,用的是接口实现类implements
使用接口的实现类
什么是单继承多实现?
java是单继承多实现
public class DbImpl implements Db,A,B,D{//单继承多实现
}
class A extends B implements C,D,E{
//继承B,实现C,D,E
}
B b = new A();
C c = new A();
D d = new A();
E e = new A();
A aa = new A();
//List 和 ArrayList 实现类
List list = new ArrayList();
//List接口的 实现类
使用接口的静态方法
System.out.println(Db.pf(3));
java 8 以前
接口-interface
interface A{
//常量
//抽象方法() 不使用abstract
}
java 8 开始
interface B{
//常量
//抽象方法()
//default 默认实现方法
//static 静态实现方法
}
A a = new B();//A B 关系? 架构中用的较多
-
B是A(父类)的子类
-
B继承了A
-
B是A接口的实现类
Db dm = new Db();//不好
1.产生匿名类
2.不能重复使用
定义接口
package cn.prictice2;
public interface Db {
String version = "1.0";
//接口中的属性,自动变为public final 全局常量
int i = 3;//全局静态常量
//void show();
//接口中的方法,会自动变为public abstract全局抽象,不写abstract也是抽象的方法
public abstract void conn();
static int pf(int i) {
return i * i;
}
// 接口中的static实现方法,会自动变为public ,静态实现方法通过接口名可以直接调用
default void version(){
System.out.println(System.getProperty("java.version"));
System.out.println(version);
}
//接口中的默认实现方法,是通过接口的实现类的实例对象,可以直接调用。
}
定义接口实现类
package cn.prictice2;
public class DbMySQLImpl implements Db{
@Override
public void conn() {
}
}
函数式接口概念?
有且只有一个抽象方法的接口,默认是函数式接口,函数式接口可以使用lambda表达式作为
方法接口参数来执行。
package cn.prictice2;
@FunctionalInterface
public interface MyUtil {
int pf(int i);
}
接口和抽象类的区别
//函数式接口 java1.8新技术-必须是一个接口,有且只有一个抽象方法,此接口主要用于lambda表达式编程,
//接口作为参数
interface MyUtil{
int pf(int i);
}
//JDBC组件,架构使用的就是接口,所以JDBC里边几乎全是接口
//Connectin 对象不是类 是接口,接口最终使用的是 implements 实现类 或 lambda表达式
//抽象类 最终使用的是子类 可以重写 重载相关的方法
jdbc接口 - 框架
javax.sql.Connection; 接口
DriverManager.class();//自动加载
集合 List Map Collection ArrayList
先定义接口,再实现接口类
5.6 内部类
共性内部类分为:
-
成员内部类
-
静态嵌套类
-
匿名内部类(直接new 抽象类,直接new 接口)
-
如果是函数式接口,可以使用lambda表达,这样可以避免new 接口产生内部匿名类
-
-
$1 $2
注意:
(1)内部类仍然是一个独立的类,在编译之后内部类会被编译成独立的.class文件,但是前面冠以外部类的类名和$符号。
(2)内部类不能用普通的方式访问,是外部类的一个成员,可以自由地访问外部类的成员变量,无论是否是private的。
(3)外部类不能直接访问其内部类,想要访问内部类,需实例化内部类
(4)内部类声明成静态的,就不能随便的访问外部类的成员变量了,此时内部类只能访问外部类的静态成员变量。
(5)其他类想要直接访问内部类,可直接实例化内部类
,方法如下:
外部类名.内部类 对象名 = new外部类().new 内部类();
eg:Out.In in = new Out().new In();
如果内部类是静态的,当其他类调用内部类可直接通过类名调用,格式如下:
外部类.内部类 对象名 = new 外部类.内部类()
eg:Out.In in2 = new Out.In();
当内部类是静态的,且方法也是静态的,此时可不需实例化对象
外部类.内部类.静态方法名();
eg:Out.In.fun();
package cn.prictice2;
public class Outter {
//成员 public 静态的内部类
public static class out{
public static void println(Object obj){
System.out.println(obj);
}
}
class Demo{
}
public static void main(String[] args) {
out.println("hello world 中文效果");
System.out.println("hello world 中文效果");
//方法体,代码中,局部内容类
//@Data
class Book {
private int id;
private String name;
}
}
}
package cn.prictice2;
public class Test {
public static void main(String[] args) {
Outter.Demo demo = new Outter().new Demo();
//System.out.println(demo);
Outter.out.println(demo);
}
}
5.7 hashCode() 和toString()
hashCode()
hashCoed 的特性:
1)HashCode的存在主要是用于查找的快捷性,如Hashtable,HashMap等,HashCode经
常用于确定对象的存储地址;
2)如果两个对象相同, equals方法一定返回true,并且这两个对象的HashCode一定相
同;
3)两个对象的HashCode相同,并不一定表示两个对象就相同,即equals()不一定为true,
只能够说明这两个对象在一个散列存储结构中。
4)如果对象的equals方法被重写,那么对象的HashCode也尽量重写。
面试题:
两个对象的 hashCode()相同,则值一定相同吗?不一定
package cn.prictice2;
public class HashCode {
public static void main(String[] args) {
System.out.println("Ma".hashCode());//2484
System.out.println("NB".hashCode());//2484
String s1 = new String("Ma");
String s2 = new String("NB");
System.out.println(s1.hashCode()); //2484
System.out.println(s2.hashCode()); //2484
}
}
不同的值计算出来的hashCode()可能相同,但同一个值的hashCode()是不会变的,
字符串值推hashCode(),但不能hashCode()的值推字符串的值。
作用
用map来存储对象,形式是key,value,不像list形式的集合有顺序的从0开始往集合里放数据,取值麻烦,存放值没有顺序,所以取值需要根据key去里面一一对比,等找到key相等的值就取出,这样就会造成效率问题。
用hashCode()将name计算为3373707,age计算为98511,存值根据计算后的数值进行对应位置的存储,get取值的时候再次将key计算为hashCode()值,同一个字符串hashCode()值相等,直接根据hashCode()值将对应位置的数据取出,不需要对key一一对比,提高效率。
toString()
toString()方法是Object类中的方法,而Java中所有的类都继承了object类。
在使用时可以将其重写。
5.8 enum枚举
枚举是实例对象是固定,实例是自动new,每个枚举类会自动继承java.lang.Enum 抽象类
如何声明枚举?
package cn.prictice2;
public class EnumDemo {
enum en1 {a, b, c}
enum color {RED, GREEN, BLUE}
enum num {
SUCCESS(200, "成功"), FAIL(400, "失败"), NOTFOUND(404, "未知"), ERROR(300, "错误");
public int code;
public String message;
num(int code, String message) {
this.code = code;
this.message = message;
}
public static num fromCode(int code) {
num nn = null;
for (num v : num.values()) {
if (v.code == code) {
nn = v;
break;
}
}
return nn;
}
public static num valueFrom(String name) {
return num.valueOf(name);
}
}
public static void main(String[] args) {
System.out.println("--------");
num n = num.SUCCESS;
System.out.println(n);//SUCCESS
System.out.println(n.message);//成功
System.out.println(n.code);//200
num err = num.fromCode(404);
System.out.println(err.message);//未知
System.out.println(num.valueFrom("ERROR"));//ERROR
System.out.println(num.valueOf("ERROR"));//ERROR
}
}