接口
-
概念:当有一些扩展功能(不是所有类的共同功能)时,需要部分子类调用,这样就出现接口,提供子类实现一些扩展方法。接口不实现具体的功能,由实现它的子类来实现具体功能。
-
关键字:Interface关键字,接口和类是同级别的,类用class定义,接口用Interface定义。
-
接口的特点:
- 接口中只能定义常量,默认是public static final修饰变量【就变成公共静态常量】
- 没有构造方法,所以不能创建对象。
- 方法:默认是抽象方法public abstract修饰方法
-
接口的实现;
- 关键字:Implements,使用关键字实现接口。
- 在测试类中使用多态来实例化接口。
- 实现接口的类不是抽象类时,必须要重写接口所有的抽象方法,
-
类与类,类与接口,接口与接口的关系;
- 类与类之间是继承关系,单继承,多层继承。
- 类与接口之间是实现关系,一个类可以实现多个接口,同时还可以继承一个类。
- 接口与接口是继承关系,一个接口可以继承多个接口。
示例:
public class Animal2Test { public static void main(String[] args) { Panda panda = new Panda(); Animal2 an=panda; an.name="大熊猫"; an.age=8; System.out.println(panda.name); System.out.println(an.age); an.eat(); an.sleep(); System.out.println("=========="); an=new LittlePanda(); an.name="小熊猫"; an.age=3; System.out.println(an.name); System.out.println(an.age); an.eat(); an.sleep(); // 接口类的实现 LittlePanda littlePanda= (LittlePanda) an; littlePanda.eatMilk(); System.out.println("=========="); an=new Tigher(); an.name="老虎"; an.age=9; System.out.println(an.name); System.out.println(an.age); an.eat(); an.sleep(); } } abstract class Animal2 { public String name; public int age; abstract void eat(); abstract void sleep(); } class Panda extends Animal2 { // String name; @Override void eat() { System.out.println("熊猫吃竹子"); } @Override void sleep() { System.out.println("熊猫睡在森林"); } public void dengji(){ System.out.println("国家一级"); } } class LittlePanda extends Panda implements EatMilkInterface { @Override public void dengji() { System.out.println("国家二级"); } @Override public void eatMilk() { System.out.println("小熊猫吃奶"); } } class Tigher extends Animal2{ @Override void eat() { System.out.println("老虎吃饭"); } @Override void sleep() { System.out.println("老虎睡在笼子里"); } } interface EatMilkInterface { // 方法前面默认有public abstract修饰 void eatMilk(); }
-
抽象类与接口的区别:
- 抽象类;
- 可以定义常量,变量,抽象方法,非抽象方法,有构造方法,体现的共性功能。
- 接口:
- 只能定义常量,抽象方法,没有构造方法,体现扩展功能。
- 抽象类;
-
在JDK 1.8之后可以在接口定义用default /static修饰方法,这样就可以给出方法的具体实现,JDK1.9 之后增加私有方法和私有静态方法。
参数传递情况
参数类型
- 当方法的形参传一个引用类型的参数,那么就传递该类的对象。返回值是一个类类型,那就返回该类的子类对象。
public class Test {
public static void main(String[] args) {
int name = 10;
Student student = new Student();
Student s = getStudent(student, 12);
System.out.println(s.name); //结果12
System.out.println("==============");
Student s1 = s.test(new Student(), 20);
System.out.println(s1.name); //结果12
System.out.println("===========");
s = s.test(new Student(), 30);
System.out.println(s.name); //结果12
System.out.println("===========");
}
public static Student getStudent(Student student, int name) {
student.name = name;
return student;
}
}
class Student {
int name = 14;
public Student test(Student student, int name) {
Student student1 = new Student();
return this;
}
}
示例2:
public class Test2 {
public static void main(String[] args) {
// 测试当方法的形参是一个类类型时
int name = 10;
Student2 student = new Student2();
// 创建一个该类的对象,将此对象传递。
Student2 s = getStudent(student, 12);
System.out.println(s.name); //结果12
System.out.println("==============");
Student2 s1 = s.test(new Student2(), 20);
// s1接收的是返回的对象的地址,该对象的变量name是初始化后的值14
System.out.println(s1.name); //结果14
System.out.println("===========");
// 传递一个匿名对象,并返回这个对象,将其付给s,s的指向改变。
s = s.test2(new Student2(), 20);
System.out.println(s.name); //结果20
System.out.println("===========");
}
public static Student2 getStudent(Student2 student, int name) {
student.name = name;
return student;
}
}
class Student2 {
int name = 14;
public Student2 test(Student2 student, int name) {
Student2 student1 = new Student2();
// 返回了一个新开辟的对象空间地址。
return student1;
}
public Student2 test2(Student2 student, int name) {
student.name=name;
return student;
}
}
- 当方法的形参传递一个抽象类类型的参数,那就传递该类的子类对象。返回值是一个抽象类类型,那就返回该抽象类的子类对象。
public class Test3 {
public static void main(String[] args) {
// 测试当方法的形参是一个类类型时
int name = 10;
Student3 student = new Monitor();
// 创建一个该类的对象,将此对象传递。
Student3 s = getStudent(student, 12);
System.out.println(s.name); // 结果12
System.out.println("==============");
Student3 s1 = s.test(new Monitor(), 20);
// s1接收的是返回的对象的地址,该对象的变量name是初始化后的值14
System.out.println(s1.name); // 结果14
System.out.println("===========");
Monitor m= (Monitor) s1;
System.out.println(m.name); // 结果15
System.out.println("==========");
// 传递一个匿名对象,并返回这个对象,将其付给s,s的指向改变。
s = s.test2(new Monitor(), 20);
System.out.println(s.name); // 结果20
System.out.println("===========");
}
public static Student3 getStudent(Student3 student, int name) {
student.name = name;
return student;
}
}
abstract class Student3 {
int name = 14;
public Student3 test(Student3 student, int name) {
Student3 student1 = new Monitor();
// 返回了一个新开辟的对象空间地址。
return student1;
}
public Student3 test2(Student3 student, int name) {
student.name=name;
return student;
}
}
class Monitor extends Student3 {
int name=15;
/*
如果这个方法运行,就会重写父类的Test2的方法,返回结果12
public Student3 test2(Student3 student, int name) {
student.name=name;
return this;
}*/
}
- 当方法的参数传递一个接口类型的参数,那么就传递该接口的子类对象。返回值是一个接口类型,那就返回该接口的子类对象。
public class Test4 {
public static void main(String[] args) {
// 测试当方法的形参是一个类类型时
int name = 10;
Student4 student = new Monitor2();
// 创建一个该类的对象,将此对象传递。
Student4 s = getStudent(student, 12);
System.out.println(s.name); // 结果12
System.out.println("==============");
Student4 s1 = s.test(new Monitor2(), 20);
// s1接收的是返回的对象的地址,该对象的变量name是初始化后的值14
System.out.println(s1.name); // 结果14
System.out.println("===========");
Monitor2 m= (Monitor2) s1;
System.out.println(m.name); // 结果13
System.out.println("==========");
}
public static Student4 getStudent(Student4 student, int name) {
return student;
}
}
interface Student4 {
int name = 14;
Student4 test(Student4 student,int name);
}
class Monitor2 implements Student4 {
int name=13;
@Override
public Student4 test(Student4 student,int name) {
return student;
}
}
链式编程
- 当调完一个方法后,返回值是一个对象,那就可以继续使用这个对象打点.调方法。以此类推就是链式编程。System.out.println(getStudent(student, 12).name);这就是链式编程。
Student3 student = new Monitor();
// 创建一个该类的对象,将此对象传递。
Student3 s = getStudent(student, 12);
System.out.println(s.name); // 结果12
System.out.println(getStudent(student, 12).name);
System.out.println("==============");
abstract class Student3 {
int name = 14;
public Student3 test(Student3 student, int name) {
Student3 student1 = new Monitor();
// 返回了一个新开辟的对象空间地址。
return student1;
}
public Student3 test2(Student3 student, int name) {
student.name=name;
return student;
}
}
class Monitor extends Student3 {
int name=15;
}
导包
- 类与类的访问权限
权限名 | 同包相关类 | 同包无关类 | 不同包相关类 | 不同包无关类 |
---|---|---|---|---|
private | y | |||
缺省 | y | y | ||
protected | y | y | y | |
public | y | y | y | y |
- 不同包的类之间访问时,需要导包,基本语法:import +包名地址.包名(系统会自动调用)
- 快捷方法:Ctrl +Alt+o,导包优化,会删除多余包或者增加未导入的包
- 导包的语句位于class之外。导包也可以在创建对象时,将包的地址放到类名之前就不用导包了。
面向对象修饰符
-
权限修饰符:public、默认修饰符、protected、private
状态修饰符:static、final
抽象修饰符:abstract
-
修饰类的关键字
权限修饰符:public、默认修饰符
状态修饰符:final
抽象修饰符:abstract
-
修饰成员变量的关键字
权限修饰符:public、默认修饰符、protected、private
状态修饰符:static、final
-
修饰构造方法的关键字
权限修饰符**:public**、默认修饰符、protected、private
-
修饰成员方法的关键字
权限修饰符:public、默认修饰符、protected、private
状态修饰符:static、final
抽象修饰符:abstract
-
常用组合:成员变量;public static final
成员方法:public static
public abstract
public final
内部类
-
内部类的概述:把类定义在类中,此类就是内部类。
-
特点:内部类可以直接访问外部类的成员(包括私有的)。
外部类要访问内部类的成员,必须创建对象。(Inter in=new Inter();)
-
根据内部类的位置不同,可分为两种:成员内部类(定义在类中,方法外)局部内部类(定义在类中,方法内)
-
成员内部类在测试类中被访问:在测试类中创建对象
public class Test5 { public static void main(String[] args) { // Outer outer=new Outer(); // Outer.Inter s1=outer.new Inter(); // 测试类中访问成员内部类,创建对象的方法。 Outer.Inter s=new Outer().new Inter(); System.out.println(s.num); // 20 s.method(); // 20 // 10 // 外部类show方法 // 外部类打印了 } } class Outer{ int a=10; private void show(){ System.out.println("外部类show方法"); } class Inter{ int num=20; public void method(){ System.out.println(num); System.out.println(a); show(); Outer.this.method(); } } public void method(){ Inter in=new Inter(); System.out.println(in.num); System.out.println("外部类打印了"); } }
-
成员内部类的修饰符:
-
private:为了保证数据的安全
-
当成员内部类被private修饰,测试类不成创建内部类的对象,内部类不能被外部直接访问。利用private的成员可以在本类中被访问的特性来访问私有的内部类。
public class Test6 { public static void main(String[] args) { Outer2 outer=new Outer2(); // 不能直接利用此方法访问内部类 Outer.Inter s=new Outer().new Inter(); // 调用外部类的方法,访问本类中的私有内部类。 outer.getInter(); } } class Outer2{ int a=10; private void show(){ System.out.println("外部类show方法"); } // 私有的成员内部类只能在本类中被访问。 private class Inter2{ int num=20; public void method(){ System.out.println(num); System.out.println(a); show(); } } // 利用外部类的方法,创建对象访问私有的成员内部类。 public void getInter(){ Inter2 inter2 = new Inter2(); System.out.println(inter2.num); inter2.method(); } }
-
static:为了方便访问数据
- 内部类被static修饰后,内部类只能访问外部类的静态方法和变量,
- 内部类的成员方法可以是静态的,也可以是非静态的。
- 静态的内部类要被测试类调用采用此方法:外部类名.内部类名 名称=new 外部类名.内部类名();,注意:和测试类访问非静态内部类方法不一样。
public class Test7 { public static void main(String[] args) { // 不能直接利用此方法访问内部类 Outer.Inter s=new Outer().new Inter(); Outer3.Inter3 inter3= new Outer3.Inter3(); inter3.method(); } } class Outer3{ static int a=10; private static void show(){ System.out.println("外部类show方法"); } // 静态内部类只能在访问外部类的静态方法和静态变量。 // 静态内部类的成员方法可以是静态的,也可以是非静态的。 static class Inter3{ int num=20; public void method(){ System.out.println(num); System.out.println(a); show(); } } }
-
-
当内部类的成员变量和外部类的成员变量名相同时,访问各个变量的方法:
- 内部类类名.this.num :访问内部类的成员变量。
- 外部类类名.this.num :访问外部类的成员变量。
``要求:使用已知的变量,在控制台输出30,20,10。
class Outer {
public int num = 10;
class Inner {
public int num = 20;
public void show() {
int num = 30;
System.out.println(num);//30
System.out.println( Inner.this.num);//20
System.out.println( Outer.this.num); //10
}
}
}
class InnerClassTest {
public static void main(String[] args) {
Outer.Inner oi = new Outer().new Inner();
oi.show();
}
}