什么是抽象类
java语言中,用abstract 关键字来修饰一个类时,这个类叫作抽象类。抽象类是它的所有子类的公共属性的集合,是包含一个或多个抽象方法的类。抽象类可以看作是对类的进一步抽象。在面向对象领域,抽象类主要用来进行类型隐藏。
abstract修饰符可以用来修饰方法也可以修饰类,如果修饰方法,那么该方法就是抽象方法;如果修饰类,那 么该类就是抽象类。
语法
public abstract class Action{
public abstract void doSomething();
}
public void doSomething(){...}
抽象类的特点:
- 由abstract修饰的类叫做抽象类,也可以修饰抽象方法。
- 抽象类,不能使用new关键字来创建对象,它是用来让子类继承的。
- 抽象方法,只有方法的声明,没有方法的实现,它是用来让子类实现的。
- final 不能和abstract同时使用,final修饰的方法禁止重写, abstract修饰的方法要求重写 ,冲突
- 只有抽象类当中才能有抽象方法,普通类当中不能有抽象方法
抽象类不能new对象,那么抽象类中有没有构造器?
抽象类是不能被实例化,抽象类的目的就是为实现多态中的共同点,抽象类的构造器会在子类实例化时调 用,因此它也是用来实现多态中的共同点构造。
抽象类和抽象方法意义
总之抽象类和抽象方法起到一个框架作用。很方便后期的调用和重写 抽象方法是为了程序的可扩展性。重写抽象方法时即可实现同名方法但又非同目的的要求。
接口(Interface)
什么是接口
Java接口是一系列方法的声明,是一些方法特征的集合,一个接口只有方法的特征没有方法的实现,因此这些方法可以在不同的地方被不同的类实现,而这些实现可以具有不同的行为(功能)。
接口的特点
1.接口是使用Interface声明
2.一个类可以实现多个接口,但是抽象类不能继承多个
public class Student implements A,B,C,D{
//Student需要实现接口A B C D中所有的抽象方法
//否则Student类就要声明为抽象类,因为有抽象方法没实现
}
public static void main (String [] arge){
A a= new Student();
B b= new Student();
C c= new Student();
D d= new Student();
}
声明的是那个接口就只能使用声明接口中的方法以及Object中的方法
列如:a只能使用A接口中的方法以及Object中的方法
3.一个类实现了接口那么那个类就必须实现接口中的所有方法
4.接口中的变量都是静态常量(public static final修饰)
public interface Action{
public static final String NAME = "tom";
//默认就是public static final修饰的
int AGE = 20;
}
public static void main (String [] arge){
System.out.println(Action.NAME);
System.out.println(Action.AGE);
}
5.一个接口可以继承多个接口,但是实现该接口的实现类需要实现全部的方法(包括继承接口中的方法)
//接口A
public interface A {
void A();
}
//接口B
public interface B {
void B();
}
//接口C
public interface C extends A,B{
void c(int a,String...name);
}
//实现类
public class Test implements C {
@Override
public void A() {
}
@Override
public void B() {
}
@Override
public void c(int a, String... name) {
}
}
接口的作用
接口的最主要的作用是达到统一访问,就是在创建对象的时候用接口创建
【接口名】 【对象名】= new 【实现接口的类】
这样你像用哪个类的对象就可以new哪个对象了,不需要改原来的代码
1、Java接口中的成员变量默认都是public,static,final类型的(都可省略),必须被显示初始化,即接 口中的成员变量为常量(大写,单词之间用"_"分隔)
2、Java接口中的方法默认都是public,abstract类型的(都可省略),没有方法体,不能被实例化
3、Java接口中只能包含public,static,final类型的成员变量和public,abstract类型的成员方法
4、接口中没有构造方法,不能被实例化
5、一个接口不能实现(implements)另一个接口,但它可以继承多个其它的接口
6、Java接口必须通过类来实现它的抽象方法
7、当类实现了某个Java接口时,它必须实现接口中的所有抽象方法,否则这个类必须声明为抽象
接口与抽象类的区别
1.抽象类也是类,除了可以写抽象方法以及不能直接new对象之外,其他的和普通类没有什么不一样的。接 口已经另一种类型了,和类是有本质的区别的,所以不能用类的标准去衡量接口。
2.声明类的关键字是class,声明接口的关键字是interface。
3.抽象类是用来被继承的,java中的类是单继承。
4.类A继承了抽象类B,那么类A的对象就属于B类型了,可以使用多态 一个父类的引用,可以指向这个父类的任意子类对象 。注:继承的关键字是extends、
5.接口是用来被类实现的,java中的接口可以被多实现。 类A实现接口B、C、D、E..,那么类A的对象就属于B、C、D、E等类型了,可以使用多态 一个接口的引用,可以指向这个接口的任意实现类对象
内部类
内部类就是在一个类的内部定义了一个类,列如:A类中定义一个B类,那么B类相对A类来说就称为内部类,反之A类就是B类的外部类
外部类分为四种:
- 成员内部类
- 静态内部类
- 局部内部类
- 匿名内部类
成员内部类(实例内部类、非静态内部类)
public class Test {
public void out(){
System.out.println("这是外部类方法");
}
class Inner{
public void in(){
System.out.println("这是内部类方法");
}
}
public static void main(String[] args) {
Test test = new Test();
test.out();
//构建出Inner内部类的实例
Test.Inner inner = test.new Inner();
inner.in();
}
}
注意:成员内部类中是不能有静态变量和方法
调用内部类需要先实例化外部类通过外部类的实例对象再实例化内部类
【成员内部类能干什么?】
1.访问外部类的所有属性(这里的属性包括私有的成员变量,方法)
public class Test {
private int id=10;
public void out(){
System.out.println("这是外部类方法");
}
private void a(){
System.out.println("这是外部类方法a");
}
class Inner{
public void in(){
System.out.println(id+1);
System.out.println("这是内部类方法");
a();
}
}
public static void main(String[] args) {
Test test = new Test();
//
test.out();
Test.Inner inner = test.new Inner();
inner.in();
}
}
2.如果内部类中的变量名和外部类的成员变量名一样,要通过创建外部类对象 "."属性来访问外部类 属性,通过this.属性访问内部类成员属性
public class Test {
private int id=10;
public void out(){
System.out.println("这是外部类方法");
}
class Inner{
public int id = 1;
public void in(){
System.out.println("这是内部类方法");
System.out.println(Test.this.id);
System.out.println(id);
}
}
public static void main(String[] args) {
Test test = new Test();
Inner inner = test.new Inner();
inner.in();
}
}
静态内部类
看到名字就知道,使用你static修饰的内部类就叫静态内部类。
static的用法
1.static修饰成员变量:整个类的实例共享静态变量
2.static修饰方法:静态方法,只能够访问用static修饰的属性或方法,而非静态方法可以访问static修 饰的方法或属性
3.被static修饰了的成员变量和方法能直接被类名调用。
4.static不能修饰局部变量,切记,不要搞混淆了,static平常就用来修饰成员变量和方法。
public class Test {
private String name;
private static int age;
public void run(){
}
public static void go(){
}
public void test(){
StaticInnerClass sic = new StaticInnerClass(); //静态的内部类不需要依赖
sic.name = "tom";
sic.test1("张三");
StaticInnerClass.age=10;
StaticInnerClass.test2("xixi");
}
//j静态内部类
private static class StaticInnerClass{
private String name;
private static int age;
public void test1(String name){
System.out.println("name:"+name);
System.out.println("this.name:"+this.name);
System.out.println("StaticInnerClass.age:"+StaticInnerClass.age);
System.out.println("Test.age:"+Test.age);
//静态类不能访问非静态属性
//System.out.println(Test.this.name);
Test.go();
//静态类不能访问非静态方法
//Test.this.run();
}
public static void test2(String name){
//只能访问自己和外部类的静态属性和方法
System.out.println("test2中name:"+name);
//静态方法里面连自己类的非静态属性都不能访问
//System.out.println(this.name);
System.out.println("StaticInnerClass.age:"+StaticInnerClass.age);
System.out.println("Test.age:"+Test.age);
// 静态方法不能访问非静态属性
//System.out.println(Test.this.name);
Test.go();
// 静态方法不能访问非静态方法
//Test.this.run();
}
}
public static void main(String[] args) {
Test test = new Test();
test.test();
/*
name:张三
this.name:tom
StaticInnerClass.age:0
Test.age:0
test2中name:xixi
StaticInnerClass.age:10
Test.age:0
*/
}
}
注
1、我们上面说的内部类能够调用外部类的方法和属性,在静态内部类中就行了,因为静态内部类没有 了指向外部类对象的引用。除非外部类中的方法或者属性也是静态的。这就回归到了static关键字的用 法。
2、静态内部类能够直接被外部类给实例化,不需要使用外部类对象
局部内部类
声明在类中的类
可以访问外部类的方法以及变量
内部类不能被public、private、static修饰;
外部类不能访问局部内部类,只能在方法体中访问局部内部类,且访问必须在内部类定义之后,如果在方法开始访问内部类,无法构建出内部类的实例
public class Test {
private String name;
private static int age;
public void run(){}
public static void go(){}
//局部内部类要定义在方法中
public void test(){
String myname="aaa";
class LocalInnerClass{
private String name;
//不能定义静态属性
//private static int age;
public void test(String name){
//参数
System.out.println(name);
//内部类中变量name
System.out.println(this.name);
//方法中的变量
System.out.println(myname);
//外部类中的变量name
System.out.println(Test.this.name);
//外部类中的静态变量age
System.out.println(Test.age);
Test.this.run();
Test.go();
}
}
//局部内部类只能在自己的方法中用,因为局部内部类相当于一个局部变量,除了方法就找不到了。
LocalInnerClass lic = new LocalInnerClass();
lic.name="tom";
//给外部类中的变量age赋值
this.age=10;
给外部类中的变量name赋值
this.name="张三";
lic.test("test");
}
public static void main(String[] args) {
Test test= new Test();
test.test();
}
}
匿名内部类
匿名内部类
什么是匿名对象?如果一个对象只要使用一次,那么我们就是需要new Object().method()。 就可以 了,而不需要给这个实例保存到该类型变量中去。这就是匿名对象。
public class Test {
public static void main(String[] args) {
//这种就叫做匿名对象的使用,不把实例保存到变量中。
new Apple().test();
}
}
class Apple{
public void test(){
System.out.println("holle");
}
}
匿名对象:我只需要使用一次,那么我就可以不声明对象接收。
匿名内部类:我也只需要使用一次,那我就不需要在类中先定义一个内部类,而是等待需要用的时候,我 就在临时实现这个内部类
1.匿名内部类需要依托于其他类或者接口来创建
- 如果依托的是类,那么创建出来的匿名内部类就默认是这个类的子类
- 如果依托的是接口,那么创建出来的匿名内部类就默认是这个接口的实现类。
2.匿名内部类的声明及创建对象必须一气呵成,并且之后能反复使用,因为没有名字。
- 匿名内部类的声明及创建对象必须一气呵成,并且之后能反复使用,因为没有名字。
public class Test {
public static void main(String[] args) {
new Work() {
public void test() {
System.out.println("实现了Work中的test");
}
}.test();
}
}
interface Work{
void test();
}
匿名内部类有什么作用?
如果说我们一个接口中的方法我们只需要使用一次那么我们就需要先实现接口,在创建接口的一个实现类,退后通过我们定义的对象调用使用的接口 ,但是我们要是使用了匿名内部类的话我们只需要走一步,就是使用匿名内部类,直接将其 类的对象创建出来。实现里面的方法。
其实只要明白一点,new Work(){实现接口中方法的代码}; Work(){...}这个的作用就是将接口给实 现了,只不过这里实现该接口的是一个匿名类,也就是说这个类没名字,