Java基础
抽象类
- abstract
1.1 抽象方法
由abstract修饰的方法,没有方法体
1.2 抽象类
由abstract修饰的类,不能创建对象
抽象类中可以没有抽象方法
抽象方法所在的类一定是抽象类
抽象类要有子类创建对象
子类要创建对象的话,必须实现父类的所有抽象方法,否则该类仍时抽象类,不能创建对象
接口
- interface
一种类别的所有对象都具有的行为放在类里面,不同类别的对象具有的相同行为放接口中。
1.1 定义接口
interface 接口名{
变量:int x = 10; ---------默认 public static final修饰
方法:jdk1.8之前都是抽象方法(之后可以有普通方法),可以省略abstract,默认修饰符public
}
public interface Demo1 {
int x = 1;
//有public abstract修饰
void f();
}
public class Test2 {
public static void main(String[] args) {
//有final修饰
//Demo1.x = 4;
//有public static修饰
System.out.println(Demo1.x);
}
}
1.2 实现接口
implements
实现接口的类要实现接口中的所有方法,才可以创建对象
如果不实现接口中的所有方法,该类为抽象方法,不可以创建对象
public class Demo1Impl implements Demo1{
@Override
public void f() {
System.out.println("接口实现");
}
}
1.3 注意
接口和接口之间可以是 继承 关系
类和接口之间可以是 实现 关系,可以实现多个接口
在接口中用default或者static修饰的方法被作为普通方法
public interface Demo {
default void test1() {
System.out.println("test1");
}
static void test2() {
System.out.println("test2");
}
}
public class DemoImpl implements Demo{
}
public class Test {
public static void main(String[] args) {
Demo.test2();
DemoImpl di = new DemoImpl();
di.test1();
}
}
实现类的接口和父类都有同名方法,实现类调用的是父类中的方法
public class SubClass {
public void test1() {
System.out.println("subclass");
}
}
public class SubDemo extends SubClass implements Demo{
}
public class Test {
public static void main(String[] args) {
//Demo.test2();
//DemoImpl di = new DemoImpl();
//di.test1();
SubDemo sd = new SubDemo();
sd.test1();
}
}
如果一个类实现了两个接口,这两个接口中有同名的普通方法,会出现编译时错误,必须重写这个同名方法
public interface Demo {
default void test1() {
System.out.println("Demo");
}
}
public interface Demo2 {
default void test1() {
System.out.println("Demo2");
}
}
public class SubDemo2 implements Demo, Demo2{
//必须重写,否则编译错误
@Override
public void test1() {
//因为test1方法是实例方法,所以用对象调用
//Demo说明调用的是Demo中的test1方法
Demo.super.test1();
}
}
- 接口和抽象类的区别
抽象类 | 接口 |
---|---|
模板类 | 不同类型的共同行为 |
不能多继承 | 可以多继承 |
有构造方法 | 没有构造方法 |
变量是普通的变量 | 都是公有静态常量 |
普通方法 | 普通方法由default或static修饰 |
抽象方法没有默认修饰符 | 抽象方法默认修饰符为public |
3.函数式接口
接口中只有一个抽象方法->lambda表达式。
@FunctionalInterface
扩展知识
- 内部类
1.1 类体内部类
public class Demo {
//该内部类可以由private static修饰
//该内部类可以访问外部类的成员
class Inner{
//static int b = 0;//不可以定义静态成员
final static int c = 0;//可以定义静态常量
int a;
void test() {
System.out.println("类体内部类");
}
}
public static void main(String[] args) {
//创建内部类对象---Demo.Inner inner = new Demo().new Inner();
Demo.Inner inner = new Demo().new Inner();
inner.test();
}
}
public class Demo2 {
public int x;
public static int y;
static class Inner{
int a;
static int b = 1;//静态内部类可以定义静态和非静态成员
void test() {
//x = 2;//静态内部类不能访问外部非静态成员
y = 3;
System.out.println("静态内部类");
}
}
public static void main(String[] args) {
//创建静态内部类对象---Demo2.Inner inner = new Demo2.Inner();
Demo2.Inner inner = new Demo2.Inner();
inner.test();
}
}
1.2 方法内的内部类
public class Demo3 {
int x = 1;
static int y = 2;
void test() {
int a = 3;
a = 4;
class Inner{
int b = 4;//jdk1.7之后默认常量
//static int c = 5;//不能定义静态成员
final static int d = 6;//可以定义静态常量
void f() {
//a = 8;//如果用到方法中定义的变量,那该变量就变成常量
//可以访问外部成员
x = 11;
y = 22;
System.out.println("方法内的内部类");
}
}
new Inner().f();
}
public static void main(String[] args) {
new Demo3().test();
}
}
1.3 匿名内部类
public class Demo4 {
//创建了Object类的子类
Object obj = new Object() {
//不是类体不可以有方法,所以这是个类
public void f() {
System.out.println("匿名内部类");
}
public String toString() {
return "Hello";
}
};
//创建了IDemo接口的实现类
IDemo demo = new IDemo() {
@Override
public void f() {
System.out.println("接口方法的实现");
}
};
public static void main(String[] args) {
//new Demo4().obj.f();//Object里没有f方法,所以编译错误
System.out.println(new Demo4().obj.toString());//Object里有toString方法,obj重写了该方法
new Demo4().demo.f();
}
}
- lambda表达式
2.1函数式接口编程:接口中只有一个抽象方法,把方法通过匿名类实现的方法简化一个表达式的写法------使用lambda表达式
2.2 写法:()->{}
()表示形参列表
->符号 goes to
{}表示方法体
package com.java.day8;
/**
* lambda表达式
* @author ThinPad
*
*/
interface IA{
//输出hello
void test();
}
public class Demo {
public static void main(String[] args) {
/*
* IA ia = new IA() {
* @Override
* public void test() {
* System.out.println("hello");
* }
* };
*
* ia.test();
*/
//lambda表达式是上面匿名内部类的一种简写
IA ia2 = () -> {
System.out.println("lambda表达式");
};
ia2.test();
}
}
如果方法体中有一条语句,则大括号可省。
参数列表的数据类型可省。
当参数列表中只有一个参数时,则小括号可省。
如果方法体中有一条返回语句,则return可省。
简写方式:方法的归属名::方法名;
简写方式的使用:有与接口中相同返回类型,参数列表相同的方法时使用。
package com.java.day8;
interface A{
int test(int x, int y);
}
public class Demo6 {
public static void main(String[] args) {
Demo6 demo = new Demo6();
//A a = (x, y) -> {
// return demo.test2(x, y);
//};
//System.out.println(a.test(1, 2));
A a = demo :: test2;
System.out.println(a.test(1, 2));
}
int test2(int x, int y) {
return x + y;
}
}
package com.java.day8;
interface IDemo{
void showMessage(String msg);
}
interface IDemo2{
int max11(int x, int y);
}
public class Demo8 {
public static void main(String[] args) {
IDemo i = System.out::println;
IDemo2 i2 = Math::max;
i.showMessage("hello");
System.out.println(i2.max11(1, 2));
}
}
package com.java.day8;
public class Student {
private String name;
private int age;
public Student() {
System.out.println("no param!");
}
public Student(String name, int age) {
this.name = name;
this.age = age;
System.out.println("have param!");
}
}
package com.java.day8;
interface Demo11{
void getStudent();
}
interface Demo12{
void getStudent(String name, int age);
}
public class Test {
public static void main(String[] args) {
Demo11 demo = Student::new;
Demo12 demo2 = Student::new;
demo.getStudent();
demo2.getStudent("周", 18);
}
}