继承、抽象类、接口
1.什么是继承?如何完成一个继承关系?
继承实际上是一种类与类之间关系,是一种通过现有的类【父类】,创建出新类【子类】的机制。子类可以得到父类中的部分变量和方法。
如何继承:通过extends关键字实现继承关系
格式:
访问限制修饰符 class 子类的类名 extends 父类的类名{
}
//现有的类
public class Person{
}
//创建Person的子类
public class Student extends Person{
}
Person类就是父类
Student类就是子类
2.子类对象创建过程
2.1子类对象在创建的时候,默认要调用父类无参数的构造方法。
/**
* Person类充当了父类
* @author Administrator
*
*/
public class Person {
public Person(){
System.out.println("Person类的无参数构造方法");
}
public Person(String value){
System.out.println("Person类的有参数构造方法");
}
}
/**
* Student类就是子类
* @author Administrator
*
*/
public class Student extends Person{
public Student(){
System.out.println("Student子类的无参数构造方法");
}
}
2.2我们可以在子类的构造方法中用过super关键字,调用父类中的任意一个构造方法执行。
/**
* Person类充当了父类
* @author Administrator
*
*/
public class Person {
public Person(){
System.out.println("Person类的无参数构造方法");
}
public Person(String value){
System.out.println("Person类的有参数构造方法,参数是value=="+value);
}
public Person(int value){
System.out.println("Person类的有参数构造方法,参数是value=="+value);
}
}
/**
* Student类就是子类
* @author Administrator
*
*/
public class Student extends Person{
public Student(){
//super(); //调用父类无参数构造方法
super("Student");
System.out.println("Student子类的无参数构造方法");
}
}
总结:子类对象在创建的时候,总是会先调用父类的构造方法创建出父类对象,然后在执行子类的构造方法,创建出子类对象。可以使用super关键字让子类调用指定的父类的构造方法创建父类对象。
3.Java中子类的继承性
子类的继承性是指子类可以从父类中继承那些变量和方法;
子类的继承性与访问限制修饰符有关。
1.子类与父类在同一个包中,子类可以继承父类中除过private修饰的变量和方法。
2.在不同的包中,子类可以继承父类中protected和public修饰符修饰的变量和方法,private和缺省的修饰的变量和方法是不能被继承。
3.子类中的变量和方法,一部分是从父类继承的,另外一部分是子类自己定义的
4.java中的访问限制修饰符
访问限制修饰符就是用来限定java元素【类,变量,方法,接口...】,在哪些情况下可以访问,哪些情况不能访问。【保护隐私】
访问限制修饰符分别有:
public【公共的】 private【私有的】 protected【受保护的】 缺省的【友好的】
1.public【公共的】任何元素都可以访问 [类,变量,方法,接口]
2.private【私有的】创建者自己可以访问,其他的元素不能访问 [变量,方法]
3.protected【受保护的】与创建者有关系【继承】的可以访问,没有关系的其他元素不能访问[变量,方法]
4.缺省的【友好的】 什么都不写 同一个包中可以访问,不同包就不能访问[类,变量,方法,接口].
类上面可以使用public【公共的】和缺省的 访问修饰符。
1.被public修饰的类,可以在任何地方被访问。
2.被缺省的修饰符修饰的类,只能被同一个包中其他类访问,跨出包就不能访问。
5.java中的包
1.为了方便管理java类。我们在开发应用程序的时候,会编写很多类,而类多了以后不利于管理,所以可以将功能相似的类统一放在一个程序包中,方便管理。
2.为了区分名称相同的类。通过隶属于不同的包,来区分名称相同的类。
3.包创建的语句所出现的位置,类的首行。
4.格式:package 包名;
例如:package com.yfbdemo.test1;
5.包名的名称规则:
1.合法的标识符
2.由多个合法标识符组成,中间通过【.】分割
3.不能有大写和空格 Com.Baidu--错误
4.公司域名倒置+项目名称【简写】+功能名称
例如: com.baidu.map.test 、 com.baidu.image.service 、com.github.wxpay.sdk
com.baidu.map.test---百度公司的地图项目的测试包
com.baidu---公司域名倒置
map---项目名称【简写】
test---功能名称
5.在使用某个包中的类的时候,需要通过import引入类所在的包
6.在IDEA开发工具中自动导包。
6.成员变量的隐藏和方法重写
成员变量的隐藏
1.在同一个类中,局部变量的名称与成员变量的名称相同。可以通过this.成员变量名称,强制调用,被隐藏的成员变量值。
2.在子类中,自己定义的成员变量与继承自父类中的某一个成员变量名称相同。可以通过super.成员变量名称,强制调用,被隐藏的成员变量值。
public class TestClass {
public String pub_str="TestClass公共的";
}
package com.click369.test1;
public class TestSonClass extends TestClass{
//在子类中,自己定义的成员变量与继承自父类中的某一个成员变量名称相同
public String pub_str="zhangsan";
public void test1(){
System.out.println("pub_str=="+pub_str);
System.out.println("pub_str=="+super.pub_str);
}
}
方法重写
1.在同一个类中方法名称相同,参数不同。
2.在子类中自己定义的一个方法,与从父类中继承的方法一模一样,这时子类重写了父类的方法。可以通过super.方法名称,强制调用继承自父类的方法。
public class TestClass {
public void testMethod(){
System.out.println("TestClass类的testMethod");
}
}
package com.click369.test1;
public class TestSonClass extends TestClass{
//在子类中自己定义的一个方法,与从父类中继承的方法一模一样,这时子类重写了父类的方法。
public void testMethod(){
System.out.println("TestSonClass类的testMethod");
}
public void test1(){
testMethod();
super.testMethod();
}
}
7.上转型对象的含义和特征
子类对象赋值给父类变量----上转型对象
public class TestClass {
public String getInfo(){
return "父类的实例方法";
}
}
public class SonClass extends TestClass{
public String info(){
return "子类的实例方法";
}
}
public class TestMain {
public static void main(String[] args) {
//t1里面保存了父类的对象
TestClass t1=new TestClass();
//父类的对象只能调用父类的方法
System.out.println(t1.getInfo());
//s1里面保存了子类的对象
SonClass s1=new SonClass();
//子类的对象可以调用子类自己定义的方法
System.out.println(s1.info());
//子类的对象也可以调用从父类继承的方法
System.out.println(s1.getInfo());
//上转型对象--子类对象赋值给父类变量
TestClass t2=new SonClass();
//上转型对象,只能调用被子类继承的方法,子类自己的方法就无法调用
//如果需要上转型对象调用子类自己的方法,将上转型对象强制转换成子类对象
SonClass s2=(SonClass)t2;
System.out.println(s2.info());
System.out.println(t2.getInfo());
}
}
方法参数为父类类型:
public class TestClass {
public String getInfo(){
return "父类的实例方法";
}
}
public class SonClass extends TestClass{
public String info(){
return "子类的实例方法";
}
}
public class TestMain {
public static void testMethod(TestClass tc){
}
public static void main(String[] args) {
//1、传递父类的对象
TestClass t1=new TestClass();
testMethod(t1);
//2、传递子类的对象
SonClass s1=new SonClass();
testMethod(s1);
//3、传递上转型对象
TestClass t2=new SonClass();
testMethod(t2);
}
}
8.什么是抽象类?为什么使用抽象类?抽象类中的元素?抽象类的使用?
1.什么是抽象类?
抽象类也是一个类class,使用abstract关键字修饰的类
2.格式:访问限制修饰符 abstract class 类名{}
public abstract class TestClass{
}
3.为什么使用抽象类?
----最简单的说法也是最重要的理由:接口和实现分离
4.抽象类中的元素
----抽象类也是一个类,它可以有实例变量,类变量,构造方法,实例方法,类方法,【抽象方法】
----抽象方法--用abstract关键字修饰,没有方法体,能出现在抽象类中。抽象是不能用final修饰的。
public abstract class TestClass {
public int testid=1001;
public static String testname="抽象类";
public TestClass(){
System.out.println("抽象类TestClass的构造方法");
}
public void testMethod(){
System.out.println("抽象类中的实例方法");
}
public static void testStaticMethod(){
System.out.println("抽象类中的类方法");
}
//抽象方法
public abstract void test11();
}
5.抽象类的特点
····抽象类不能new,可以通过上转型对象构造出抽象类的对象。
····当一个普通的java类继承一个抽象类以后,要重写抽象类中的抽象方法,否则将这个普通的java类该成抽象类
····抽象类可以继承抽象类。
····抽象类中可以有抽象方法,也可以一个抽象方法都没有。
····抽象类对象调用抽象方法,实际上实在调用被子类重写以后的方法
public abstract class TestClass {
public int testid=1001;
public static String testname="抽象类";
public TestClass(){
System.out.println("抽象类TestClass的构造方法");
}
public void testMethod(){
System.out.println("抽象类中的实例方法");
}
public static void testStaticMethod(){
System.out.println("抽象类中的类方法");
}
//抽象方法
public abstract void test11();
}
public class SonClass extends TestClass{
public void test11() {
}
}
/*
public abstract class SonClass extends TestClass{
}
*/
public class TestMain {
public static void main(String[] args) {
//1.抽象类不能创建对象。
//TestClass t1=new TestClass();
//2.通过上转型对象构造出抽象类的对象
TestClass t2=new SonClass();
}
}
6.抽象类的意义:
····提供可由子类实现的公共形式,子类根据自身的特点,按照自己的意图重写构造这个公共形式。
····优点:可以结构化我们的程序,达到代码重用的效果
9.什么是接口?为什么使用接口?接口中的元素?接口的使用?
接口
接口本质与抽象类相似,都是提供可由子类实现的一般形式[公共形式],实现接口的子类可以根据自身的特点来扩展一般形式[公共形式]。
定义:
通过interface关键来定义一个接口。
格式:访问限制修饰符 interface 接口名称{}
public interface MyInter{
}
interface MyInter{
}
接口本质与抽象类的意义相似:
提供去由子类实现的公共形式,子类通过继承/实现抽象类/接口,根据自身的特点重新构造这个公共形式。
为什么有了抽象类还要学习接口?
因为在java中所有的继承关系都是单继承关系。类与类的继承关系是单继承关系,一个类无法继承多个类,接口的存在就是为了克服类的单继承问题而产生的。因此上一个类是可以实现多个接口的。
接口中的元素
1.接口中所有的变量都是public static final修饰的类变量,可以省略public static final修饰符
2.接口中可以有类方法【jdk8.0开始接口被增强可以有静态方法、接口默认方法】
3.接口中可以有抽象方法,所有的抽象方法都是public abstract,可以省略public abstract
4.接口中的所有的元素都是public修饰符修饰的,除过接口默认方法。
public interface MyInterface {
//1.接口中所有的变量都是public static final修饰的类变量,可以省略public static final修饰符
int num=100;
public String name="zhangsan";
public static String address="xian";
//2.接口是没有构造方法
//public MyInterface(){}
//3.接口中没有是实例方法
//public void testMethod(){}
//4.接口中可以有类方法【jdk8.0开始接口被增强可以有静态方法、接口默认方法】
public static void testMethod(){}
//5.接口中可以有抽象方法,所有的抽象方法都是public abstract,可以省略public abstract
public abstract void abstractMethod();
void abstractMethod1();
}
//接口中的元素
final修饰的类变量
Static修饰的类方法
public abstract抽象方法
因为接口中的所有的元素都是public修饰符修饰的,因此上接口继承接口以后,会将父接口中的所有元素全部继承【全继承】
//接口可以继承接口,并且是全继承【接口中中的元素都是public】
public interface TestInterface extends MyInterface{
}
接口的使用
通过让类使用implments关键字去实现这个接口,或者多个接口。如果有多个接口中间使用“,”分割。
public interface MyInter{
}
public interface TestInter{
}
public class TestClass implments MyInter{ //实现一个接口
}
public class TestClass implments MyInter,TestInter{//实现多个接口
}
类实现接口
一个普通的类通过implments关键字实现一个或多个接口。需要重写接口中的抽象方法,否则将这个普通的类变成抽象类。
public interface MyInterface {
//接口中的所有变量都是public static final修饰的静态常量.
//所以在接口中定义变量的时候,实际上是省略了public static final修饰符的。
int interid=1001;
String intername="zhangsan";
//jdk8.0中接口增强:接口静态方法、接口默认方法。
public static void test2(){
System.out.println("接口中的静态方法");
}
public abstract void test3();
}
public class TestClass implements MyInterface{
public void test3() {
}
}
public abstract class TestClass implements MyInterface{
}
不光是普通的类可以实现接口,抽象类也是可以实现接口。
接口可以继承接口,继承关系是全继承【子接口会继承父接口中的所有元素】
public interface TestInterface extends MyInterface{
public abstract void test3();
}
10.抽象类与接口的区别
实现:抽象类的子类使用 extends 来继承;接口必须使用 implements 来实现接口。
构造函数:抽象类可以有构造函数;接口不能有。
实现数量:类可以实现很多个接口;但只能继承一个抽象类【java只支持单继承】。
访问修饰符:接口中的方法默认使用 public 修饰;抽象类中的抽象方法可以使用Public和Protected修饰,如果抽象方法修饰符为Private,则报错:The abstract method 方法名 in type Test can only set a visibility modifier, one of public or protected。
11.接口回调对象的含义和特征
接口是不能new,通过实现了这个接口的子类去创建接口对象。
接口回调对象与上转型对象相似
上转型对象:子类的对象赋值给父类的变量
接口回调对象:将实现该接口的子类对象赋值给该接口变量。
接口回调对象的访问特征:
----接口回调对象和实现该接口的子类对象还有接口名称,可以调用接口中的类变量
----接口回调对象和实现该接口的子类对象,都不能调用接口的类方法,只能接口名称去调用接口中的类方法
----接口回调对象和实现该接口的子类对象,可以调用接口中的抽象方法,只不过调用的是被子类重写以后的抽象方法
----接口回调对象是不能调用子类自己定义的变量和方法,子类对象可以调用子类自己定义的变量和方法。
/**
* interface是创建接口的关键
* @author Administrator
*
*/
public interface MyInterface {
String name="zhangsan";
public static void testStatic(){
System.out.println("MyInterface接口中的类方法");
}
void test();
}
---------------------------------------------------------------
public class MyClass implements MyInterface{
@Override
public void test() {
System.out.println("接口的子类重写接口中的抽象方法");
}
public void myClassMethod(){
System.out.println("子类自己定义的方法");
}
}
----------------------------------------------------------------
public class TestMain {
public static void main(String[] args) {
//接口是不能new
//MyInterface my=new MyInterface();
//那么我们就要通过实现该接口的子类来创建接口对象
//接口回调对象
//实现该接口的子类对象赋值给接口变量--接口回调对象
MyClass mc=new MyClass();
//myinter---接口回调对象
MyInterface myinter=mc;
//1、接口回调对象和实现该接口的子类对象还有接口名称,可以调用接口中的类变量
System.out.println(myinter.name);
System.out.println(mc.name);
System.out.println(MyInterface.name);
//接口回调对象是不能调用接口中的类方法
//myinter.testStatic();
//实现接口的子类不能调用接口中的类方法
//mc.testStatic();
//可以使用接口名调用接口中的类方法
//2.接口回调对象和实现该接口的子类对象,都不能调用接口的类方法,只能接口名称去调用接口中的类方法
MyInterface.testStatic();
//3.接口回调对象和实现该接口的子类对象,可以调用接口中的抽象方法,只不过调用的是被子类重写以后的抽象方法
myinter.test();
mc.test();
//4.接口名称是不能调用接口中的抽象方法
//MyInterface.test();
//5.接口回调对象是不能调用子类自己定义的变量和方法,子类对象可以调用子类自己定义的变量和方法。
//myinter.myClassMethod();
mc.myClassMethod();
}
}
当一个类中的方法的参数是接口类型,那么我们可以传递实现该接口的子类对象,也可以传递接口回调对象。
/**
* interface是创建接口的关键
* @author Administrator
*
*/
public interface MyInterface {
String name="zhangsan";
public static void testStatic(){
System.out.println("MyInterface接口中的类方法");
}
void test();
}
-----------------------------------------------------------------------
public class TestClass {
public void kaihui(MyInterface inter){
System.out.println("TestClass中的实例方法,参数是接口类型");
}
}
-----------------------------------------------------------------------
public class MyClass implements MyInterface{
@Override
public void test() {
System.out.println("接口的子类重写接口中的抽象方法");
}
public void myClassMethod(){
System.out.println("子类自己定义的方法");
}
}
-----------------------------------------------------------------------
public class TestMain {
public static void main(String[] args) {
//当一个类中的方法的参数是接口类型,那么我们可以传递实现该接口的子类对象,也可以传递接口回调对象。
TestClass tc=new TestClass();
//MyInterface接口的子类对象
MyClass mc=new MyClass();
tc.kaihui(mc);
//接口回调对象
MyInterface inter=new MyClass();
tc.kaihui(inter);
}
}
12.static \ this \ super \ final 关键字
static关键字
static--静态的 【提前分配好内存空间】
----1.使用static修饰的成员变量就是静态成员变量,或者类变量。
----2.使用static修饰的方法就是静态方法,或者类方法。
----3.使用static修饰的元素会在程序执行之前提前分配好内存空间。会在多个同类型对象之间共享,可以认为是多个同类型对象之间的交集存在。
this关键字
----1.this调用本类中的属性,也就是类中的成员变量;
----2.this调用本类中的其他方法;
----3.this调用本类中的其他构造方法,调用时要放在构造方法的首行。
super关键字
this -- 出现在哪一个类中表示当前这个类的对象。【调用本类中的变量和方法】
super出现在哪一个类就表示该类的父类对象【用来在子类调用父类中的变量和方法】
super的使用
super()---调用父类无参数构造方法
super(xxxx)-----调用父类有参数构造方法
public Student(){
//调用父类有参数构造方法
super("zhangsan");
System.out.println("Student子类的无参数的构造方法");
}
super.变量名称----调用被子类隐藏的成员变量值
例如:
public void test1(){
//可以通过super.成员变量名称,强制调用,被隐藏的成员变量值。
System.out.println("name=="+super.name); //zhangsan
}
super.方法名称([xxxxxx])-----调用被子类继承来的父类的方法
-----------------------------------------------------------------------
public void testMethod(){
//强制调用继承自父类的方法
super.testMethod();
}
final关键字
1.final--最终的
2.可以修饰类,变量,方法
3.final修饰的java类,没有子类,不能被继承
final修饰的变量,不能被重新赋值,就是一个常量。
final修饰的方法,不能被重写。
方法重写--子类中有方法与继承自父类的方法一样,就是子类重写了父类的方法。
4.用final修饰的变量,不能被重新赋值。【变量就成了常量】
5.用final修饰的方法,不能被重写【方法重写】。