Java当中类和对象的详解

1 面向对象

Java语言是一种面向对象的程序设计语言,而面向对象思想是一种程序设计思想,我们在面向对象思想的指引下, 使用Java语言去设计、开发计算机程序。 这里的对象泛指现实中一切事物,每种事物都具备自己的属性和行为。面 向对象思想就是在计算机程序设计过程中,参照现实中事物,将事物的属性特征、行为特征抽象出来,描述成计算 机事件的设计思想。 它区别于面向过程思想,强调的是通过调用对象的行为来实现功能,而不是自己一步一步的去 操作实现。

举例

洗衣服:

面向过程:把衣服脱下来—>找一个盆—>放点洗衣粉—>加点水—>浸泡10分钟—>揉一揉—>清洗衣服—>拧干—>晾 起来

面向对象:把衣服脱下来—>打开全自动洗衣机—>扔衣服—>按钮—>晾起来

区别:面向过程:强调步骤。

面向对象:强调对象,

特点 : 这里的对象就是洗衣机。 特点面向对象思想是一种更符合我们思考习惯的思想,它可以将复杂的事情简单化,并将我们从执行者变成了指挥者。 面向对象的语言中,包含了三大基本特征,即封装、继承和多态

2 类

什么是类

  • : 是一组相关属性和行为的集合, 可以看成是一类事物的模板, 使用事物的属性特征和行为特征来描述该类事物

现实中, 描述一类事物

  • 属性 : 就是该事物的状态信息
  • 行为 : 就是该事物能够做什么

什么是对象

  • 对象 : 是一类事物的具体体现, 对象是类的一个实例, 必然具备该类事物的属性和行为

类与对象的关系

  • 类是对一类事物的描述, 是抽象的
  • 对象是一类事物的实例, 是具体的
  • 类都是对象的模板, 对象是类的实体

类的定义

类的定义格式 :

成员变量 : 对应事物的属性

成员方法 : 对应事物的行为

public class ClassName{
	// 成员变量
	// 成员方法
}

定义类 : 就是定义类的成员, 包括成员变量和成员方法

成员变量 : 和以前定义变量集合是一样的; 只不过位置发生了改变,在类中,在方法外

成员方法 :和以前定义方法几乎是一样的, 只不过把static去掉

public class Student {
    //成员变量
    String name;//姓名
    int age;//年龄
    
    /*成员方法*/
    //学习的方法
    public void study() {
    System.out.println("好好学习,天天向上");
    }
    //吃饭的方法
    public void eat() {
    System.out.println("学习饿了要吃饭");
    }
}

类的创建及使用

通常情况下, 一个类并不能直接使用, 需要根据类创建一个对象, 才能使用

/*
1.导包
import 包名称.类名称
对于和当前类同属于一个包的情况, 可以省略包语句不写

2.创建,格式
类名称 对象名 = new 类名称()
Student stu = new Student()

3.使用
使用成员变量 : 对象名.成员变量名
使用成员方法 : 对象名.成员方法名(参数)

*/

成员变量如果没有赋值, 将会拥有一个默认值

3 对象

一个对象的内存图

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-aSyhKq2X-1589014687148)(assets/1588925567220.png)] 两个对象使用同一个方法的内存图

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-VX1G8Bok-1589014687150)(assets/1588925972674.png)]

两个引用指向同一个对象的内存图
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-pV02KHlg-1589014687152)(assets/1588926293692.png)]

两个对象名称 指向了 同一个对象

使用对象作为方法的参数

当一个对象作为参数时, 传递到方法当中时, 实际上传递进去的是对象的地址值

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ZKjWl5KY-1589014687156)(assets/1588927036193.png)]

使用对象作为方法的返回值

当使用一个对象类型作为方法的返回值时, 返回值其实就是对象的地址值

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-1f1M6t8S-1589014687158)(assets/1588927806593.png)]

成员变量和局部变量的区别

局部变量成员变量
定义的位置不一样在方法的内部在方法的外部,直接写在类当中
作用范围不一样只有在方法当中使用, 出了方法就不能使用整个类全都可以通用
默认值不一样没有默认值, 如果要想使用,必须手动进行赋值如果没有赋值, 会有默认值; 规则与数组一样
在内存当中的位置不同栈内存堆内存
生命周期不同随着方法的调用而存在,随着方法的调用完毕而消失随着对象的创建而存在,随着对象的消失而消失

4 封装

定义 : 就是将一些细节信息隐藏起来, 对于外界不可见; 若需要访问某个属性, 提供公共方法对其访问; 适当的封装可以让代码更容易理解与维护, 也加强了代码的安全性

  1. 方法就是一种封装
  2. 关键字 private 也是一种封装

private 关键字将需要保护的成员变量和成员方法进行修饰; 在本类当中仍然可以随意访问; 超出了本类范围之外就不能再直接访问

private 数据类型 变量名 // private 返回值类型 方法名

public class Student{
    private String name;
    private int age;
}

对需要访问的成员变量, 提供对应的一对 getXxx, setXxx方法进行访问, 并且可以在set方法内部对属性进行校验

public class Student{
	// 成员变量
    private String name;
    private int age;
    private boolean male // 是不是爷们儿
    
    // 对应每个属性的setXxx, getXxx方法
    public void setName(String n){
        name = n;
    }
    public String getName(){
        return name;
    }
    
    public void setAge(int a){
        age = a;
    }
    public int getAge(){
        return age;
    }
    
    public void setMale(boolean b){
        male = b;
    }
    public boolean isMale(){
        return male
    }
}

基本类型当中的 boolean值, 其的get方法 ,要写成 isXxx的形式

5 this

this代表所在类的当前对象的引用(地址值), 即对象自己的引用

通过谁调用的方法, this指代的 就是谁

当类的成员变量与方法的局部变量重名的时候, 会造成误解; 只能优先使用局部变量; 而this关键字后面的 . 一定是类的成员变量

6 构造方法

构造方法是专门用来创建对象的方法, 当我们通过关键字new来创建对象时, 其实就是在调用构造方法

构造方法没有返回值, 所以不需要返回值类型, 甚至不需要void

注意事项 :

  1. 构造方法的名称必须和所在的 类名称 完全一样, 就连大小写也要一样
// 格式
public 类名称(参数类型 参数名称){
    方法体
}


public class Student{

	private String name;
	private int age;
	
	// 无参数构造方法
	public Student() {}
	
	// 有参数构造方法
	public Student(String name,int age){
        this.name = name;
        this.age = age;
	}
    
}
  • 如果你不提供构造方法, 系统会给出无参数构造方法
  • 如果你提供构造方法, 系统将不再提供无参数构造方法
  • 构造方法也是可以重载的, 既可以定义参数, 也可以不定义参数

定义一个标准的类

一个标准的类通常要拥有下面四个组成部分

  1. 所有的成员变量都要使用private关键字修饰
  2. 为每一个成员变量编写一对儿 Getter/Setter 方法
  3. 编写一个无参数的构造方法
  4. 编写一个全参数的构造方法

这样标准的类也叫做 Java Bean; 快捷键自动生成Getter/Setter方法

Alt+Insert 或者 code -->Generate --> Constructor构造器 // Getter/Setter

7 匿名对象

定义 : 只有右边的对象, 没有左边的名字和赋值运算符

格式 : new 类名称();

注意事项 : 匿名对象只能使用唯一的一次, 下次再用不得不创建一个新对象

用途 : 有些情况下, 有的对象只能使用一次; 推荐使用匿名对象

8 Scanner类

定义 : 一个可以解析基本类型和字符串的简单文本扫描器

Scanner sc = new Scanner(System.in);
int i = sc.nextInt();

备注 : System.in 系统输入指的是通过键盘录入数据

使用import关键字导包, 在类的所有代码之前导包, 引入要使用的类型, java.lang包下的所有类无序导入 import 包名.类名;

import java.util.Scanner;

/*
Scanner : 实现键盘输入数据到程序当中
 */
public class Demo01Scanner {
	public static void main(String[] args) {
		Scanner sc = new Scanner(System.in);

		// 获取键盘输入的int数字
		int num = sc.nextInt();
		System.out.println("输入的int数字是: "+ num);

		// 获取键盘输入的字符串
		String str = sc.next();
		System.out.println("输入的字符串是: "+ str);
	}
}

详细Scanner类的操作 : 参考文档

9 Random类

用途 : 用来生产随机的数字

Random r = new Random();
int num = r.nextInt()	// nextInt()无参数, 范围是int的范围
int num = r.nextInt(3)  // 左闭右开 [)

练习 : 随机生成一个1-100之间的int数字, 键盘输入猜在多少次之内猜到

/*
用来生成随机数
*/
public class Demo01Random {

	public static void main(String[] args) {
		Random r = new Random();
		int randomNum = r.nextInt(100)+1; // 生成[1,100]之间的数字
		Scanner sc = new Scanner(System.in);

		int number = 0;

		while (true){
			System.out.println("请输入你猜测的数字: ");
			int guessNum = sc.nextInt(); // 键盘猜测输入的数字


			if(guessNum>randomNum){
				System.out.println("太大了, 请重试");
				number += 1;
                
			}else if(guessNum<randomNum){
				System.out.println("太小了,请重试: ");
				number += 1;
			} else {
				System.out.println("恭喜你,猜中啦");
				break; // 不猜了
			}
		}
		System.out.println("游戏结束, 猜了" + number + "次");
	}
}

10 ArrayList类

java.util.ArrayList是大小可变的数组的实现, 存储在内的数据成为元素, 此类提供一些方法来操作内部存储的元素, ArrayList中可不断添加元素, 其大小也自动增长

对于ArrayList来说, 有一个尖括号<E>代表泛型

泛型 : 也就是装在集合当中的所有元素, 全都是统一的什么类型

注意 : 泛型只能是引用类型, 不能是基本类型

// 创建格式 
ArrayList<String> list = new ArrayList<>();

注意事项 : 对于ArrayList来说, 直接打印得到的不是地址值, 而是内容; 如果内容为空, 得到的是 []

ArrayList的常用方法

  • public boolean add(E e) :将指定的元素添加到此集合的尾部
  • public E remove(int index) :移除此集合中指定位置上的元素。返回被删除的元素
  • public E get(int index) :返回此集合中指定位置上的元素。返回获取的元素
  • public int size() :返回此集合中的元素数。遍历集合时,可以控制索引范围,防止越界
for(int i=0, i<list.size(),i++){
    System.out.println(list.get(i))
}

ArrayList集合存储基本数据类型

如果希望向集合ArrayList当中存储基本你数据类型, 必须使用基本数据类型对应的 “包装类”

基本类型 与 包装类有对应的关系, 除了int --> Integer, char --> Character特殊; 包装类都不用导入

练习 : 生成6个1-33之间的随机整数, 添加到集合,并遍历集合

/*
1. 需要存储6个数字, 创建一个集合, <Integer>
2.产生随机数, 需要用到Random
3.用循环6次,来产生6个随机数字, for循环
4.循环内调用r.nextInt(33)+1,
5.把数字添加到集合中 :add
6.遍历集合 : for,size,get
*/


public Class ArrayList{
    public static void main(String[] args){
        ArrayList<Integer> list = new ArrayList<>();
        Random random = new Random()
        
        for(int i=0,i<=6,i++){
            int num = random.nextInt(33)+1;
            list.add(num);
        }
        
        // 遍历集合
        for(int i=0,i<=list.size(),i++){
            System.out.println(list.get(i))
        }
    }
}

练习2 : 存储自定义对象, 添加到结合,并遍历

public class TestArrayList{
    public static void main(String[] args){
        // 创建集合对象
        ArrayList<Student> list = new ArrayList<Student>();
        
        // 创建学生对象
        Student s1 = new Student("赵丽颖",15);
        Student s2 = new Student("唐嫣",19);
        Student s3 = new Student("景甜",20);
        Student s4 = new Student("柳岩",25);
        
        // 把学生对象作为元素添加到集合中
        list.add(s1);
        list.add(s2);
        list.add(s3);
        list.add(s4);
        
        // 遍历集合
        for(int i=0;i<list.size();i++ ){
        Student s = list.get(i);
        System.out.println(s.getName()+"====="s.getAge());
        }
    }
}

11 字符串

java.lang.String 类代表字符串。Java程序中所有的字符串文字(例如 “abc” )都可以被看作是实现此类的实例。

字符串不变 : 字符串的值在创建后不能被更改

字符串常量池 : 程序当中直接写上的双引号字符串, 就在字符串常量池中

对于基本类型来说, == 是进行数值的比较

对于引用类型来说, == 是进行地址值的比较

ring s1 = "abc";
s1 += "d";
System.out.println(s1); 
// "abcd
// 内存中有"abc","abcd"两个对象,s1从指向"abc",改变指向,指向了"abcd"

String对象是不可变的, 所以他们可以被共享

String s1 = "abc";
String s2 = "abc";
// 内存中只有一个"abc"对象被创建,同时被s1和s2共享。

“abc” 等效于 char[] data={ ‘a’ , ‘b’ , ‘c’ } 。

例如:
String str = "abc";
相当于:
char data[] = {'a', 'b', 'c'};
String str = new String(data)
// String底层是靠字符数组实现的。

// 无参构造
String str = new String()
// 通过字符数组构造
char chars[] = {'a', 'b', 'c'};
String str2 = new String(chars)
// 通过字节数组构造
byte bytes[] = { 97, 98, 99 };
 String str3 = new String(bytes);

比较

public boolean equals (Object anObject) :将此字符串与指定对象进行比较。(比较数据值)

public boolean equalsIgnoreCase (String anotherString) :将此字符串与指定对象进行比较,忽略大小写。

获取与截取

public int length () :返回此字符串的长度。

public String concat (String str) :将指定的字符串连接到该字符串的末尾。

public char charAt (int index) :返回指定索引处的单个字符

public int indexOf (String str) :返回指定子字符串第一次出现在该字符串内的索引。若不存在,则返回-1值

public String substring (int beginIndex) :返回一个子字符串,从beginIndex开始截取字符串到字符串结尾。

public String substring (int beginIndex, int endIndex) :返回一个子字符串,从beginIndex到endIndex截取字符串。含beginIndex,不含endIndex。

public class Demo02StringGet {

	public static void main(String[] args) {
		// 获取字符串的长度
		int i = "nsfksbkfnafa".length();
		System.out.println("字符串的长度为 : "+ i);

		// 拼接字符串
		String str1 = "Hello";
		String str2 = "World";
		String str3 = str1.concat(str2);
		System.out.println("新的字符串为 : "+ str3);

		// 获取指定位置的字符
		System.out.println("指定位置的字符为: "+ str1.charAt(1));

		// 获取参数字符串在字符串当中首次出现的位置
		System.out.println("位置是 : "+ str1.indexOf("l"));
        
        // 获取起始位置指定索引的子字符串
		System.out.println("位置是 : "+ str1.substring(2));  // llo

		// 获取起始位置和结束位置的指定索引的子字符串
		System.out.println("位置是 : "+ str1.substring(2,3));  // l [)

	}
}

转换

public char[] toCharArray () :将此字符串转换为新的字符数组。

public byte[] getBytes () :使用平台的默认字符集将该 String编码转换为新的字节数组。

public String replace (CharSequence target, CharSequence replacement) :将与target匹配的字符串使用replacement字符串替换。

/*
public char[] tocharArray() : 将当前字符串拆分成字符数组作为返回值
public byte[] getBytes() : 获取当前字符串底层的字节数据
public String replace(旧字符串,新字符串) :在原有字符串当中,使用新的字符串替换旧的字符串
 */

public class Demo02StringConvert {
	public static void main(String[] args) {
		char[] chars = "Hello".toCharArray();

		// 转换为字符数组
		for (int i = 0; i < chars.length; i++) {
			System.out.println("每个字符分别为"+chars[i]);
		}

		// 转换为字节数组
		byte[] bytes = "abc".getBytes();
		for (int i = 0; i < bytes.length; i++) {
			System.out.println(bytes[i]);
		}

		// 替换旧的字符串当中的内容
		String str = "it cast it Hello";
		String newString = str.replace("it","IT");
		System.out.println("新的字符串为: "+newString);

	}
}

分割

public String[] split(String regex) :将此字符串按照给定的regex(规则)拆分为字符串数组。

注意事项 : split()的参数其实是一个正则表达式; 写两个 \ \ 代表转义

public class String_Demo03 {
    public static void main(String[] args) {
        //创建字符串对象
        String s = "aa|bb|cc";
        String[] strArray = s.split("|"); 
        // ["aa","bb","cc"]
        for(int x = 0; x < strArray.length; x++) {
            System.out.println(strArray[x]); // aa bb cc
        }
    }
}

12 static

起因 : 对于某些成员变量来说, 是类的每个具体对象的共享变量, 那么这样的成员变量变不再属于对象自己,而属于类 , 用 static 修饰, 变成 类变量

定义 : 它可以用来修饰成员变量和成员方法,被修饰的成员是属于类的,而不是单单是属于某个对象的。也就是说,既然属于类,就可以不靠创建对象来调用了。

对于本类当中的静态方法, 可以省略类名称不写

静态是不能直接访问非静态; 因为在内存当中先有的静态内容, 后有的非静态内容; 即先编译静态变量和方法, 后编译非静态变量和方法

// 定义
static 数据类型 变量名;
static int age;

// 访问类变量(静态变量)
类名.静态变量名

// 调用静态方法
类名.静态方法名(参数)

static修饰类成员变量

public class Student {

	private int id;
	private String name;
	private int age;
	static String room;

	private static int idCounter;

	public int getId() {
		return id;
	}

	public void setId(int id) {
		this.id = id;
	}

	public static void main(String[] args) {
		// main()
	}

	public Student(String name, int age) {
		this.name = name;
		this.age = age;
		this.id = idCounter++;
	}

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}

	public int getAge() {
		return age;
	}

	public void setAge(int age) {
		this.age = age;
	}
}


package cn.itcast.day08;


/*
如果一个成员变量, 使用了static来修饰, 则这个成员变量不属于对象自己, 供类的所有对象享用
 */
public class Demo03StaticField {

	public static void main(String[] args) {
		Student one = new Student("黄蓉",19);
		Student two = new Student("郭靖",22);

		one.room = "101教室";
		System.out.println("姓名 : "+one.getName()+",年龄: "+one.getAge()+"教室: "+one.room+",学号 :"+one.getId());
		System.out.println("姓名 : "+two.getName()+",年龄: "+two.getAge()+"教室: "+two.room+",学号 :"+two.getId());

	}

}


static修饰类成员方法

被static修饰的成员方法, 可以直接被 类调用

static的内存图

根据类名称访问的静态成员变量的时候,全程和对象没得关系, 只和 类 有关系

根据类名称访问的静态成员的方法, 会在方法区当中单独开辟一块内存空间存储叫做静态区

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-V6SSUp4t-1589014687160)(assets/1588996242827.png)]

静态代码块

写在类当中, 用 static {} 表示; 当第一次用到本类时, 静态代码块执行唯一的一次

静态内容总是优先于非静态, 所以静态代码块比构造方法先执行

用途 : 用来一次性地对静态成员变量进行赋值

13 Arrays类

java.util.Arrays 此类包含用来操作数组的各种方法,比如排序和搜索等。其所有方法均为静态方法,调用起来非常简单。

public static String toString(int[] a) :返回参数数组的内容以字符串表示形式。

public static void main(String[] args) {
    // 定义int 数组
    int[] arr = {2,34,35,4,657,8,69,9};
    // 打印数组,输出地址值
    System.out.println(arr); // [I@2ac1fdc4// 
    // 数组内容转为字符串
    String s = Arrays.toString(arr);
    // 打印字符串,输出内容
    System.out.println(s); // [2, 34, 35, 4, 657, 8, 69, 9]}
}

public static void sort(int[] a) :对指定的 int 型数组按数字升序(默认)进行排序。

public static void main(String[] args) {
    // 定义int 数组
    int[] arr = {24, 7, 5, 48, 4, 46, 35, 11, 6, 2};
    System.out.println("排序前:"+ Arrays.toString(arr)); // 排序前:[24, 7, 5, 48, 4, 46, 35, 11, 6,2]
    // 升序排序
    Arrays.sort(arr);
    System.out.println("排序后:"+ Arrays.toString(arr));// 排序后:[2, 4, 5, 6, 7, 11, 24, 35, 46,48]}
}

14 Math类

java.lang.Math 类包含用于执行基本数学运算的方法,如初等指数、对数、平方根和三角函数。类似这样的工具类,其所有方法均为静态方法,并且不会创建对象,调用起来非常简单。

public static double abs (double a) : 返回double 值的绝对值

double d1 = Math.abs(5); //d1的值为5
double d2 = Math.abs(5); //d2的值为5

public static double ceil(double a) : 返回大于等于参数的最小整数(向上取)

double d1 = Math.ceil(3.3); //d1的值为 4.0
double d2 = Math.ceil(3.3); //d2的值为 ‐3.0
double d3 = Math.ceil(5.1); //d3的值为 6.0

public static double floor(double a) : 返回小于等于参数的最大整数(向下取)

double d1 = Math.floor(3.3); //d1的值为3.0
double d2 = Math.floor(3.3); //d2的值为‐4.0
double d3 = Math.floor(5.1); //d3的值为 5.0

public static long round(double a) : 返回最接近参数的long(相当于四舍五入)

long d1 = Math.round(5.5); //d1的值为6.0
long d2 = Math.round(5.4); //d2的值为5.0

15 继承

Java语言是单继承的, 一个类的直接父类只能有唯一的一个

继承是多态的前提, 如果没得继承, 就没有多态

继承的主要解决问题就是 : 共性抽取

通过 extends 关键字, 可以声明一个子类继承另外一个父类, 定义格式如下

class 父类 {..}
clas 子类 extends 父类 {...}

继承中访问成员变量的特点

在父子类的继承关系中, 成员变量的查找顺序 : 先在子类对象当中寻找, 找到则停止, 找不到在父类当中查找, 再往上找不到则报错

继承中访问成员方法的特点

在父子类的继承关系中, 成员方法的查找顺序 : 通过谁创建的对象, 就在谁当中去查找, 一直向上找到为止;不会向下去找子类的成员方法

继承中访问构造方法的特点

  1. 子类构造方法当中有一个默认隐含的"super()"调用
  2. 可以通过super关键字来子类构造调用父类重载构造; 必须是子类构造方法的第一个语句, 不能一个子类构造调用多次super构造

方法的复写

在继承关系当中, 方法的名称一样, 参数列表也一样, 只是内部的具体实现不同

重写时, 针对父类已经实现的方法, 必须先 super.父类方法(), 再重写

注意事项 :

  1. 可在复写的方法上面用 @override 表明示方法的复写
  2. 子类方法的返回值必须小于等于父类方法的返回值范围
  3. 子类方法的权限必须大于等于父类方法的权限修饰符

拓展提示 : public > protected > (default 留空) > private

16 super/this

super关键字的三种用法

  1. 在子类的成员方法中, 访问父类的成员变量
  2. 在子类的成员方法中, 访问父类的成员方法
  3. 咋子类的构造方法中, 访问父类的构造方法
this.成员变量 ‐‐ 本类的
super.成员变量 ‐‐ 父类的
this.成员方法名() ‐‐ 本类的
super.成员方法名() ‐‐ 父类的

this关键字的三种方法

  1. 在本类的成员方法中, 访问本类的成员变量
  2. 在本类的成员方法中, 访问本类的另一个成员方法
  3. 在本类的构造方法中, 访问本类的另一个构造方法
  4. super和this两种构造调头, 不能同时使用

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-fiSG8445-1589014687161)(assets/1589008206002.png)]

17 抽象类

比如定义一个Animal, 里面有成员方法 eat() ,但是具体的吃什么我吗不知道, 浴室里面不能写内容; 这样的方法就是抽象方法, 抽象类与抽象方法都是用关键字 abstract 修饰

定义 : 父类中的方法,被它的子类们重写,子类各自的实现都不尽相同。那么父类的方法声明和方法主体,只有声明没有意义,而方法主体则没有存在的意义了。我们把没有方法主体的方法称为抽象方法。Java语法规定,包含抽象方法的类就是抽象类。

抽象方法 :没有方法体即没有了 {} 的方法;

抽象类 : 包含抽象方法的类

public abstract class 类名 {
    代码块;
    public abstract void run();
}


抽象的使用

继承抽象类的子类必须重写父类所有的抽象方法。否则,该子类也必须声明为抽象类。最终,必须有子类实现该父类的抽象方法,否则,从最初的父类到最终的子类都不能创建对象,失去意义。

  1. 抽象类不能new 创建对象, 如果创建, 编译无法通过而报错, 只能创建其非抽象子类的对象;

假设创建了抽象类的对象, 调用抽象的方法, 而抽象方法没有方法体, 没有意义

  1. 抽象类中, 可以有构造方法, 是供子类创建对象时, 初始化父类成员使用的

子类的构造方法中, 有默认的super(), 需要访问父类的构造方法

  1. 抽象类中, 不一定包含抽象方法, 但是有抽象方法的类一定是抽象类

未包含抽象方法的抽象类, 目的就是不想让调用者创建该类对象, 通常用于某些特殊的类结构设计

  1. 抽象类的子类, 必须重写父类中所有的抽象方法, 否则, 编译无法通过而报错, 除非该类也是抽象类

访问本类的另一个构造方法
4. super和this两种构造调头, 不能同时使用

[外链图片转存中…(img-fiSG8445-1589014687161)]

17 抽象类

比如定义一个Animal, 里面有成员方法 eat() ,但是具体的吃什么我吗不知道, 浴室里面不能写内容; 这样的方法就是抽象方法, 抽象类与抽象方法都是用关键字 abstract 修饰

定义 : 父类中的方法,被它的子类们重写,子类各自的实现都不尽相同。那么父类的方法声明和方法主体,只有声明没有意义,而方法主体则没有存在的意义了。我们把没有方法主体的方法称为抽象方法。Java语法规定,包含抽象方法的类就是抽象类。

抽象方法 :没有方法体即没有了 {} 的方法;

抽象类 : 包含抽象方法的类

public abstract class 类名 {
    代码块;
    public abstract void run();
}


抽象的使用

继承抽象类的子类必须重写父类所有的抽象方法。否则,该子类也必须声明为抽象类。最终,必须有子类实现该父类的抽象方法,否则,从最初的父类到最终的子类都不能创建对象,失去意义。

  1. 抽象类不能new 创建对象, 如果创建, 编译无法通过而报错, 只能创建其非抽象子类的对象;

假设创建了抽象类的对象, 调用抽象的方法, 而抽象方法没有方法体, 没有意义

  1. 抽象类中, 可以有构造方法, 是供子类创建对象时, 初始化父类成员使用的

子类的构造方法中, 有默认的super(), 需要访问父类的构造方法

  1. 抽象类中, 不一定包含抽象方法, 但是有抽象方法的类一定是抽象类

未包含抽象方法的抽象类, 目的就是不想让调用者创建该类对象, 通常用于某些特殊的类结构设计

  1. 抽象类的子类, 必须重写父类中所有的抽象方法, 否则, 编译无法通过而报错, 除非该类也是抽象类

假设不写所有抽象方法, 则类中可能包含抽象方法, 那么创建对象后, 调用抽象的方法, 没有意义

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值