兴隆大院网站哪个公司做的,企业网上登记注册,营销型网站的定位,成都旅游十大必去景区抽象类
在继承体系下#xff0c;父类有些方法可能是要被重写的#xff0c;如果我们事先就知道某些方法需要重写的话#xff0c;我们可以不用在父类里面具体实现这个方法#xff0c;这时候我们会用到抽象方法#xff0c;这时候我们会用到关键字abstract关键字来修饰
publ…抽象类
在继承体系下父类有些方法可能是要被重写的如果我们事先就知道某些方法需要重写的话我们可以不用在父类里面具体实现这个方法这时候我们会用到抽象方法这时候我们会用到关键字abstract关键字来修饰
public abstract class Animal {protected abstract void eat();
}例如上面的Animal 类每一个动物都会吃但是每一个动物却吃的食物不同父类的eat方法无法完全描述某个对象这时候子类就需要重写这个方法如果我们不想在父类具体实现这个eat方法的话我们可以写成抽象方法~~
说完抽象方法我们来类比一下抽象类 如果一个类中没有包含足够的信息来描绘一个具体的对象这样的类就是抽象类 抽象类也是用abstract 修饰的~~
注意要点 有抽象方法的类一定是抽象类所以如果方法被abstract修饰那类也必须由abstract修饰否则编译报错 抽象类是不能进行实例化的但是可以有继承的向上转型和向下转型~~ 被private、static、final 修饰的方法不能是抽象方法 因为抽象方法就是为了被子类重写的根据重写的规则被private、static、final修饰的方法确实不能被重写 抽象类被继承后继承后子类要重写父类中的抽象方法除非子类也是抽象类必须要使用 abstract 修饰无论是谁继承了抽象类都必须重写所有的抽象方法否则编译报错~~ 当Dog继承Animal必须重写Aniaml所有的抽象方法~~ 如果Dog还是抽象类Cat 继承 Dog并且在 Cat 不是抽象的情况下我们要在 Cat 这个类重写所有的抽象方法即包括 Animal 也包括 Dog 的抽象方法
抽象类的作用 抽象类就是用来被继承的 谁继承了抽象类都必须重写抽象方法否则编译报错这也是为了多加一层编译器的校验 接口 接口就是公共的行为规范标准大家在实现时只要符合规范标准就可以通用。 在Java中接口可以看成是多个类的公共规范是一种引用数据类型 我们使用 intarface 来定义接口就是把class替换成interface public interface Ieat {void eat();
}接口虽然不是类但是接口编译完成后字节码文件的后缀格式也是.class 接口的使用规则 接口的成员方法是默认都是public static final 修饰的 接口的成员方法默认都是 public abstract 修饰的 当你在接口里定义了一个成员变量的时候你必须对其进行初始化 如果你想具体实现某些方法你可以使用 static 或者 default 来进行修饰 public interface Ieat {static void eat(){//...}default void eat2(){//...}
}访问权限也是和之前讲的是一样的被static就是默认权限的静态方法被default 修饰就是默认访问权限。 接口不能有实例化代码块、静态代码块也不能有构造方法~~ 如果类没有实现接口中的所有的抽象方法则类必须设置为抽象类如果被继承就必须重写所有的抽象方法 这个和抽象类是类似的~~ 软性规则 创建接口时, 接口的命名一般以大写字母 I 开头. 接口的命名一般使用 “形容词” 词性的单词. 阿里编码规范中约定, 接口中的方法和属性不要加任何修饰符号, 保持代码的简洁性. 接口的继承 接口与接口之间可以多继承。即用接口可以达到多继承的目的。 接口可以继承一个或者多个接口, 达到复用的效果. 使用 extends 关键字。 interface IA{void eat();
}interface IB{void sleep();
}interface C extends IA,IB{}接口的作用 解决了 Java 不能多继承的问题 意味着一个类可以有多个接口 如果子类由继承父类还有多个接口的时候我们要先继承后接口先extends 再 implements 快捷键搭建接口当中的抽象方法 IDEA 中使用 ctrl i 快速搭建接口当中的抽象方法~~ 或者使用 alt enter 进行选择implements methods 进行快速搭建接口你选择Make ‘Dog’ abstract 的话就是讲这个类变为抽象类~~ 接口的好处
public class Animal {protected String name;protected int age;
}public interface Irun {void run();
}public class Cat extends Animal implements Irun{public Cat(String name, int age) {this.name name;this.age age;}Overridepublic void run() {System.out.println(this.name 正在跑步);}
}public class Dog extends Animal implements Irun{public Dog(String name, int age) {this.name name;this.age age;}Overridepublic void run() {System.out.println(this.name 正在跑步);}
}public class Test {public static void walk(Irun irun){irun.run();}public static void main(String[] args) {walk(new Dog(旺财,11));walk(new Cat(小咪,10));}
}接口也可以有动态绑定和多态~~ 由于接口可以实现多态所以程序员可以不关注类型只要有这个接口的类都能调用里面的接口方法而不用去关心这是什么类。 Object 类 Object是Java默认提供的一个类。Java里面除了Object类所有的类都是存在继承关系的。默认会继承Object父类。即所有类的对象都可以使用Object的引用。 我们这里先重点关注一下上面标出来的三个方法toStringequalshashCode
toString打印对象
class Person{public String name;public int age;}public class Test {public static void main(String[] args) {Person person new Person();System.out.println(person);}
}我们在数组里知道直接打印数组名的话会出现包含数组的地址的一串字符串~~ 如果直接打印对象的话也会出现和数组类似的情况这是为什么 Java所有的类都会继承Object类在调用println的时候我们来看看一共调用了哪些方法
首先println 方法如下 之后无论是走if 语句还是else 语句都会调用toString方法 最后就会来到toString 方法这里getClass.getName()就是类名然后加符号最后调用hashCode找到地址。 但是如果我们重写了 toString 方法的话根据前面的知识优先调用子类的方法来打印对象内容。 class Person{public String name;public int age;Overridepublic String toString() {return Person{ name name \ , age age };}
}这样的话我们就会优先调用子类自己的toString 方法 我们可以使用编译器自动生成toString方法 和之前搭建getter、setter还有构造方法是一样的只是这里选择的是toString()
class A{public String name;public int age;Overridepublic String toString() {return A{ name name \ , age age };}
}equals 在Java当中如果使用 来进行比较时 如果比较的是基本数据类型的话就是比较两个的数值相不相同 如果比较的是引用数据类型就会比较他们的地址相不相同 来我们看一下源码 还是一样的直接调用equals方法还是比较两个对象的地址所以如果想比较两个对象的内容相不相同就必须重写equals方法~~ public boolean equals(Object o) {if (this o) return true;if (o null || getClass() ! o.getClass()) return false;Person person (Person) o;return age person.age Objects.equals(name, person.name);}class Person{public String name;public int age;public Person(String name, int age) {this.name name;this.age age;}Overridepublic String toString() {return Person{ name name \ , age age };}Overridepublic boolean equals(Object o) {if (this o) return true;if (o null || getClass() ! o.getClass()) return false;Person person (Person) o;return age person.age Objects.equals(name, person.name);}
}public class Test {public static void main(String[] args) {Person person1 new Person(张三,10);Person person2 new Person(张三,10);System.out.println(person1.equals(person2));}
}比较对象中内容是否相同的时候一定要重写equals方法。 hashCode
源码 native 说明这是本地方法这个是有C/C代码编写的我们是看不到的 简单来说hashCode方法可以找到对象的内存地址 public class Test {public static void main(String[] args) {Person person1 new Person(张三,10);Person person2 new Person(张三,10);System.out.println(person1.hashCode());System.out.println(person2.hashCode());}
} 由于这是两个不同的对象所以他们的内存地址是不一样的~~
但是如果我们认为当两个对象的内容是一样的那地址就应该是一样的话我们就需要重写hashCode 方法~~ Overridepublic int hashCode() {return Objects.hash(name, age);}这样他们的地址就会是一样的显示~~ 快捷键搭建
以上三个方法都能使用快捷键快速搭建 内部类 内部类就是在类里面再定义一个类这个类定义的位置和外部类的成员是相同的。 静态内部类 被static修饰的内部成员类称为静态内部类。 class A{public int age;public static int price;public A(){System.out.println(A()......);}public void methodA1(){System.out.println(methodA1()......);}public static void methodA2(){System.out.println(methodA2()......);}static class B{public void methodB(){//age 10;//err,静态内部类只能访问外部类的静态成员//A();//不要在静态内部类中调用外部类的构造方法构造方法是没有静态的所以构造方法一定不是静态方法//methodA1(); //err,静态内部类只能访问外部类的静态成员,methodA1不是类方法静态成员方法price 10;methodA2();}}//.....
}注意事项 静态内部类只能访问外部类的静态成员 创建静态内部类
A.B b new A.B();我们可以将静态内部类当成外部类的一个静态成员静态成员的访问不需要创建对象我们可以通过类名来访问于是我们通过 A.B 就访问到了静态内部类然后就通过new A.B 就可以完成创建了 实例内部类 未被static 修饰的实例内部类就是实例内部类 实例内部类可以自由访问外部类的任意成员如果实例内部类和外部类有重名的成员时在内部类中优先访问自己的如果真的相访问外部类同名的成员时我们可以使用 外部类类名.this.成员 即可~~ class A{public int age;public static int price;public A(){System.out.println(A()......);}public void methodA1(){System.out.println(methodA1()......);}public static void methodA2(){System.out.println(methodA2()......);}public void methodA3(){System.out.println(methodA3()......);}class C{public int age 10;public void methodC(){System.out.println(age);methodA3();System.out.println(A.this.age);methodA1();A.this.methodA1();}public void methodA1(){System.out.println(C::methodA1()......);}}//.....
}public class Test{public static void main(String[] args) {A.C c new A().new C();c.methodC();}
}创建实例内部类 我们要先创建外部类再去创建实例内部类 A.C c new A().new C();当然也可以分部去写
A a new A();
A.C c a.new C();注意事项 1.外部类中的任何成员都 可以在实例内部类方法中直接访问 2.实例内部类所处的位置与外部类成员位置相同因此也受public、private等访问限定符的约束 3.在实例内部类方法中访问同名的成员时优先访问自己的如果要访问外部类同名的成员必须外部类名 称.this.同名成员 来访问 4.实例内部类对象必须在先有外部类对象前提下才能创建 5.实例内部类的非静态方法中包含了一个指向外部类对象的引用 6.外部类中不能直接访问实例内部类中的成员如果要访问必须先要创建内部类的对象。 匿名内部类
class A{public void test1(){System.out.println(heihei);}
}public class Test{public static void main(String[] args) {new A(){}.test1();}}通过后面的 .方法 来调用相应的方法。 我们也可以重写匿名内部类的方法 但是要注意不能使用对象来接收匿名内部类 接口也可以使用
interface A{void test1();
}public class Test{public static void main(String[] args) {new A(){public void test1(){System.out.println(haha);}};}}和上面不一样的是接口是一定要重写其中的抽象方法的并且花括号后面是不能直接 .方法 的而是要通过被接收后然后去再去调用相应的方法~~
因此接口是可以被接收的接收后也是可以继续使用的 局部内部类 局部内部类是定义在方法里的因此它的生命周期和方法是一样。 public void A() {//...class D{ //......}//...}