欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

Java基础第五节

程序员文章站 2022-06-21 18:53:59
...

继承、抽象类、接口

5.1 什么是继承?如何完成一个继承关系?

  1. 面向对象的特征之一。[封装,继承,多态]
  2. 继承是一种通过现有的类,创建出新类的机制。
  3. 继承实际上一种类与类之间关系。

代码说明:

首先有一个基类 Thing

public class Thing {

    public Thing() {
        System.out.println("Everything begins here!");
    }
}

然后有个子类命名为Shape(形状)继承Thing

public class Shape extends Thing {
    public String name = "Shape";
    private static String sname = "S-Shape";

    public Shape() {
        System.out.println("Here is constructor of Shape!");
    }

    public void getName() {
        System.out.println("This is getName of Shape! ");
    }

    public static void getSname() {
        System.out.println("Here is static getName of Shape");
    }
}

然后有个子类命名为Circle(圆)继承Shape

public class Circle extends Shape {

    public String name = "Circle";

    public Circle() {
        System.out.println("This is constructor of Circle!");
    }

    @Override
    public void getName() {
        System.out.println("This is getName of Circle! ");
    }

    public void getSuperName() {
        System.out.println(super.name);
    }

    public static void getSname() {
        System.out.println("Here is static getName of Circle");
    }

}

然后有一个测试类:

public class Test {

    public static void main(String[] args) {
        Shape shape = new Circle();
        System.out.println(shape.name);
        shape.getName();
        Shape.getSname();
        Circle.getSname();
        Circle circle = new Circle();
        circle.getSuperName();
        System.out.println(circle.name);
    }
}

结果:

Everything begins here!
Here is constructor of Shape!
This is constructor of Circle!
Shape
This is getName of Circle! 
Here is static getName of Shape
Here is static getName of Circle
Everything begins here!
Here is constructor of Shape!
This is constructor of Circle!
Shape
Circle

第一句语句

Shape shape = new Circle();

得到的结果是:

Everything begins here!
Here is constructor of Shape!
This is constructor of Circle!

继承的实现:

子类继承父类,在子类构造器生成的时候,会调用父类的构造器,如果没有显示的写出supper(),编译器会默认的给加上supper()无参构造器。如果想调用父类的有参构造器,就必须的显示的调用,编译器不会默认加上的。子类创建的时候,从子类开始一层一层的调用构造方法。

5.2子类对象创建过程?

  1. 子类对象在创建的时候,默认要调用父类无参数的构造方法。
package com.click369.test1;
/**
 * Person类充当了父类
 * @author Administrator
 *
 */
public class Person {

	public  Person(){
		System.out.println("Person类的无参数构造方法");
	}
	
	public  Person(String value){
		System.out.println("Person类的有参数构造方法");
	}
}
package com.click369.test1;
/**
 * Student类就是子类
 * @author Administrator
 *
 */
public class Student extends Person{

	public Student(){
		System.out.println("Student子类的无参数构造方法");
	}
}
Student  stu1=new Student();

Java基础第五节

  1. 我们可以在子类的构造方法中用过super关键字,调用父类中的任意一个构造方法执行。

    package com.click369.test1;
    /**
     * 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);
    	}
    }
    
    package com.click369.test1;
    /**
     * Student类就是子类
     * @author Administrator
     *
     */
    public class Student extends Person{
    
    	public Student(){
    		//super(); //调用父类无参数构造方法
    		super("Student");
    		System.out.println("Student子类的无参数构造方法");
    	}
    }
    Student  stu1=new Student();
    

    总结:子类对象在创建的时候,总是会先调用父类的构造方法创建出父类对象,然后在执行子类的构造方法,创建出子类对象。可以使用super关键字让子类调用指定的父类的构造方法创建父类对象。

5.3Java中子类的继承性?

  1. 子类的继承性是指子类可以从父类中继承那些变量和方法
  2. 子类的继承性与访问限制修饰符有关。

Java基础第五节

5.4java中的访问限制修饰符

1.访问限制修饰符就是用来限定java元素【类,变量,方法,接口…】,在哪些情况下可以访问,哪些情况不能访问。【保护隐私】

访问限制修饰符分别有:

public【公共的】 private【私有的】 protected【受保护的】 缺省的【友好的】

  1. public【公共的】任何元素都可以访问 [类,变量,方法,接口]
  2. private【私有的】创建者自己可以访问,其他的元素不能访问 [变量,方法]
  3. protected【受保护的】与创建者有关系【继承】的可以访问,没有关系的其他元素不能访问[变量,方法]
  4. 缺省的【友好的】 什么都不写 同一个包中可以访问,不同包就不能访问[类,变量,方法,接口].

2.类上面可以使用public【公共的】和缺省的 访问修饰符。

  1. 被public修饰的类,可以在任何地方被访问。
  2. 被缺省的修饰符修饰的类,只能被同一个包中其他类访问,跨出包就不能访问。

Java基础第五节

5.5java中的包

  1. 为了方便管理java类。我们在开发应用程序的时候,会编写很多类,而类多了以后不利于管理,所以可以将功能相似的类统一放在一个程序包中,方便管理。
  2. 为了区分名称相同的类。通过隶属于不同的包,来区分名称相同的类。
  3. 包创建的语句所出现的位置,类的首行。
  4. 格式:package 包名;

包名的名称规则:

  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引入类所在的包

  • 类中创建包的语句与定义类的语句之间,通过import引入类所在的包的语句

  • Java.lang包系统会自动引入,我们就不需要手动通过import关键字引入,除过Java.lang包其他的包都是需要import关键字引入。

  • 通过情况下是import 包名+类名; 【只引入这个包中的这个类】

    ​ 例如:import com.click369.test1.TestClass1;

  • 通过情况下是import 包名.*; 【将指定包中的所有类全部引入】

例如:import com.click369.test1.*;

6.在Exlipse开发工具中通过【Ctrl+Shift+o】自动导包。

5.6成员变量的隐藏和方法重写

  1. 在同一个类中,局部变量的名称与成员变量的名称相同。可以通过this.成员变量名称,强制调用,被隐藏的成员变量值。
  2. 在子类中,自己定义的成员变量与继承自父类中的某一个成员变量名称相同。可以通过super.成员变量名称,强制调用,被隐藏的成员变量值。
package com.click369.test1;
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);
	}
}

5.7上转型对象的含义和特征?

1.定义

子类对象赋值给父类变量---上转型对象

2.例子

package com.click369.test3;
public  class TestClass {
	public  String  getInfo(){
		return "父类的实例方法";
	}
}

package com.click369.test3;
public class SonClass extends TestClass{
	public  String  info(){
		return "子类的实例方法";
	}
}

package com.click369.test3;
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());	
	}
}
  1. 方法参数为父类类型
package com.click369.test3;
public  class TestClass {
	public  String  getInfo(){
		return "父类的实例方法";
	}
}

package com.click369.test3;
public class SonClass extends TestClass{
	public  String  info(){
		return "子类的实例方法";
	}
}

package com.click369.test3;
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);
	}
}

特征:

上转型对象不能操作子类新增的成员变量;不能使用子类新增的方法。上转型对象可以操作子类继承或者隐藏的成员变量,也可以使用子类继承的或者重写的方法。上转型对象操作子类继承或重写的方法,其作用等价于子类对象去调用这些方法。因此,如果子类重写了父类的某个方法,则当对象的上转型对象调用这个方法时一定是调用了这个重写的方法

5.8 什么是抽象类?为什么使用抽象类?抽象类中的元素?抽象类的使用?

  1. 什么是抽象类?

    抽象类也是一个类class,使用abstract关键字修饰的类

  2. 格式:访问限制修饰符 abstract class 类名{}

public  abstract  class  TestClass{

}
  1. 为什么使用抽象类?
  • 具体详情请查看: https://www.cnblogs.com/heyonggang/p/3142338.html

  • 提供可由子类实现的公共形式,子类根据自身的特点,按照自己的意图重写构造这个公共形式。

    4.抽象类中的元素

    1、抽象类也是一个类,它可以有实例变量,类变量,构造方法,实例方法,类方法,【抽象方法】

    2、抽象方法–用abstract关键字修饰,没有方法体,能出现在抽象类中。抽象是不能用final修饰的。

package com.click369.test1;
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();
}

抽象类的特点:

  1. 抽象类不能new,可以通过上转型对象构造出抽象类的对象。
  2. 当一个普通的java类继承一个抽象类以后,要重写抽象类中的抽象方法,否则将这个普通的java类该成抽象类
  3. 抽象类可以继承抽象类。
  4. 抽象类中可以有抽象方法,也可以一个抽象方法都没有。
  5. 抽象类对象调用抽象方法,实际上实在调用被子类重写以后的方法。
package com.click369.test1;
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();	
}

package com.click369.test1;
public class SonClass extends TestClass{
	public void test11() {
		
	}
}
/*
public  abstract  class SonClass extends TestClass{

}
*/
package com.click369.test1;

public class TestMain {

	public static void main(String[] args) {
		//1.抽象类不能创建对象。
		//TestClass  t1=new TestClass();
		//2.通过上转型对象构造出抽象类的对象
		TestClass  t2=new SonClass();
	}
}

抽象类的意义:

提供可由子类实现的公共形式,子类根据自身的特点,按照自己的意图重写构造这个公共形式。

优点:可以结构化我们的程序,达到代码重用的效果。

5.9 什么是接口?为什么使用接口?接口中的元素?接口的使用?

1. 接口

  • 接口本质与抽象类相似,都是提供可由子类实现的一般形式[公共形式],实现接口的子类可以根据自身的特点来扩展一般形式[公共形式]。

  • 既然接口与抽象类可以实现相同的目的,那么我们已经学习过了抽象类,为什么还要有接口?

  • 因为在java中所有的继承关系都是单继承关系。也就是说一个类只能有一个父类,不能一个类同时继承多个类。为了克服这种单继承关系,所以才用接口。那么也就是说接口是可以被同一个类去实现多个。

  • 接口本质与抽象类的意义相似:

  • 提供去由子类实现的公共形式,子类通过继承/实现抽象类/接口,根据自身的特点重新构造这个公共形式。

为什么有了抽象类还要学习接口?

  • 类与类的继承关系是单继承关系,一个类无法继承多个类,接口的存在就是为了克服类的单继承问题而产生的。因此上一个类是可以实现多个接口的。

接口的使用

​ 通过让类使用implments关键字去实现这个接口,或者多个接口。如果有多个接口中间使用“,”分割。

public   interface   MyInter{
}
public   interface   TestInter{
}
public   class   TestClass   implments   MyInter{ //实现一个接口
}
public   class   TestClass   implments   MyInter,TestInter{//实现多个接口
}

接口中的元素

  1. 接口中所有的变量都是public static final修饰的类变量,可以省略public static final修饰符
  2. 接口中可以有类方法【jdk8.0开始接口被增强可以有静态方法、接口默认方法】
  3. 接口中可以有抽象方法,所有的抽象方法都是public abstract,可以省略public abstract
  4. 接口中的所有的元素都是public修饰符修饰的,除过接口默认方法。
package com.click369.test3;

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关键字实现一个或多个接口。需要重写接口中的抽象方法,否则将这个普通的类变成抽象类。
package com.click369.test1;
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();
}

接口回调对象

  • 接口是不能new,通过实现了这个接口的子类去创建接口对象。
  • 接口回调对象与上转型对象相似
  • 上转型对象:子类的对象赋值给父类的变量
  • 接口回调对象:将实现该接口的子类对象赋值给该接口变量。

5.9抽象类与接口的区别?

  1. 抽象类要被子类继承,接口要被类实现。
  2. 接口只能做方法声明,抽象类中可以作方法声明,也可以做方法实现。
  3. 接口里定义的变量只能是公共的静态的常量,抽象类中的变量是普通变量。
  4. 接口是设计的结果,抽象类是重构的结果。
  5. 抽象类和接口都是用来抽象具体对象的,但是接口的抽象级别最高。
  6. 抽象类可以有具体的方法和属性,接口只能有抽象方法和不可变常量。
  7. 抽象类主要用来抽象类别,接口主要用来抽象功能。

5.10接口回调对象的含义和特征?

  1. 接口回调对象和实现该接口的子类对象还有接口名称,可以调用接口中的类变量
  2. 接口回调对象和实现该接口的子类对象,都不能调用接口的类方法,只能接口名称去调用接口中的类方法
  3. 接口回调对象和实现该接口的子类对象,可以调用接口中的抽象方法,只不过调用的是被子类重写以后的抽象方法
  4. 接口回调对象是不能调用子类自己定义的变量和方法,子类对象可以调用子类自己定义的变量和方法。

5.11 static \ this \ super \ final关键字?

this关键字

this表示的是当前对象本身,更准确地说,this代表当前对象的一个引用,可以调用该类的属性,方法,构造器。

当在方法内需要用到调用该方法的对象时就可以使用this。

使用this调用成员变量
当形参与成员变量重名时,如果在方法内部需要使用成员变量,必须添加this来表明该变量时类成员
public Persion(String name, int age) {
	this.name = name;
	this.age = age;
}

使用this调用方法。

调用当前对象的其他方法(可以省略)
位置:任意

public void getInfo(){	
	System.out.println("姓名:" + name) ;
	this.speak();
}
public void speak(){
	System.out.println(“年龄:” + this.age);	
}

构造方法中使用this来调用其它构造方法。

位置:必须是第一条语句

public Persion(String name, int age) {
	this.name = name;
	this.age = age;
}
public Persion(String name, int age,double salary) {
	this(name,age);
	this.salary = salary;
}

super关键字

super代表父类的内存空间的标识,这个父类不仅仅指的是子类的直接父类。

使用场景:

  • super可用于访问父类中定义的属性
  • super可用于调用父类中定义的成员方法
  • super可用于在子类构造方法中调用父类的构造器,必须在构造器中的第一句,且不能同时出现this调用本类中其他的构造方法
  • 当子父类出现同名成员时,可以用super进行区分

this和super的区别

区别点 this supper
1 访问属性 访问本类中的属性,如果本类没有此属性则从父类中继续查找 访问父类中的属性
2 调用方法 访问本类中的方法 直接访问父类中的方法
3 调用构造器 调用本类构造器,必须放在构造器的首行 调用父类构造器,必须放在子类构造器的首行
4 特殊 表示当前对象 无此概念

static关键字

static修饰成员变量

  • static修饰的成员变量为静态成员变量 ,或者叫做: 类属性,类变量.注意:static不能修饰局部变量。
  • 它为该类的公用变量,属于类,对于该类的所有对象来说,static成员变量只有一份,被该类的所有对象共享,如果一个对象修改了类变量都将影响其他对象对这个类变量的调用
  • 可以使用”对象.类属性”来调用。不过,一般都是用“类名.类属性”
  • static变量存放在静态域中

static修饰方法

  • static修饰的方法叫静态方法
  • 不需要对象,就可以调用(类名.方法名)
  • 静态方法不能以任何方式引用this和super关键字,因为this,super都是对象的引用,它在内存中是在静态方法加载后出现的,所以无法访问
  • 静态方法中不可以访问非静态变量,非静态方法,只能访问静态变量和静态方法
  • 理解:加载类的时候就加载静态变量和静态方法,此时可能还没有创建对象,所以非静态变量和非静态的方法还没有分配空间,无法访问非静态方法中可以访问静态方法或者静态变量
  • 理解:加载类的时候就已经加载静态变量和静态方法,创建对象后,非静态变量和非静态的方法才分配空间,此时静态变量和静态方法已经存在,可以访问
  • 重载的方法需要同时为static的或者非static的

static修饰代码块

  • 如果希望加载后,对整个类进行某些初始化操作,可以使用static静态代码块。
  • 类第一次被载入时先执行static代码块;类多次载入时,static代码块只执行一次;Static经常用来进行static变量的初始化。
  • 是在类初始化时执行,不是在创建对象时执行
  • 静态初始化块中不能访问非static成员。

static修饰内部类
使用场景:单例模式的实现

public class Singleton {
	private Singleton() {
 
	}
 
	private static class SingletonHolder {
		private final static Singleton instance = new Singleton();
	}
 
	public static Singleton getInstance() {
		return SingletonHolder.instance;
	}
	
	public static void main(String[] args) {
		Singleton s1 = Singleton.getInstance();
		Singleton s2 = Singleton.getInstance();
		System.out.println(s1 == s2);
	}
}

final关键字

1.final修饰变量,成为常量,值不能再变化

--final修饰基本数据类型,值只能赋值一次,后续不能再赋值
--final修饰引用数据类型,不能变化的引用变量的值,可以变化的是对象的属性

2.final修饰方法,不能被子类重写
3.final修饰类,不能再有子类,如String类、StringBuffer、System
4.final不能修饰构造方法

5.static final 修饰的变量是全局静态常量
化块中不能访问非static成员。

static修饰内部类
使用场景:单例模式的实现

public class Singleton {
	private Singleton() {
 
	}
 
	private static class SingletonHolder {
		private final static Singleton instance = new Singleton();
	}
 
	public static Singleton getInstance() {
		return SingletonHolder.instance;
	}
	
	public static void main(String[] args) {
		Singleton s1 = Singleton.getInstance();
		Singleton s2 = Singleton.getInstance();
		System.out.println(s1 == s2);
	}
}

final关键字

1.final修饰变量,成为常量,值不能再变化

--final修饰基本数据类型,值只能赋值一次,后续不能再赋值
--final修饰引用数据类型,不能变化的引用变量的值,可以变化的是对象的属性

2.final修饰方法,不能被子类重写
3.final修饰类,不能再有子类,如String类、StringBuffer、System
4.final不能修饰构造方法
5.static final 修饰的变量是全局静态常量

相关标签: 笔记