Java SE基础笔记

本文是Java SE的基础笔记,涵盖注释、标识符和关键字、变量、数据类型、运算符、控制语句、方法、面向对象编程等多个核心概念。详细阐述了每种类型的注释、标识符的命名规则和关键字、变量的声明、赋值和作用域、各种数据类型的使用,以及运算符的分类和用法。此外,还讲解了控制语句如if、switch、for、while等的使用,以及方法的声明、调用和重载。最后介绍了面向对象编程的基础,包括类、对象、构造方法、封装、this关键字和static修饰符的应用。
摘要由CSDN通过智能技术生成

文章目录

一、注释

1.1注释的三种方式

  • 注释是对代码的解释和说明,目的是让程序员更快的理解代码
  • 注释中的字符将被 Java 编译器忽略,不会生成到class字节码文件中,只在Java源文件中保留

1.2 书写注释的三种方式

1.单行注释,格式如下:

//这是单行注释

2.多行注释,格式如下:

/*
*这是第一行多行注释
*这是第二行注释
*/

3.javadoc注释,格式如下:

/**
*这里的信息是javadoc注释
*@author 作者名字
*@version 版本号
*@since 从哪个版本开始存在的
*javadoc的注释会被JDK解析并生成帮助文档
*/

二、标识符和关键字

2.1 标识符

标识符是指程序员自己规定的代表一定含义的单词。例如:类名、接口名、变量名、方法名、常量名等。

2.1.1 标识符命名规则

命名规则是必须遵守的,否则会报错。

标识符命名规则如下:

  • 标识符只能由数字、字母、下划线(_)、美元符号($)组成
  • 标识符不能以数字开始
  • 标识符严格区分大小写
  • Java关键字和保留字不能作为标识符
  • 标识符理论上没有长度限制

实例:

public class Student {//Student是类名
	int age;//age是变量名
	public void setAge(int a){//setAge是方法名,a是变量名
		age = a; 
	}
}

2.1.2 标识符命名规范

命名规范是一种书写代码的通用习惯,不遵守不会报错。

标识符命名规范如下:

  • 见名知意:增强可读性
  • 驼峰命名:利用首字母大小写分隔单词,每个单词之间会划清界限
  • 类名、接口名首字母大写,后面每个单词首字母大写,例如:HelloWorld
  • 变量名、方法名首字母小写,后面每个单词首字母大写,例如:getName
  • 常量名全部大写,单词和单词之间使用下划线连接,例如:MAX_NUMBER

2.2 关键字

Java关键字是编译语言事先定义的,有特殊意义的单词。
Java中所有关键字都是小写的。

常见关键字:

byteshortintlongfloat
doublebooleanchariffor
elsewhiledocontinuebreak
publicdefaultprotectedprivatethrow
throwstrycatchfinalfinally
caseswitchtransientpackagenew
staticthisabstractstrictfpnative
gotosuperextendsimplementsimport
instanceofreturnsynchronizedvoidconst
classenumassertinterfacevolatile

三、变量

3.1 字面量

字面量就是数据、数值。

在编程语言中数据被分为:

  • 整数型:1、2、-1
  • 浮点型:1.0、3.14
  • 字符型:‘a’、‘中’
  • 布尔型:true、false
  • 字符串型:“abc”、“中国”

3.2 变量

变量是内存中存储数据最基本的单元。
变量的三要素是数据类型、变量名、字面量。

3.2.1 变量的声明及赋值

  • 使用变量前必须先声明
  • 使用局部变量前必须先初始化
  • 同一个域中,变量不能重名

变量声明的语法格式:

数据类型 变量名;
变量名 =;

实例:

int i;
i = 1;

int count = 100;

int a = 200,b = 300,c = 400

int a,b,c = 20;//这种声明赋值方式是错的。但是在C++中是对的。

3.2.2 变量的分类

变量根据声明位置分为两大类:

  • 局部变量:在方法体中声明的变量以及方法中每一个参数都是局部变量
  • 成员变量:在方法体外,类体内声明的变量是成员变量
    • 静态(成员)变量:使用static关键词修饰的称为静态成员变量
    • 实例(成员)变量:没有static关键词修饰的称为实例成员变量

实例:

public class Test{
	int x = 20;//实例变量x
 	static int y = 200;//静态变量i
 	
 	public static void  sum(int a,int b){//局部变量a和b
		int i = 100;//局部变量i
	}
}

3.2.3 变量的作用域

变量的作用域指变量的使用范围。

不同类型的变量存储在java虚拟机上的不同内存区域,所以变量是有作用域的。
先简单理解为:出大括号就不认识。

示例:

{
	int i = 100;
	{
		这里可以访问i
	}
}
{
	这里无法访问i。
}

四、数据类型

根据数据类型决定在程序运行阶段给该变量分配多大的内存空间。
数据类型主要分为两大类:

  • 基本数据类型:
    • 整数型:byte、short、int、long
    • 浮点型:float、double
    • 字符型:char
    • 布尔型:boolean
  • 引用数据类型:除基本数据类型其他均为引用数据类型

基础数据类型的详细信息:

数据类型占字节数取值范围缺省默认值
byte1[-27~27-1]、[- 128~127]0
short2[-215~215-1]、[- 32768~32767]0
int4[-231~231-1]、[- 2147483648~2147483647]0
long8[-263~263-1]0L
float4[-231~231-1]0.0f
double8[-263~263-1]0.0
boolean1true、falsefalse
char2[-231~231-1]、[ 0~65535]‘\u0000’

关于计算机存储单位:
1bit就是一个1或0
1字节 = 8bit
1byte = 8bit
1KB = 1024byte
1MB = 1024KB
1GB = 1024MB
1TB = 1024GB

4.1 字符型数据类型

  • char类型的字面量用单引号括起来,只能存储一个字符
  • char类型采用unicode编码方式

实例:

public class Test {
    public static void main(String[] args) {
        char c1 = '中';
        System.out.println(c1);
        char c2 = 'a';
        System.out.println(c2);
        char c3 = '0';
        System.out.println(c3);
//        char c4 = "a"; String类型不能赋值给char类型
//        System.out.println(c4);
//        char c5 = 'ab'; char类型只能容纳一个字符
//        System.out.println(c5);
//        char c6 = 'a; 未结束的字符文字
//        System.out.println(c6);
    }
}

运行结果:

中
a
0

4.2 转义字符

  • 转义字符是一种特殊的字符常量
  • 转义字符以反斜线" \ "开头,后跟一个或几个字符

常用转义字符:

符号字符含义
\n换行
\r回车
\f换页符
\b退格
\0空字符
\s空格
\t制表符
\"双引号
\’单引号
\\反斜杠
\ddd八进制字符
\uxxx16进制Unicode字符

实例:

public class Test {
    public static void main(String[] args) {
        char c1 = 't';
        System.out.println(c1);
        char c2 = '\t';// \t是一个字符,表示“制表符tab”
        System.out.println(c2);
        System.out.println("abc\tdef");
        System.out.print("123\n456");//print()表示仅打印不换行
        System.out.println("\\");//输出一个"\"
        char c3 ='\u4e2d';//unicode编码表示"中"
        System.out.println(c3);
    }
}

运算结果:

t

abc	def
123
456\
中

4.3 整数型

整数型包括:byte、short、int、long。

  • 一般直接使用int即可
  • 在Java中,整数型的字面量默认被当作int类型处理
  • 如果希望整数型被当作long类型处理,需要在字面量后加“L / l”

4.4 浮点型数据类型

浮点型包括:float,double。

  • 在Java中,浮点型的字面量默认被当作double类型处理
  • 如果希望浮点型被当作float类型处理,需要在字面量后加“F / f”
  • 浮点型数据在计算机中存储的都是近似值
  • 在银行方面double精度也是远远不够的,一般使用java.math.BigDecimal,属于引用数据类型
  • long类型8个字节,float4个字节,但是float容量更大

4.5 布尔型数据类型

布尔型包括:boolean。

  • boolean只有两个值:true和false
  • 布尔类型不能和其它类型转换

4.6 字符串型数据类型

  • String类型的字面量用双引号括起来
  • String类型是引用数据类型,非基本数据类型

4.6 类型转换

小容量转大容量称为自动类型转换。[ byte < short(char) < int < long < float < double ]
大容量转小容量称为强制类型转换,必须加强制类型转换符,超范围会有精度损失。

  • byte、short、char做混合运算时,先各自转换为int再做运算
  • 多种类型做混合运算时,各自先转换成容量最大的再运算。char,short,byte运算除外,会先转成int。
  • 当整数型没有超出byte,short,char范围时,可以直接赋值
  • 浮点数类型强转时,只留下整数位。

byte、short、char做混合运算时,先各自转换为int再做运算

实例:

char c1 = 'a';
byte b = 1;
short s = c1 + b;//当有变量时,需要加强转才行:(c1 + b)为int类型
short k = 98;//当是具体数值时,可以自动转

多类型混合运算,各自转为容量最大的再运算

实例:

public class Test {
    public static void main(String[] args) {
      long a = 10L;
      char c = 'a';
      short s = 100;
      int i = 30;
      System.out.println(a+c+s+i);//237 多种类型做混合运算时,各自先转换成容量最大的再运算

      //int x = a+c+s+i;
      //System.out.println(x);
      //报错!java: 不兼容的类型: 从long转换到int可能会有损失
      //说明在运算时(a+c+s+i)自动转换为long类型了
       
       int x = c+s+i;
       System.out.println(x);
       //结果为:227未报错,因为char、short、byte运算时自动转为int
    }
}

实例:

int a = 100;没有类型转换
long b = 100;自动类型转换:int转为long
long c = 100L;没有类型转换
long d = 2147483648;会报错,int值超范围,此时必须加“L”变为long类型
long e = 2147483648L;
int f = (int)e;强制类型转换,超int范围会损失精度
byte g = 127;自动类型转换
   
    
计算机存储数据是以二进制补码形式存储的,正数的原码反码补码是一样的。
long类型100L00000000 00000000 00000000 00000000 00000000 00000000 00000000 01100100
强转为int类型:00000000 00000000 00000000 01100100
强转自动将前面4个字节砍掉
 
byte g =byte300;  g的值为44
int类型:00000000 00000000 00000001 00101100300
byte类型:0010110044

实例:

public class Test {
    public static void main(String[] args) {
        char c1 = 97;
        System.out.println(c1);
        char c2 = 'a' + 1;//acsll码97+1=98,98代表b
        System.out.println(c2);
        char c3 = '0' + '1';//ascll码48+49=97,97代表a
        System.out.println(c3);
    }
}

运行结果:

a
b
a

五、运算符

运算符是对操作数的运算方式。
按照操作数分类有单目运算符、双目运算符、三目运算符。

按照功能来分:

  • 算术运算符:+、-、*、/、%、++、 –
  • 关系运算符:>、>=、<、<=、==、!=
  • 逻辑运算符:&、|、!、&&、||
  • 赋值运算符:=、+=、-=、*=、/=、%=、^=、&=、|=、<<=、>>=
  • 位运算符:&、|、^、~、<<、>>、>>>
  • 条件运算符:布尔表达式?表达式 1:表达式 2
  • 字符连接运算符:+
  • 其他运算符:instance、new

5.1 算术运算符

算术运算符:

操作符描述例子(A=10,B=20)
+加法:相加运算符两侧的值A + B 等于 30
-减法:左操作数减去右操作数A – B 等于 -10
*乘法:相乘操作符两侧的值A * B 等于 200
/除法:左操作数除以右操作数B / A 等于 2
%取余:左操作数除以右操作数的余数B % A等于 0
++自增:操作数的值增加1B++ 或 ++B 等于 21
自减:操作数的值减少1B-- 或 --B 等于 19
  • 前缀表达式:先赋值,再自增减

  • 后缀表达式:先自增减,再赋值

实例:

//前缀表达式
int a = 1;
int b = a++;//先做b = a,再做a = a + 1
//b = 1,a = 2

//后缀表达式
int x = 1;
int y = ++x;//先做x = x + 1,再做y = x

//y = 2,x = 2

实例:

public class Test {
    public static void main(String[] args) {
        int a = 7;
        int b = 3;
        System.out.println(a + b);
        System.out.println(a - b);
        System.out.println(a * b);
        System.out.println(a / b);
        System.out.println(a % b);
        int x = 10;
        System.out.println(x++);//10 先赋值,再自加
        System.out.println(x);//11
        int y = 5;
        System.out.println(++y);//6 先自加,再赋值
        System.out.println(y);//6
    }
}

运算结果:

10
4
21
2
1
10
11
6
6

5.2 关系运算符

关系运算符:

运算符描述例子(A=10,B=20)
==两个操作数的值相等,则为真(A == B)为假
!=两个操作数的值不等,则为真(A != B) 为真
>左操作数的值大于右操作数的值,则为真(A > B)为假
<左操作数的值小于右操作数的值,则为真(A < B)为真
>=左操作数的值大于等于右操作数的值,则为真(A >= B)为假
<=左操作数的值小于等于右操作数的值,则为真(A <= B)为真
  • 关系运算符的运算结果都是布尔类型
  • 关系运算符中两个符号的中间不能有空格

实例:

public class Test {
    public static void main(String[] args) {
        int a = 10;
        int b = 5;
        System.out.println(a == b);
        System.out.println(a != b);
        System.out.println(a > b);
        System.out.println(a >= b);
        System.out.println(a < b );
        System.out.println(a <= b);
        
    }
}

运算结果:

false
true
true
true
false
false

5.3 逻辑运算符

逻辑运算符:

操作符描述例子
&逻辑与运算符:当且仅当两个操作数都为真,则为真(A & B)为假
|逻辑或操作符:任何两个操作数任何一个为真,则为真(A|B)为真
逻辑非运算符:用来反转操作数的逻辑状态!(A&&B)为真
&&短路与运算符:前操作数为false时,结果必false,就不再判断后操作数(A & B)为假
||短路或运算符:前操作数为true时,结果必true,就不再判断后操作数(A||B)为真
  • 逻辑运算符两边必须为布尔类型,并且结果也是布尔类型
  • 如果把两边操作数改为int类型,那么&、|会被认为是位运算符

实例:

public class Test {
    public static void main(String[] args) {
        boolean a = true;
        boolean b = false;
        System.out.println(a&b);
        System.out.println(a|b);
        System.out.println(!a);
        System.out.println(a&&b);
        System.out.println(a||b);
    }
}

运算结果:

false
true
false
false
true

5.4 赋值运算符

赋值运算符:

操作符描述例子
=赋值运算符C = A + B
+=加和赋值操作符C + = A
-=减和赋值操作符C - = A
*=乘和赋值操作符C * = A
/=除和赋值操作符C / = A
%=取模和赋值操作符C%= A
<<=左移位赋值运算符C << = 2
>>=右移位赋值运算符C >> = 2
&=按位与赋值运算符C&= 2
^=按位异或赋值操作符C ^ = 2
|=按位或赋值操作符C |= 2
  • 赋值运算符“=”:将右操作数的值赋给左侧操作数
  • 扩展赋值运算符书写时两个符号间不能有空格
  • 使用扩展赋值运算符时,不会改变运算结果数据类型

x = x +1和x += 1相似,但是本质不同,不能等价。

实例:

public class Test {
    public static void main(String[] args) {
        byte x = 100;
        //x = x + 1;报错!x + 1默认为int类型,转换为byte会有损失
        System.out.println(x);
        x += 1;//等价于x = (byte)(x+1)
        System.out.println(x);
    }
}
//上文的x += 1中的x生来就是byte类型。

5.5 位运算符

位运算符用来对二进制位进行操作。

位运算符:

操作符描述例子(A=0011 1100,B=0000 1101)
按位与运算符:如果相对应位都是1,则结果为1,否则为0(A&B),得到12,即0000 1100
|按位或运算符:如果相对应位都是 0,则结果为 0,否则为 1(A|B)得到61,即0011 1101
^按位异或运算符:如果相对应位值相同,则结果为0,否则为1(A ^ B)得到49,即 0011 0001
按位取反运算符:反转操作数的每一位(〜A)得到-61,即1100 0011
<<按位左移运算符:左操作数按位左移右操作数指定的位数A << 2得到240,即 1111 0000
>>按位右移运算符:左操作数按位右移右操作数指定的位数A >> 2得到15即1111
>>>按位右移补零操作符:左操作数的值按右操作数指定的位数右移,移动得到的空位以零填充A>>>2得到15即0000 1111

实例:

public class Test {
    public static void main(String[] args) {
        int a = 60;//60 = 0011 1100
        int b = 13;//13 = 0000 1101
        int c = 0;
        c = a & b;//12 = 0000 1100 
        System.out.println("a & b = " + c );
        
        c = a | b;//61 = 0011 1101 
        System.out.println("a | b = " + c );
        
        c = a ^ b;//49 = 0011 0001 
        System.out.println("a ^ b = " + c );
        
        c = ~a;//-61 = 1100 0011 
        System.out.println("~a = " + c );
        
        c = a << 2;//240 = 1111 0000 
        System.out.println("a << 2 = " + c );
        
        c = a >> 2;//15 = 1111 
        System.out.println("a >> 2  = " + c );
        
        c = a >>> 2;//15 = 0000 1111 
        System.out.println("a >>> 2 = " + c );
    }
}

运行结果:

a & b = 12
a | b = 61
a ^ b = 49
~a = -61
a << 2 = 240
a >> 2  = 15
a >>> 2 = 15

5.6 条件运算符

条件运算符:布尔表达式 ? 表达式1 : 表达式2

  • 如果为true,执行表达式1,否则执行表达式2

  • 条件运算符不是语句

sex?'男':'女';//是错误的,不是Java语句
char c = sex ? '男' : '女';//这样是对的,前面的类型要对应,但是实际开发不这么写
System.out.println(sex?'男':'女');//这样也是对的,在这里的括号里什么数据类型都能放

实例:

public class Test {
    public static void main(String[] args) {
        boolean sex = true;
        System.out.println(sex?'男':'女');
    }
}

运算结果:

5.7 字符串连接运算符

字符串连接运算符:+

  • 当+两边都是数字类型,做加法运算

  • 当+两边有一边为字符型,做拼接操作

  • 遵循自左向右的顺序执行。

实例:

public class Test {
    public static void main(String[] args) {
        System.out.println(100+200+"200");
        System.out.println(300+200);
        System.out.println(300+(100+"200"));
        System.out.println(100+"+"+200+"="+100+200);//遵循自左向右的顺序,除非有小括号
        System.out.println(100+"+"+200+"="+(100+200));
    }
}

运算结果:

300200
500
300100200
100+200=100200
100+200=300

5.8 接受键盘输入

public class Test {
    public static void main(String[] args) {
        //创建一个键盘扫描器
        java.util.Scanner s = new java.util.Scanner(System.in);
        //从键盘接收一个int类型的数据
        int a = s.nextInt();
        System.out.println(a);
        //从键盘接收一个字符串类型的数据
        String b = s.next();
        System.out.println(b);
    }
}

运行结果:

10
10
你好
你好

导包形式接收键盘数据

实例:

import java.util.Scanner;
public class Test {
    public static void main(String[] args) {
        //创建键盘扫描器对象
        Scanner s = new Scanner(System.in);
        //从键盘接收一个int类型的数据
        int a = s.nextInt();
        System.out.println(a);
    }
}

运算结果:

1
1

六、控制语句

控制语句是用来对程序流程的选择、循环、转向和返回等进行控制的。
Java中共有四类8种控制语句:

  • 选择语句:if、switch
  • 循环语句:for、while、do…while
  • 转向语句:break、continue
  • 返回语句:return

6.1 选择语句

选择语句又称分支语句,它用来对给定的条件进行判断,从而决定执行两个或多个分支中的哪一支。

6.1.1 if语句

  • if语句在任何情况下都只有一个分支进行

if语句的语法格式:

//第一种
if(布尔表达式){
	java语句;
}

//第二种
if(布尔表达式){
	java语句;
} else {
	java语句;
}

//第三种
if(布尔表达式){
	java语句;
}else if(布尔表达式){
	java语句;
} else {
	java语句;
}

//第四种
if(布尔表达式){
	java语句;
}else if(布尔表达式){
	java语句;
} else if(布尔表达式){
	java语句;
}

实例:

public class Test {
    public static void main(String[] args) {
        boolean a = true;
        String b = "";
        if(a){
            b = "男";
        } else {
            b = "女";
        }
        System.out.println(b);
    }
}

运行结果:

6.1.2 switch语句

  • switch()中可以放byte、short、int、char、String类型
  • switch 语句中 case 可以进行合并

switch的语法格式为:

switch(变量){
	case 字面量:
		java语句;
		break;//非必须
	case 字面量:
		java语句;
		break;//非必须
	default://非必须
		java语句;	
}

实例:

import java.util.Scanner;
public class Test {
    public static void main(String[] args) {//
        Scanner scan = new Scanner(System.in);
        System.out.print("请输入[1-7]的整数数字:");
        int dayOfWeek = scan.nextInt();
        switch(dayOfWeek){
            case 1:
            case 2:
            case 3:
            case 4:
            case 5:
                System.out.println("今天是工作日哦!");
                break;
            case 6:
                case 7:
                System.out.println("今天是休息日哦!");
                break;
            default :
                System.out.println("对不起,您的输入有误");
        }
    }
}

运算结果:

请输入[1-7]的整数数字:4
今天是工作日哦!

6.2 循环语句

6.2.1 for语句

  • for语句执行顺序:初始表达式、布尔表达式、循环体、更新表达式

for语句的语法格式:

for(初始循环表达式;布尔表达式;更新表达式){
	循环体;
}

实例:

public class Test {
    public static void main(String[] args) {//计算1~100所有奇数之和
        int sum = 0;
        for(int i = 1; i <= 100; i++){
            if(i % 2 != 0){
                sum += i;
            }
        }
        System.out.println("sum = " + sum);
    }
}

运行结果:

sum = 2500

6.2.2 while语句

while语句的语法格式:

while(布尔表达式){
	循环体;
}

实例:

public class Test {
    public static void main(String[] args) {//计算1~100所有偶数之和
        int sum = 0;
        int i = 0;
        while(i <= 100){ 
            if(i % 2 == 0){
                sum += i; 
            }
        i++; 
        }
        System.out.println("sum = " + sum);
    }
}

运算结果:

sum = 2550

6.2.3 do…while语句

  • do…while 循环至少会执行一次

do…while语句的语法格式:

do{
	循环体;
}while(布尔表达式);

实例:

import java.util.Scanner;
public class Test {
    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);
        String username;
        String password;
        do{
            System.out.print("用户名:");
            username = scanner.next();
            System.out.print("密码:");
            password = scanner.next();
        }while(!username.equals("admin") || !password.equals("123"));
        System.out.println("登录成功,欢迎" + username + "回来!");
    }
}

运行结果:

用户名:1
密码:1
用户名:admin
密码:123
登录成功,欢迎admin回来!

6.3 转向语句

  • 在Java中转向语句有break和continue
  • 转向语句用于实现循环执行过程中程序流程的流转

6.3.1 break语句

  • break语句可以用于switch中,在循环中,break用来终止跳出循环

实例:

public class Test {
    public static void main(String[] args) {
        for(int i = 1; i <= 10; i++){
            if(i == 5){
                break;
            }
        System.out.println("break : i = " + i);
        }
    }
}

运行结果:

break : i = 1
break : i = 2
break : i = 3
break : i = 4

6.3.2 continue语句

  • continue 适用于任何循环控制结构中,作用是让程序立刻跳到下一次循环
    • 在 for 循环中,continue 语句使程序跳到更新语句
    • 在 while 或 do…while 循环中,程序立即跳转到布尔表达式的判断语句

实例:

public class Test {
    public static void main(String[] args) {
        for(int i = 1; i <= 10; i++){
            if(i == 5){
                continue;
            }
        System.out.println("continue : i = " + i);
        }
    }
}

运行结果:

continue : i = 1
continue : i = 2
continue : i = 3
continue : i = 4
continue : i = 6
continue : i = 7
continue : i = 8
continue : i = 9
continue : i = 10

七、方法

方法是指一段可以完成某个特定功能的并且可以被重复使用的代码片段。

7.1 方法的声明

  • 在使用方法前必须对其声明

方法的声明格式:

[修饰符列表] 返回值列表 方法名(形式参数列表){
	方法体;
}

实例:

public static void sumInt(int a,int b){
	int c = a + b;
	System.out.println(a + "+" + b+ "="  +c);
}
/*
*public static 是修饰符列表
*void 是返回值
*sumInt 是方法名
*(int a,int b)是形式参数,每一个形参都是局部变量
*一对大括号括起来的是方法体
*/
  • [修饰符列表],此选项是可选项,非必须的
  • 返回值,类型可以是Java中任意一种数据类型
    • 如果方法返回类型不为空,那必须在方法体最后加“return 值”,且要考虑到所有程序出口的return 值
    • 返回值类型为void,在方法体最后不能加“return 值”,但是可以加“return;”
      • return表示结束当前方法。执行return后的本方法内语句是无法执行的
  • 方法名,必须为合法的标识符,遵守驼峰命名
  • 形式参数,个数为0~N。多个参数用逗号隔开

7.2 方法的调用

  • 方法声明完后,需要手动调用

  • 调用方法的语法格式(前提:方法被static修饰)是“类名.方法名(实际参数列表);”。

实例:

public class Test{
	public static void main(String[] args){
		sumInt(100,200);//100和200为实际参数,类名可省略
		Other.doOther();//类名不可省略!
	}
	public static void sumInt(int x,int y){//int x和int y为形式参数
		System.out.println(x+"+"+y+"="+(x+y));
	}
}

public class Other{
	public static void doOther(){
		System.out.println("Other");
	}
}
  • 实际参数和形式参数的个数和类型必须一一对应。(也可能存在自动类型转换,小转大可以)
  • 在同一个类中的方法调用时,可以省略类名。

7.3 方法的重载

方法重载是指同一个类中定义多个同名的方法,但是每个方法具有不同的个数、类型或顺序的参数。

  • 继承父类的子类中有和父类中方法同名但参数不同的也是方法重载
  • 方法重载常用于创建完成一组任务相似,但参数个数、类型或顺序不同的方法

实例:

public class U {//以下均为方法p的方法重载
	public static void p(){ 
		System.out.println();
	}
	public static void p(int x){ 
		System.out.println();
	}
	public static void p(int x,long y){
		System.out.println(); 
	}
	public static void p(long x,int y){ 
		System.out.println();
	}
}
  • 在调用时通过传递给他们不同个数、类型或顺序的实参来判断使用哪个方法
  • 方法重载与修饰词列表和返回值类型无关
  • 构成重载的条件:
    • 在同一个类中
    • 方法名相同
    • 参数列表不同(个数不同 或 类型不同 或 顺序不同)

7.4 方法的递归

方法调用自身叫做方法的递归调用。

实例:

public class Test {
    public static void main(String []args){//使用递归的方式计算5的阶乘
     int n = 5;
     int result = f(n);
     System.out.println(result);
    }
    public static int f(int n){
        if (n == 1){
            return 1;
        }
        return n*f(n-1);
    }
}

八、面向对象编程

8.1类和对象

类是现实世界中具有共同特征的事物进行抽象形成的模板或概念。
对象是实际存在的个体。

  • 通过类可以创建对象,对象也被称为实例,创建对象的过程也叫实例化。
  • 对对象的特征进行抽取形成类,这个过程叫抽象。

8.1.1 类的定义

类由属性和方法构成。

  • 属性描述的是状态,方法描述的是行为动作

  • 对象的属性以变量的形式存在,这里的变量就是成员变量中的实例(成员)变量

  • 在Java中,凡是使用class创建的类,都属于引用数据类型

定义类的语法格式:

[修饰符] class 类名 {
	类体;//类体=属性+方法
}

实例:

public class Student{//定义一个学生类
	//学号
	int no;
	//姓名
	String name;
	//年龄
	int age;
	//性别
	boolean sex;
}

8.1.2 对象的创建和使用

8.1.2.1对象的创建
  • 类定义后才可以创建对象

  • 一个类可以创建多个对象

创建对象的语法格式:

new 类名();

实例:

public class Test{
	public static void main(String[] args){
		//创建一个学生对象
		new Student();
		//再创建两个学生对象,用变量接收一下
		Student s1 = new Student();
		Student s2 = new Student();
	}
}
public class Student{//定义一个学生类
	//学号
	int no;
	//姓名
	String name;
	//年龄
	int age;
	//性别
	boolean sex;
}
8.1.2.2 对象的使用
public class Test{
	public static void main(String[] args){
		//创建一个学生对象
		Student s = new Student();
		System.out.println("学号:" + s.no);
		System.out.println("姓名:" + s.name);
		System.out.println("年龄:" + s.age);
		System.out.println("性别:" + s.sex);
	}
}
public class Student{//定义一个学生类
	//学号
	int no;
	//姓名
	String name;
	//年龄
	int age;
	//性别
	boolean sex;
}

运行结果:

学号:0
姓名:null
年龄:0
性别:false
  • 如果实例变量没有被手动赋值,在创建对象时,程序会给实例变量默认赋值
8.1.2.3 构造方法

构造方法是类中的特殊方法

  • 通过调用构造方法来完成对象的创建以及对象属性的初始化操作

构造方法定义的语法格式:

[修饰符列表] 构造方法名(形式参数列表){
	构造方法体;
}
  • 构造方法名和类名一致
  • 构造方法不能写返回值类型(包括void)
  • 一个类中可以定义多个构造方法,即允许方法重载
  • 构造方法的返回值是当前类的类型
  • 当一个类没有显示定义任何构造方法时,程序会默认提供无参构造方法
  • 一旦有程序员自己定义的构造方法后,程序将不再默认提供无参构造方法

实例:

public class Test {
    public static void main(String[] args){
        new Data();
        new Data(2020);//没有手动赋值的属性,程序依然会自动默认
        new Data(2020,8);
        new Data(2020,8,23);
    }
}
public class Data {
    int year;
    int month;
    int day;

    public Data(){
        System.out.println(year+","+month+","+day+" 无参构造");
    }
    public Data(int year){
        System.out.println(year+","+month+","+day+" 带year构造");
    }
    public Data(int year,int month){
        System.out.println(year+","+month+","+day+" 带year,month构造");
    }
    public Data(int year,int month,int day){
        System.out.println(year+","+month+","+day+" 带year,month,day构造");
    }
}

运行结果:

0,0,0 无参构造
2020,0,0 带year构造
2020,8,0 带year,month构造
2020,8,23 带year,month,day构造
8.1.2.4 空指针异常

实例:

public class PointerTest{
	public static void main(String[] args){
		Pointer p=new Pointer();
		System.out.println(p.i);
		p=Null;//造成空指针异常java.lang.NullPointerException,报错!
		System.out.println(p.i);
	}
} 
public class Pointer{
	int i;
}

运行结果:

0
Exception in thread "main" java.lang.NullPointerException
 at PointerTest.main(PointerTest.java:6)
  • 当p=null时,p引用就无法找到堆内存中的Java对象了,程序就无法正常访问
8.1.2.5 方法调用时参数的传递问题

当参数为基本数据类型时,参数传递的是数据10:

public class Test {
    public static void main(String[] args){
        int x = 10;
        int y = x;//仅将x的值复制一份给y
        add(x);
        System.out.println("main:"+y);
    }
    public static void add(int i){
        i++;
        System.out.println("add:"+i);
    }
}

运行结果:

add:11
main:10

当参数为引用数据类型时,参数传递的是内存地址:

public class Test {
    public static void main(String[] args){
        Person p = new Person();
        Person p1 = new Person();
        p.age = 10;
        p1 = p;//将p的地址复制一份给p1
        add(p1);//因为p1和p的内存地址相同,因此修改p1中age就相当于修改p中的age
        System.out.println("main:"+p.age);
    }
    public static void add(Person p2){
        p2.age++;
        System.out.println("add:"+p2.age);
    }
}
class Person{
    int age;
}

运行结果:

add:11
main:11
  • 前者把x的值“10”复制一份给了y,而后者把p的内存地址复制了一份给了p1,因此导致p和p1指向的地址是同一个Java对象,通过任何一个引用去访问堆内存中的对象,对象内存都会受到影响

九、封装

封装是指利用抽象数据类型将数据和基于数据的操作封装在一起,使其构成一个不可分割的独立实体,数据被保护在抽象数据类型的内部,尽可能的隐藏内部的细节,只保留一些对外接口使之与外部发生联系。

  • 系统的其他对象只能通过包裹在数据外面的已经授权的操作来与这个封装的对象进行交流和交互

  • 封装降低了程序的耦合度,提高了系统的扩展性以及重用性,可以隐藏内部实现细节,外部看不到内部复杂结构,对外只提供简单的安全的操作入口,更安全

9.1如何封装

  • 使用Java语言中的private修饰符,private表示私有的,私有的数据只能在本类中访问

实例:

public class MobilePhoneTest {
    public static void main(String[] args){
        MobilePhone phone = new MobilePhone();
        phone.voltage = 3.7;
        System.out.println(phone.voltage);
        phone.voltage = 100;
        System.out.println(phone.voltage);
    }
}
public class MobilePhone {
    private double voltage;
}

运行结果:

java: voltage 在 MobilePhone 中是 private 访问控制
  • private修饰的数据无法在外部程序直接访问

9.2 set和get方法

set和get方法是用来提供访问入口的

  • set和get方法访问的都是某个具体对象的属性,不同对象调用set和get方法获取的属性值不同,set和get方法必须有对象的存在才能调用

  • set方法是用来修改属性值的。一般在set方法内部编写安全控制程序

  • get方法是用来读取属性值的。不需要参数。返回值类型是该属性所属类型

set方法定义的语法格式:

public void set+属性名首字母大写(参数){
	xxx = 参数;
}

get方法定义的语法格式:

public 返回值类型 get+属性名首字母大写(无参数){
	return xxx;
}

实例:

public class MobilePhoneTest {
    public static void main(String[] args){
        MobilePhone phone = new MobilePhone();
        phone.setVoltage(3.7);
        System.out.println(phone.getVoltage());
        phone.setVoltage(100);
        System.out.println(phone.getVoltage());
    }
}
public class MobilePhone {

    private double voltage;
    public MobilePhone(){//无参构造方法

    }
    public void setVoltage(double _voltage) {//set方法,只能用来修改属性值
        if(_voltage<3||_voltage>5){//用来设置门槛,保证修改安全
            throw new RuntimeException("电压输入错误");
        }
        voltage=_voltage;
    }
    public double getVoltage() {//get方法,只能用来读取数据
        return voltage;
    }
}

运行结果:

3.7
Exception in thread "main" java.lang.RuntimeException: 电压输入错误
at MobilePhone.setVoltage(MobilePhone.java:10)
at MobilePhoneTest.main(MobilePhoneTest.java:6)

十、this和static

10.1 this

this是Java中的关键字,指“当前对象”

  • this这个引用保存了当前对象的内存地址指向自身
  • this在实例方法以及构造方法中,语法格式分别为“this.”和“this(实际参数列表)”
  • this不能出现在有静态方法中,只能出现在实例方法中

实例:

public class ThisTest {
    public static void main(String[] args){
        Customer c1 = new Customer("张三");
        c1.shopping();
        Customer c2 = new Customer("李四");
        c2.shopping();
    }
}
class Customer{
    String name;
    public Customer(){
    }
    public Customer(String s){
        name=s;
    }
    public void shopping(){
        System.out.println(this.name + "正在购物!");//name前面可以隐藏(this.)
    }
}
  • 当形参名和类中属性名重名时,this是不能省略的

实例:

class Customer{
    String name;
    public Customer(){
    }
    public Customer(String name){
        //name = name;//如果形参也命名为name,系统会遵循就近原则,所以name = name中,两个name都为形参name
        this.name = name;//这是this的第二个用法,前者是本类中实例变量name,后者是形参name,此处不能省略this
    }
  • this(实际参数列表)用在构造方法里

实例:

public class Date {
    private int year;
    private int month;
    private int day;
    public Date(){
        this.year = 1970;
        this.month = 1;
        this.day = 1;
    }
    public Date(int year,int month,int day){
        this.year = year;
        this.month = month;
        this.day = day;
    }
    public int getYear(){
        return year;
    }
    public void setYear(int year){
        this.year = year;
    }
    public int getMonth(){
        return month;
    }
    public void setMonth(int month){
        this.month = month;
    }
    public int getDay(){
        return day;
    }
    public void setDay(int day){
        this.day = day;
    }
}

public class DateTest {
    public static void main(String[] args){
        Date d1 = new Date();
        System.out.println(d1.getYear()  +  "年 "  +  d1.getMonth()  +  "月 "  + d1.getDay() + "日");
        Date d2 = new Date(2008,8,8);
        System.out.println(d2.getYear()  +  "年 "  +  d2.getMonth()  +  "月 "  + d2.getDay() + "日");
    }
}

在上面的无参构造方法和有参构造方法中,代码基本相同,没有复用,这时可以采用this()的方式。

  • this()语法只能出现在构造方法的第一行,因此在一个构造方法中this()只能出现一次

实例:

public Date(){
    this(1970,1,1);
}
public Date(int year,int month,int day){
    this.year = year;
    this.month = month;
    this.day = day;
}

10.2 static

static是Java中的关键字,表示“静态的”,可以用来修饰变量、方法、代码块。

  • 在Java中凡是用static修饰的都是类相关的
  • 实例变量必须先创建对象才能访问,通过“引用.”访问。实例变量在构造方法执行时才初始化
  • 静态变量访问时不需要创建对象,直接通过“类名.”访问。静态变量在类加载时就初始化

10.2.1 static变量

当一个类中所有对象的某个属性值不会随着对象的变化而变化时,我们可以把这个属性定义为静态属性。

  • 静态属性不需要创建对象,在类加载时初始化,直接通过“类名.”来访问
  • 引用.的形式也可以,但是很不建议用,实际上程序还是通过“类.”的方式访问的,并不会出现空指针异常

实例:

public class ManTest{
	public static void main(String[] args){
		System.out.println(Man.sex);//静态变量用类名.形式访问
	}
}
public class Man{
	int idCard;
	static boolean sex = true;
}

10.2.2 static方法

static方法一般用在工具类。

  • 静态方法不需要创建对象,直接通过“类名.”访问。也可以用使用“引用.”来访问,但是很不建议
  • 方法描述的是行为动作,当某个行为动作需要对象的参与,这个方法应该定义为实例方法
  • 当方法体中直接访问了实例变量,那这个方法一定是实例方法

比如为了简化输出语句编写的工具类
实例:

public class U {
	public static void p(int data){ 
		System.out.println(data);
	}
	public static void p(long data){ 
		System.out.println(data);
	}
	public static void p(float data){ 
		System.out.println(data);
	}
	public static void p(double data){ 
		System.out.println(data);
	}
	public static void p(boolean data){ 
		System.out.println(data);
	}
	public static void p(char data){
		System.out.println(data); 
	}
	public static void p(String data){ 
	System.out.println(data);
	}
}
public class HelloWorld {
	public static void main(String[] args) { 
		U.p("Hello World!");
		U.p(true); 
		U.p(3.14); 
		U.p('A');
	} 
}

10.2.3 静态代码块

静态代码块是Java为程序员提供的一个特殊时刻,如果想在类加载时,执行一段代码就使用静态代码块。

  • 静态代码块在类加载时执行,在main方法执行前,并且只执行一次

静态代码块的语法格式:

类{
	static{
		java语句;
	}
}
  • 静态代码块内部和静态代码块之间都遵循自上而下的顺序执行,类体内代码也有执行顺序

实例:

public static StaticTest{
	static int i = 100;//放在此处正确
	static{
		System.out.println(i);
	}
	static int i = 100;//放在此处访问不到
}//静态代码块是访问不到后面的i变量的,必须将变量放在前面

10.2.4 实例代码块

实例语句块在构造方法执行前自动执行。

实例代码块的语法格式:

 类{
		{
			java语句;
		}
}

静态代码块和实例代码块的执行顺序
实例:

public class CodeOrder {
    static{
        System.out.println("A");
    }
    public static void main(String[] args){
        System.out.println("Y");
        new CodeOrder();
        System.out.println("Z");
    }
    public CodeOrder(){
        System.out.println("B");
    }
    {
        System.out.println("C");
    }
    static{
        System.out.println("X");
    }

}

运行结果:

A
X
Y
C
B
Z

十一、继承

子类继承父类的特征和行为,使子类对象(实例)具有父类的属性。

  • 继承可以看作将父类中的属性方法(除构造方法外)直接复制到子类中
  • 不同的类中持有的共同的特征和动作,可以放在一个通用类中,让其他类共享

Java中继承的语法格式:

class 类名 extends 父类名{
	类体;
}

实例:

public class Account { //银行账户类 
	//账号
	private String actno; //余额
	private double balance;
	//账号和余额的 set 和 get 方法 
	public String getActno() {
		return actno;
	}
	public void setActno(String actno) { 
		this.actno = actno;
	}
	public double getBalance() {
		return balance; 
	}
	public void setBalance(double balance) { 					
		this.balance = balance;
	}
}
public class CreditAccount extends Account{ //信用账户类 
	//信誉度(信用账户类特有属性)
	private double credit; 
	//信誉度的 set 和 get 方法 
	public double getCredit() {
		return credit; 
	}
	public void setCredit(double credit) { 
		this.credit = credit;
	} 
}
public class AccountTest {
	public static void main(String[] args) { 
		CreditAccount act = new CreditAccount(); act.setActno("111111111");
		act.setBalance(9000.0);
		System.out.println(act.getActno()+"信用账户,余额"+act.getBanlance()+"元");
	}
}
  • 通过继承解决了代码复用的问题,但继承会导致耦合度高
  • B 类继承 A类,称 A类为超类、父类、基类,B 类则称为子类、派生类、扩展类
  • java 中的继承只支持单继承,不支持多继承。但可以通过间接继承,达到多继承的效果
  • 子类继承父类,构造方法和被 private 修饰的数据不能被继承
  • java 中的类若没有显性继承任何类,则默认继承根类Object

十二、方法的覆盖和多态

12.1 方法覆盖

  • 父类继承过来的方法无法满足子类业务需求时,可以将父类中继承过来的方法重写
  • 当该方法被重写后,子类对象一定会调用重写后的方法

实例:

public class Animal {
    public void move(){
        System.out.println("动物在移动!");
    }
}
public class Cat extends Animal{
    public void move(){
        System.out.println("猫在走猫步!");
    }
    public void catchMouse(){
        System.out.println("猫在抓老鼠");
    }
}

public class Bird extends Animal{
    public void move(){
        System.out.println("鸟儿在飞翔!");
    }
}

public class Test {
    public static void main(String[] args){
        Cat cat = new Cat();
        cat.move();
        cat.catchMouse();
        Bird bird = new Bird();
        bird.move();
    }
}

运行结果:

猫在走猫步!
猫在抓老鼠
鸟儿在飞翔!
  • 方法覆盖只能用在具有继承关系的父子类之间
  • 覆盖后的方法应与原方法具有相同的返回值,方法名和相同的形式参数列表(建议直接复制到子类)
  • 构造方法和私有的方法不能被继承,所以不能被覆盖
  • 覆盖后的方法不能比原方法有更低的访问权限,只能更高(封闭)
  • 覆盖后的方法不能比原方法抛出更多的异常,可以相同或少
  • 方法覆盖只和方法有关,与属性无关
  • 静态方法不存在覆盖(可以但意义不大)

12.2 多态

多态就是同一个行为发生在不同的对象上会产生不同的效果。

  • Java中允许多态两种语法出现:向上转型和向下转型

  • 无论是向上转型还是向下转型,两个类必须有继承关系

12.2.1 向上转型

向上转型是子类型转为父类型。又称为自动转换类型。
实例:

public class PolyTest {
    public static void main(String[] args) { //创建 Animal 对象
        Animal a1 = new Cat();//将Animal类属性指向Cat类
        a1.move();
        Animal a2 = new Bird();
        a2.move();
    }
}
class Animal {
    public void move(){
        System.out.println("Animal move!");
    }
}
class Cat extends Animal{
    //方法覆盖
    public void move(){
        System.out.println("走猫步!");
    }
    //子类特有
    public void catchMouse(){
        System.out.println("抓老鼠!");
    }
}
class Bird extends Animal { //方法覆盖
    public void move() {
        System.out.println("鸟儿在飞翔!");
    }
    //子类特有
    public void sing() {
        System.out.println("鸟儿在歌唱!");
    }
}

运行结果:
走猫步!
鸟儿在飞翔!
Java程序运行包括编译和运行:

  • 在编译阶段编译器只知道a1的数据类型是Animal,编译器会去Animal.class字节码中查找move()方法,发现方法后,将move()方法绑定到a1引用上,编译通过。这叫静态绑定
  • 在运行阶段实际上在堆内存中存的是Cat类型,所以运行时会自动执行Cat类中的move()方法。这叫动态绑定

12.2.2 向下转型

向下转型是父类型转为子类型。又称为强制转换类型。

  • 当需要访问子类对象中的特有方法时,需要向下转型

实例:

public class PolyTest {
    public static void main(String[] args) {
        Animal a = new Cat();
        a.catchMouse();//访问子类中特有方法
    }
}
class Animal {
    public void move(){
        System.out.println("Animal move!");
    }
}
class Cat extends Animal{
    //方法覆盖
    public void move(){
        System.out.println("走猫步!");
    }
    //子类特有
    public void catchMouse(){
        System.out.println("抓老鼠!");
    }
}
class Bird extends Animal { //方法覆盖
    public void move() {
        System.out.println("鸟儿在飞翔!");
    }
    //子类特有
    public void sing() {
        System.out.println("鸟儿在歌唱!");
    }
}

运行结果:

java: 找不到符号
  符号:   方法 catchMouse()
  位置: 类型为Animal的变量 a
  • 在编译时编译器只知道a变量的数据类型是Animal,只会去Animal.class字节码文件中寻找catchMouse()方法,但是没找到,编译错误

代码应改为:

public class PolyTest {
    public static void main(String[] args) {
        Animal a = new Cat();
        Cat c = (Cat)a;//强制转换类型:将Animal强转换成Cat类
        c.catchMouse();
    }
}
class Animal {
    public void move(){
        System.out.println("Animal move!");
    }
}
class Cat extends Animal{
    //方法覆盖
    public void move(){
        System.out.println("走猫步!");
    }
    //子类特有
    public void catchMouse(){
        System.out.println("抓老鼠!");
    }
}
class Bird extends Animal { //方法覆盖
    public void move() {
        System.out.println("鸟儿在飞翔!");
    }
    //子类特有
    public void sing() {
        System.out.println("鸟儿在歌唱!");
    }
}
  • 向下转型有风险

实例:

public class PolyTest {
    public static void main(String[] args) {
        Animal a = new Bird();
        Cat c = (Cat)a;
    }
}
class Animal {
    public void move(){
        System.out.println("Animal move!");
    }
}
class Cat extends Animal{
    //方法覆盖
    public void move(){
        System.out.println("走猫步!");
    }
    //子类特有
    public void catchMouse(){
        System.out.println("抓老鼠!");
    }
}
class Bird extends Animal { //方法覆盖
    public void move() {
        System.out.println("鸟儿在飞翔!");
    }
    //子类特有
    public void sing() {
        System.out.println("鸟儿在歌唱!");
    }
}

运行结果:

Exception in thread "main" java.lang.ClassCastException: class Bird cannot be cast to class Cat (Bird and Cat are in unnamed module of loader 'app')
at PolyTest04.main(PolyTest04.java:4)
  • 编译可以通过,因为编译器只知道在a变量是Animal类且存在继承关系,语法上没有错误,编译通过
  • 运行没有通过,因为在运行时堆内存中创建了一个Bird对象,Cat和Bird是没有继承关系的,所以强转失败

12.2.3 instanceof运算符

在向下转型时,需要用instanceof来判断是否可以进行强转。

  • instanceof运算符的结果是布尔类型

  • (c instanceof Cat)结果是true,说明在运行阶段c引用指向的对象是Cat类型

实例:

public class PolyTest {
	public static void main(String[] args) { 
		Animal a = new Bird();
		if(a instanceof Cat){ 
			Cat c = (Cat)a; 
			c.catchMouse();
		} 
	}
}
class Animal {
    public void move(){
        System.out.println("Animal move!");
    }
}
class Cat extends Animal{
    //方法覆盖
    public void move(){
        System.out.println("走猫步!");
    }
    //子类特有
    public void catchMouse(){
        System.out.println("抓老鼠!");
    }
}
class Bird extends Animal { //方法覆盖
    public void move() {
        System.out.println("鸟儿在飞翔!");
    }
    //子类特有
    public void sing() {
        System.out.println("鸟儿在歌唱!");
    }
}

12.2.4多态在开发中的应用

实例:

public class PolyTest {
    public static void main(String[] args){
        Dog dog = new Dog("二哈");
        Bird bird = new Bird("小鸟儿");
        Master master = new Master();
        master.feed(dog);
        master.feed(bird);
    }
}
class Master{
    public void feed(Pet pet){
        System.out.println("主人开始喂食");
        pet.eat();
        System.out.println("主人喂食完毕");
    }
}
class Pet{
    String name;
    public void eat(){

    }
}
class Dog extends Pet{
    public Dog(String name){//有参构造方法
        this.name = name;
    }
    public void eat(){//重写方法
        System.out.println(this.name+"在吃骨头");
    }
}
class Bird extends Pet{
    public Bird(String name){//有参构造方法
        this.name = name;
    }
    public void eat(){//重写方法
        System.out.println(this.name+"在唱歌");
    }
}

运行结果:

主人开始喂食
二哈在吃骨头
主人喂食完毕
主人开始喂食
小鸟儿在唱歌
主人喂食完毕

十三、super关键字

super代表当前对象中从父类继承过来的那部分特征。

  • super()只能从出现在构造方法第一行,通过当前方法去调用父类中的构造方法,目的是创建子类对象时,先初始化父类特征

  • super可以出现在实例方法和构造方法中,但不能使用在静态方法中

  • super的语法为:“super”、“super()”

  • super. 大部分情况下不能省略,例如:父类子类用同名属性,或同名方法。想在子类中访问父类的不能省略

  • super和this不能共存

  • 当一个构造方法第一行:既没有this()有没有super(),默认会有一个super();表示通过当前子类构造方法调用父类的无参构造方法

  • super不是引用,也不保存内存地址,也不指向任何对象

实例:

public class SuperTest {
    public static void main(String[] args){
        new B();
    }
}
class A{
    public A(){
        System.out.println("A类型的无参构造方法");
    }
    public A(int i){
        System.out.println("A类型的有参构造方法");
    }
}
class B extends A{
    public B(){
        super();如果此处没写任何东西,默认会有一个super();去调用父类的无参构造方法
        //super(100);如果此处写了super(100);那只会调用父类的有参构造方法
        System.out.println("B类型的无参构造方法");
    }

}

运行结果:

A类型的无参构造方法
B类型的无参构造方法

实例:

public class SuperTest {
    public static void main(String[] args){
        new C();
    }
}
class A{
    public A(){//无参构造
        System.out.println("1");
    }
}
class B extends A{
    public B(){//无参构造
        System.out.println("2");
    }
    public B(String name){//有参构造
        //此处存在隐式无参super
        System.out.println("3");
    }
}
class C extends B{
    public C(){//无参构造
        this("zhangsan");
        System.out.println("4");
    }
    public C(String name){//有参构造
        this(name,20);
        System.out.println("5");
    }
    public C(String name,int age){//有参构造
        super(name);//显式有参super
        System.out.println("6");
    }
}

运行结果:

1
3
6
5
4

super(实参列表)的适当使用:

public class SuperTest {
    public static void main(String[] args){
        CreditAccount ca1 = new CreditAccount();
        System.out.println(ca1.getActno()+","+ca1.getBalance()+","+ca1.getCredit());
        CreditAccount ca2 = new CreditAccount("1111",1000.0,0.99);
        System.out.println(ca2.getActno()+","+ca2.getBalance()+","+ca2.getCredit());
    }
}
class Account{
    //账户号
    private String actno;
    //余额
    private double balance;
    public Account(){

    }
    public Account(String actno,double balance) {
        this.actno = actno;
        this.balance = balance;
    }
    public void setActno(){
        this.actno = actno;
    }
    public String getActno(){
        return actno;
    }
    public void setBalance(double balance){
        this.balance = balance;
    }
    public double getBalance(){
        return balance;
    }
}
class CreditAccount extends Account{
    //属性:信誉度,子类特有的特征
    private double credit;
    public CreditAccount(){

    }
    public CreditAccount(String actno,double balance,double credit){
        //this.actno = actno;
        //this.balance = balance;
        // 这两条的属性是父类中的私有属性,无法访问
        //可以通过super()去调用父类中的有参构造方法
        super(actno,balance);
        this.credit = credit;
    }
    public void setCredit(double credit){
        this.credit = credit;
    }
    public double getCredit(){
        return credit;
    }
}

运行结果:

null,0.0,0.0
1111,1000.0,0.99
  • super什么时候不能省略:当父类子类有同名实例变量或实例方法时

实例:

public class SuperTest {
    public static void main(String[] args){
        Vip v = new Vip("张三");
        v.shopping();
    }
}
class Customer{
    String name;
    public  Customer(){

    }
    public Customer(String name){
        //super();
        this.name = name;
    }
}
class Vip extends Customer{
    //和父类有同名属性
    String name;
    public Vip(){

    }
    public Vip(String name){
        super(name);
    }
    public void shopping(){
        System.out.println(this.name + "正在购物");
        System.out.println(super.name + "正在购物");
        System.out.println(name + "正在购物");
    }
}

运行结果:

null正在购物
张三正在购物
null正在购物
  • super不仅可以访问父类属性,也可以访问父类方法

实例:

public class SuperTest {
    public static void main(){
        Cat c = new Cat();
        c.yiDong();
    }
}
class Animal{
    public void move(){
        System.out.println("Animal move");
    }
}
class Cat extends Animal{
    public void move(){
        System.out.println("CAt move");
    }
    public void yiDong(){
        this.move();
        move();
        super.move();
    }
}


运行结果:

Cat move
Cat move
Animal move
  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Spring伦儿

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值