-----------android培训、java培训、java学习型技术博客、期待与您交流! ------------
一、抽象类
1、抽象方法:
(2)声明:
注意:抽象方法声明语句后要加分号。
2、抽象类:
3、抽象类的特点:
也就是说:抽象方法一定在抽象类中。
2)抽象类和抽象方法都要用abstract进行修饰
3)抽象类不能被实例化。即:抽象类不可以用new创建对象。因为调用抽象方法没意义。
4)抽象类中的抽象方法要被使用,必须由子类复写其所有的抽象方法后,建立子类对象调用。如果子类只覆盖了部分抽象方法,那么该子类还是一个抽象类,不能创建对象。
4、抽象类典型问题:
抽象类不能被实例化。
抽象类中的构造方法供子类实例化调用。
答: final:被final修饰的类不能有子类。而被abstract修饰的类一定是一个父类。
private: 抽象类中的私有的抽象方法,不被子类所知,就无法被复写。
而抽象方法出现的就是需要被复写。
static:如果static可以修饰抽象方法,那么连对象都省了,直接类名调用就可以了。
而抽象方法是没有方法体的,这样的调用无意义。
5、代码示例:
abstract class Student
{
abstract void study();//子类必须覆盖抽象方法。否则子类也是抽象类,也属于强制行为。,是抽象方法子类就必须复写
void sleep()//能有非抽象方法
{
System.out.println("躺着");
}
}
class BaseStudent extends Student
{
void study()
{
System.out.println("base study");
}
}
class AdvStudent extends Student
{
void study()
{
System.out.println("adv study");
}
}
class AbstractDemo
{
public static void main(String[] args)
{
new BaseStudent().study();
new BaseStudent().sleep();
new AdvStudent().study();
}
}
6、抽象类的作用:
7、产生抽象类的原因:
二、接口
1、接口出现的意义:
接口使抽象的概念更向前迈进了一步。interface这个关键字产生一个完全抽象的类,它根本没有提供任何具体实现。
2、接口的定义:
接口就是一组规范和要求,java接口是一些方法和特征的集合,但没有方法的实现,在java中接口定义的规范和要求是以抽象方法来实现。
接口被用来建立类与类之间的协议。
3、接口的成员特点:
(1)成员变量
是常量,默认修饰 public static final
(2)成员方法
都是抽象的,默认修饰 public abstract
4、关系
(1)类与类的关系(单继承)
是继承关系。类与类只能单继承,可以多重继承。
(2)类和接口的关系(多实现)
是实现关系。类可以多实现接口。
类在继承一个类的同时,可以实现多个接口。
(3)接口和接口的关系(多继承)
是继承关系。接口可以多继承接口。
代码示例:
interface A
{
void methodA();
}
interface B //extends A
{
void methodB();
}
interface C extends B,A//接口里面可以有多继承
{
void methodC();
}
class D implements C
{
public void methodA(){}
public void methodC(){}
public void methodB(){}
}
5、接口的特点:
内聚(类完成功能的能力)
编程规范:低耦合,高内聚。
6、接口和抽象类的区别:
(1)接口的出现避免了无法多继承的局限性。
抽象类只能被单继承。一个类只能单继承一个类。
接口可以多实现。一个类可以多实现多个接口。
(2)数据特点
1)抽象类中的数据特点:
成员变量:可以是变量,也可以是常量
成员方法:可以是抽象方法,也可以是非抽象方法
构造方法:有构造方法
2)接口中的数据特点:
成员变量:是常量。默认修饰 public static final
成员方法:都是抽象方法。都有默认修饰 public abstract
构造方法:没有构造方法
(3)定义功能的种类
抽象类中定义的是继承体系中的共性功能。
接口中定义的是继承体系中的扩展功能。
(4)与子类的关系
抽象类被继承。是"is a"关系:xx是yy的一种,属于yy的体系
接口被实现。是"like a"关系:xx像yy,具备yy的特点,但不属于yy的体系
7、使用接口的原因:
// Multiple interfaces.
interface CanFight {
void fight();
}
interface CanSwim {
void swim();
}
interface CanFly {
void fly();
}
class ActionCharacter {
public void fight() {
}
}
class Hero extends ActionCharacter implements CanFight, CanSwim, CanFly {
public void swim() {
}
public void fly() {
}
}
public class Adventure {
public static void t(CanFight x) {
x.fight();
}
public static void u(CanSwim x) {
x.swim();
}
public static void v(CanFly x) {
x.fly();
}
public static void w(ActionCharacter x) {
x.fight();
}
public static void main(String[] args) {
Hero h = new Hero();
t(h); // Treat it as a CanFight
u(h); // Treat it as a CanSwim
v(h); // Treat it as a CanFly
w(h); // Treat it as an ActionCharacter
}
} // /:~
8、使用接口的情况:
三、内部类
1、定义:
2、访问特点:
格式为:外部类名.this.x
(2)外部类要想访问内部类的成员,必须创建对象访问。
(3)要想生成内部类的对象,只能通过外部类的对象"new"出内部类的对象。
3、内部类的访问:
(1)外部类访问内部类
当内部类定义在外部类的成员位置,而且非私有,则可以在其他外部类中直接建立内部类对象
格式:外部类名.内部类名 变量名 = new 外部类对象().内部类对象()
如:Outer.Inner in = new Outer().new Inner()
(2)内部类的修饰符
当内部类在成员位置上,就可以被成员修饰符所修饰。比如:
private:将内部类在外部类中进行封装。只有内部类才能被private修饰。
Static:当内部类被static修饰后,内部类就具备static的特性。只能直接访问外部类中的static成员。出现了访问局限。
(3)静态内部类
当内部类在外部类的成员位置,且被static修饰时
a)外部其他类可直接访问静态内部类的非静态成员
格式:new 外部类名.内部类名().内部类成员
如:new Outer.Inner().function();
b)外部其他类可直接访问静态内部类的静态成员
格式:new 外部类名.内部类名.内部类成员
如:new Outer.Inner.function();
(4)注意:
当内部类中定义了静态成员,该内部类必须是static的。
class Outer {
private static int x = 3;
static class Inner// 静态内部类
{
static void function() {
System.out.println("innner :" + x);
}
}
static class Inner2 {
void show()// 不是静态方法必须通过new静态内部类然后调用方法
{
System.out.println("inner2 show");
}
}
public static void method() {
// Inner.function();
new Inner2().show();
}
}
class Demo {
public static void main(String[] args) {
// 静态内部类可以直接访问
Outer.method();
Outer.Inner.function();
}
}
/*output
inner2 show
innner :3
*/
4、什么时候使用内部类:
(2)内部事物在使用外部事物的内容
5、内部类的位置
(1)成员位置
1)可以被private修饰(Body,Heart)
2)可以被static修饰。(它访问的外部类的成员必须是静态的)
注意:只有定义在成员位置的内部类才能用private和static修饰
(2)局部位置(局部内部类)
1)可以直接访问外部类中的成员,因为还持有外部类的引用。
2)也可以直接访问局部成员,但是局部成员要用final修饰。
注意:局部内部类不能用private和static修饰
/*
内部类定义在局部时,
1,不可以被成员修饰符修饰
2,可以直接访问外部类中的成员,因为还持有外部类中的引用。
但是不可以访问它所在的局部中的变量。只能访问被final修饰的局部变量。
*/
class Outer {
int x = 3;
void method(final int a) {
final int y = 4;
class Inner {
void function() {
System.out.println(y);// 访问局部变量需要是final所修饰的
System.out.println(x);// 可以直接访问外部类变量
}
}
new Inner().function();
}
}
class Demo {
public static void main(String[] args) {
Outer out = new Outer();
out.method(7);
out.method(8);
}
}
/*output:
4
3
4
3
*/
练习1:
/* Write a class named Outer that contains an inner class named Innet.
* Add a method to Outer that returns an object of type Inner. In main(),
* create and initialize a reference to an Inner.
*/
public class Outer1 {
class Inner {
Inner() {
System.out.println("Inner()");
}
}
Outer1() {
System.out.println("Outer1()");
}
// make an Inner from within a non-static method of outer class:
Inner makeInner() {
return new Inner();
}
public static void main(String[] args) {
Outer1 o = new Outer1();
Inner i = o.makeInner();
}
}
/*output:
Outer1()
Inner()
*/
练习2:
/* Modify Exercise 1 so that Outer has a private String field (initialized
* by the constructor), and Inner has a toString() that displays this field.
* Create an object of type Inner and display it.
*/
public class Outer2 {
private String s;
class Inner2 {
Inner2() {
System.out.println("Inner()");
}
public String toString() {
return s;
}
}
Outer2(String s) {
System.out.println("Outer1()");
this.s = s;
}
Inner2 makeInner3() {
return new Inner2();
}
public static void main(String[] args) {
Outer2 o = new Outer2("Hi is risen!");
Inner2 i = o.makeInner3();
System.out.println(i.toString());
}
}
/*output:
Outer1()
Inner()
Hi is risen!
*/
四、匿名内部类
1、前提:
继承一个类或者实现一个接口(注意不要弄混匿名内部类的前提和多态的前提)。
2、格式:
new 父类名或者接口名()
{
重写父类方法或者实现接口中的方法。
也可以自定义其他方法。
};
3、实质:
其实匿名内部类就是一个父类的匿名子类对象,可以理解为带自定义内容的对象。
代码示例:
// Returning an instance of an anonymous inner class.
public class Parcel {
public Contents contents() {
return new Contents() { // Insert a class definition
private int i = 11;
public int value() {
return i;
}
}; // Semicolon required in this case
}
public static void main(String[] args) {
Parcel p = new Parcel();
Contents c = p.contents();
}
} // /:~
contents()方法将返回值的生成与描述这个返回值的类的定义结合在一起!
匿名内部类的语法指的是:“创建一个继承自Contents的匿名类的对象。”通过new表达式返回的引用被自动向上转型为对Contents的引用。
上述程序其实是下述代码的简化形式:
// Expanded version of Parcel.java
public class Parcel2 {
class MyContents implements Contents {
private int i = 11;
public int value() {
return i;
}
}
public Contents contents() {
return new MyContents();
}
public static void main(String[] args) {
Parcel2 p = new Parcel2();
Contents c = p.contents();
}
} // /:~
4、何时定义匿名内部类:
匿名内部类只是为了简化书写,匿名内部类有局限,通常定义匿名内部类时,该类方法不超过3个。
5、匿名内部类的好处和弊端:
(1)好处:
简化代码书写
(2)弊端:
1)不能直接调用自己的特有方法
2)不能执行强转换动作
3)如果该类里面方法较多,不允许使用匿名内部类
6、匿名内部类的使用规则:
一般只复写父类的功能,不定义新的功能,因为用父类引用无法调用新功能
7、使用局部内部类而不使用匿名内部类的情况:
(1)需要一个已命名的构造器,或者需要重载构造器时,用局部内部类;而匿名内部类只能用于实例化。
(2)需要不止一个该内部类的对象,用局部内部类。
匿名内部类代码示例:
abstract class AbsDemo {
abstract void show();
}
class Outer {
public void function() {
AbsDemo d = new AbsDemo() {
int num = 9;
void show() {
System.out.println("num===" + num);
}
void abc() {
System.out.println("haha");
}
};// 这就是匿名内部类
d.show();
// d.abc();//编译失败;多态中编译看左边,父类中没有abc()方法所以编译失败
}
}
class Demo {
public static void main(String[] args) {
new Outer().function();
}
}
/*output:
num===9
*/
练习:
interface Content {
int value();
}
class Anonymous {
public Content contents() {
return new Content() {
private int i = 11;
public int value() {
return i;
}
};
}
public static void main(String[] args) {
Anonymous a = new Anonymous();
Content c = a.contents();
int v = c.value();
System.out.println(v);
}
}
/*output:
11
*/