02 Java语言基础

Java 语言基础

第一节、变量
1 变量概念

在计算机中用于存数据的内存空间,这空间有格式大小的区分。

2 变量三要素

变量存在三要素:

  • 数据类型 【规定了这个空间存放值的类型】
  • 变量名 【方便记忆寻址到这个内存空间】
  • 变量值 【存放的具体内容 】
3 变量声明与赋值
数据类型 变量名 =;  理解把等号 右边的值 赋值给左边的变量保存。 
//定义一个变量
int age =  29;
//访问一个变量
System.out.println(age) // 这里不要“”
4 变量使用细节
public class VarDemo{

	public static void main(String[] args){		
		//定义
		int age = 20;
		//使用
		//1.1 直接使用
		System.out.println(age);
		//1.2 变量值传递
		int xiaoMingAge = age;
		System.out.println(xiaoMingAge);
		
		
		//声明一个变量
		int money;
		// 第一次赋值叫初始化
		money = 100;
		System.out.println(money);
		// 修改变量值,变量允许执行期间修改值
		money = 200;
		System.out.println(money);
		
		 
		//声明多个变量
		int a , b, c;
		a = 10086;
		b = 10000;
		c = 10010;
		System.out.printf("%d %d %d \n",a,b,c);
		
		
		// 声明多个变量 并赋值
		int m , s=100, h=0;
		m = 1;
	    System.out.printf("%d %d %d \n",m,s,h);
		
		 
		int level = 12;
		//int level = 90; 			// Error 相同作用域下不允许出现同名变量
		
		int sg ;
		// System.out.println(sg);  // Error 局部变量必须先赋值后使用
		
		int sb;
		//sb= "hello";   			// Error  变量值实际类型必须和 变量类型一致(兼容)。
	}
}
 
第二节、数据类型

数据类型规定了数据的大小,用合理的数据类型的变量存储数据。java是一种强类型的编程语言,对类型要求非常严格。java中的数据类型大致为 基本数据类型 引用数据类型

2.1 类型介绍
8大基本数据类型
byteshortintlongfloatdoublecharboolean
字节类型短整型整型长整型单精度双精度字符布尔
1字节2字节4字节8字节4字节8字节2字节1字节

思考? 整数为什么需要 4 整数类型

答:因为不同类型表示范围是不一样的。

进制 概念

什么是进制?
进制是表示和存储数据的方式,人类生活多用10进制,计算机使用的是二进制。  
十进制: 由 0 1 2 3 4 5 6 7 8 9  十个数码组成。逢10进1
(123)10 
=>
1*10^2 + 2*10^1 + 3*10^0 = 123

二进制: 由  0、1 两个数码组成。逢2进1。
(  0  1  0  1 )2
=> 二进制换算十进制。
1*2^2+1*2^0=> 5
 
=> 十进制换算二进制。
2 | 10        0
   ————————
  2 | 5       1
     ————————
     2| 2       0
       -------
       |  1   
>1010

一个二进制中的数码表示 1位 bit
一个字节byte 等于8个 bit
0000 0000 byte 
0000 0000 0000 0000 short
0000 0000 0000 0000 0000 0000 0000 0000  int
0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 long

如何确定表示范围呢?
0000 0000 byte 
源码:直接化二进制,最高位表示符号位,0 表示正数 1表示负数
10 
+10  0000 1010
-10  1000 1010
反码:正数的反码和源码和补码形同。负数的反码除符号位其位取反。
10 : 0000 1010
-10: 1111 0101
补码:正数的反码和源码和补码形同。负数的补码反码+1
10 : 0000 1010
-10: 1111 0110
在计算机中数据使用补码表示。
引用数据类型
除了基本数据类型以外的其他类型都是引用类型:
自定义类  String 、接口 、数组 、枚举、......
2.2 类型使用详解
2.2.1 byte
//定义一个byte类型变量
byte m1 = 90;
System.out.println( m1 );

//超出了byte范围 报错。
//byte m2 = 128;  // Error
//byte m3 = -200; // Error
//System.out.println( m1 + ", " + m2 + ", " + m3  );

IO 操作需要处理字节时常用。

2.2.2 short
//定义一个short变量
short a1 = 30000;
System.out.println( a1 );	 

很少使用,基本使用int 代替他,除非有要求。

2.2.3 int

表示一个整数

int sal = 930320999;
System.out.println( sal );

开发中整数类型首选它,常用类型 出镜率非常高

2.2.4 long

表示一个 长整型数据

long count = 7000000000L;
System.out.println( count );

long 数据类型 赋值建议使用L l

2.2.5 float

表示一个 浮点数

float f1 = 9.8f;
System.out.println( f1 );

float 数据类型 赋值建议使用 f F 后缀

2.2.6 double

表示 高精度浮点数

double f2 = 3.1415926d;
System.out.println( f2 );

double 数据类型 赋值也可以使用 d D 后缀

2.2.7 boolean

表示 真假情况


boolean isVIP = true; 

boolean isMarried = false;

System.out.println( isVIP  );
System.out.println( isMarried  );

boolean 数据类型 只有两个取值 true 与 false

2.2.8 char

表示单个字符,赋值方式有如下

// 1. 使用单引号赋值
char m1 = '中';  
System.out.println( m1  );

直接赋值 使用单引号

// 2.编码赋值: 1071  =  去开黑  1000 去洗脚    ASCII 编码 收录了128个字符
char m2 = 65;
System.out.println( m2  );

ASCII 编码赋值

//3.Unicode编码赋值   常见编码:GBK 中文 BIG5 大五  Unicode (统一编码)
char m3 = '\u6881';
System.out.println( m3  );

Unicode 统一编码,支持所有国家地区符号

// 4.转义符赋值  转义符,改变原有含义,表示一些特殊字符
char m4 = '\\' ;
System.out.println( m4  );
System.out.print("hello" );
System.out.print('\n' );
System.out.print("world" );

特殊符号使用 转义方式赋值,编译器不检查个数而是判断转义符 对应的实际字符。

2.3 String 类型

表示多个字符的集合

String name = "康康";
System.out.println(name);

String 是引用数据类型,它不是基本数据类型,一定要记住! 注意 使用 双引号赋值。

2.4 类型转换
  • 自动类型提升
  • 强制类型转换
public static void main(String[] args){
   // 自动类型提升,安全的,自动完成无需干预。
   byte b1 = 100;
   int  m1 = b1; 
   System.out.println(m1); 	

   // 强制类型转换,不安全的,手动完成。
   int s1 = 10;           //00000000 00000000 00000000 00001010
   // A a = (A)b ;
   byte s2 = (byte)s1;    //00001010
   System.out.println(s2); 

   double pi = 3.14;
   int mm = (int)pi;
   System.out.println(mm); 
   // 用高精度变量 存放 低精度的变量或数值,自动类型提升。
   // 用低精度变量 存放 高精度的变量或数值,需要强制转换。		
   // byte -> short -> int -> long -> float -> double   
   // 箭头右边变量 ,可以直接保存左边的变量,反之需要强转。
}
2.5 控制台输入

从键盘上输入数据赋值给变量

  1. 导包
import java.util.Scanner; 
  1. 创建对象
Scanner sc = new Scanner( System.in );
  1. 调用方法
System.out.println("输入一个数");
int m1 = sc.nextInt();

完整用例:

import java.util.Scanner; // 引入输入工具类,俗称导包。
public class InputDemo{
    public static void main(String[] args){
        //创建一个输入工具对象
        Scanner sc = new Scanner( System.in );
        // 从键盘读一个 整数 int ,保存到m1变量中
        System.out.println("输入一个数");
        int m1 = sc.nextInt();
        System.out.println("输入一个数");
        int m2 = sc.nextInt();
        System.out.println("您刚刚输入的是:"+m1+","+m2);
        //从键盘上读一个小数 
        System.out.println("输入一个数");
        double d1 = sc.nextDouble();
        System.out.println("输入一个数");
        double d2 = sc.nextDouble();
        System.out.println("您刚刚输入的是:"+d1+","+d2);
        // 从键盘读一个字符串
        System.out.println("输入一个名字");
        String myName =  sc.next();
        System.out.println("你好!"+myName);
    }
}

常用方法 整数 :nextInt() 浮点数: nextDouble() 字符串:next()

第三节、运算符

一系列运算符号。

3.1 赋值运算符

符号: =

int age = 100;

int money;
money = 200;

把等号 右边的变量值或数据 赋值给 等号左边的变量。

3.2 算术运算符

符号:+ - * / %模

public static void main(String[] args){
		int  a = 5;
		int  b = 2;
		int c = a+b;
		System.out.println(c);
		
		System.out.println(a+b);
		System.out.println(a-b);
		System.out.println(a*b);
		System.out.println((double)a/b);
		System.out.println(a%b);
}

注意:除法运算结果精度参考参与数的最高精度。如果参与数都是整数结果会砍掉小数。

算术运算符运算结果: 数值。

3.3 关系运算符

符号 > < >= <= == !=

public static void main(String[] args){
		
		int a = 10;
		int b = 14;
		
		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 );
	}

类似 >= 符号中间没有空格

关系运算符运算结果为:boolean 值

3.3 逻辑运算符

符号:&& || !

运算法则: && 同真则真,一假则假 || 一真则真 同假则假 !取反

public static void main(String[] args){

    boolean hasIDCard = false; 

    int money = 10;

    // 要求 成人+网费
    //System.out.println(  hasIDCard==true &&  money>=5      );

    // 要求 要么成人 要么有钱
    //System.out.println(  hasIDCard==true ||  money>=5      );

    //System.out.println(  !(10>100)     );
}

用于连接多个条件

逻辑运算符运算结果为:boolean 值

3.4 复合赋值运算符

符号:+= -= *= /= %=

public static void main(String[] args){
		/*
		 int sal = 8000;
		 int newSal = sal + 2000;
		*/
		/*
		int sal = 8000;
		sal = sal + 2000;
		*/
        int sal = 8000;
		sal += 2000;
		System.out.println(sal);
		
		sal-=1000;
		System.out.println(sal);
		
		sal*=2;
		System.out.println(sal);
		
		sal/=2;
		System.out.println(sal);
		
		sal%=2;
		System.out.println(sal);	 
}

用于在现有变量基础上做算术运算符并赋值,简化运算和赋值。

3.5 自增自减

符号: ++ --

1. 符号可以位于 操作数前或者后面。
    
2. 无论在前或在后,只要执行完成,操作数要么+1 要么 -1。也就是说在前在后对对操作数讲影响是固定的。
    
3. 在前在后对于 表达式 的影响是有区别的,在前:先运算再赋值, 在后,先赋值再运算。

int a = 10;
 a++; // ++a
sout(a);// 11

int m = 10;
// System.out.println( m++ ); // 10   ①
// System.out.println( ++m ); // 11   ②
分别运行 ① ② 观察到结果。    

在自身基础上 +1 或 -1

3.6 位运算符(了解)
&按位与   |按位或  ^异或  按位取反~  左移<<  右移>>  无符号右移>>>
public static void main(String[] args){
		int n = -10; // 0000 1010
		int m = 2;  // 0000 0010
		//               
		// 按位与: 二进制位同1 则 1  其他为0 
		
		//System.out.println( n&m );
		
		// 按位或: 二进制位有1 则 1    
		//System.out.println( n|m );
		
	  	// 按位异或: 二进制位 相同为 0 不同为 1   
		//System.out.println( n^m );
		
		// 按位异或: 二进制位 逐位取反 
		//System.out.println( ~n );
		
		//移动过程中不保留负数符号位。
		//System.out.println(n>>>1);
		 
}
3.7 其他

符号:exp?A:B

运算法则: 判断exp表达式的值 如果为true 则取值A 否则取B

public static void main(String[] args){

    Scanner sc = new Scanner(System.in);

    //输入一个数据
    System.out.println("输入一个数据[1-5]");
    int level = sc.nextInt();

    String grade = level==5?"王者":  level==4?"钻石": level==3?"黄金": level==2?"白银":level==1?"青铜":"非法输入";
    System.out.println(grade);
}

img

[]  ()  .  其他特殊运算符。
第四节、流程控制

流程控制的作用是去组织程序代码,可以使程序安装一定的顺序进行执行,几乎所有的编程语言都具备这样的能力,同时基本分为三大种控制结构 顺序 选择 循环:

4.1 顺序结构
  • 顺序结构

它是程序的最基本的结构,从上到下,按照代码的编写顺序依次执行。

System.out.println("hello");
System.out.println("world");
4.2 分支结构
  • 选择分支结构

选择性执行某些代码,当条件成立时执行某些代码,不满足则不执行某些代码。

  • IF 语句

if( 条件表达式 ){

条件成立才执行的语句;

}

public static void main(String[] args){

    int dx = 100;  //大象的单位
    int max = 20; //冰箱存储的极限单位

    System.out.println("打开冰箱门");
    if( dx <= max   ){
        System.out.println("放大象");
    }
    System.out.println("关闭冰箱门");
}

大象 放冰箱案例

  • IF-ELSE 语句

if( 条件表达式 ){

条件成立才执行的语句;

}else{

条件不成立才执行的语句;

}

class LeapDemo{
	public static void main(String[] args){
		//创建一个输入对象
		Scanner sc = new Scanner(System.in);
		
		System.out.println("输入一个年份");
		int year =  sc.nextInt();
		
		//判断
		if(  (year%4==0 && year%100!=0)  || (year%400==0)  ) {
		    System.out.println(year+"是一个闰年");
	    }	 
		else {
			System.out.println(year+"是一个平年");
		}	 
	}
}

输入年份 判断闰年 平年案例

  • IF-ELSE-IF

if( 条件表达式A ){

条件A成立才执行的语句;

}else if(条件表达式B){

条件B成立才执行的语句;

}else{

以上条件不成立才执行的语句;

}

public static void main(String[] agrs){
    Scanner sc = new Scanner(System.in);
    //输入以前的工资
    System.out.println("输入你目前的工资");
    int oldSal = sc.nextInt();

    System.out.println("输入你目前的职位【 1普工  2主管  3经理  】");
    int job = sc.nextInt();

    if(job  == 1 ){
        oldSal = oldSal+100;	
    }else if( job == 2){
        oldSal = oldSal + 500;
    }else if( job == 3  ) {
        oldSal = oldSal + 1000;
    }else{
        System.out.println("输入有误");
    }
    //输出		
    System.out.println("调薪后您的薪水为:"+oldSal);
}

根据岗位 调整工资案例

  • IF 嵌套

在IF 的内部可以 再使用IF结构,内部的IF 外部成立才执行。

class GKDemo{
	
	 public static void main(String[] args){
		
		 Scanner sc = new Scanner(System.in);
		 
		 System.out.println("请输入一个分数");
		 int socre = sc.nextInt();
		 
		//合法输入
        if(  socre>=0 && socre<=750  ){
			 //判断条件
			 if( socre >=550   ){ 
				  System.out.println("恭喜,您的分数可以报一本院校");
			 }else if(  socre>=500  ){
				  System.out.println("恭喜,您的分数可以报二本院校");
			 }else if( socre>=480 ){
				  System.out.println("恭喜,您的分数可以报三本院校");
			 }else if( socre>=400 ){
				  System.out.println("恭喜,您的分数可以报专科院校");
			 }else{
				  System.out.println("恭喜,放牛!");
			 }
		}else{
			System.out.println("非法输入");	
		}		
	 }
}

根据 分数查询 可以报考学校

  • switch-case

语法

switch( 变量 ){

case 值A: 语句;break;

case 值B: 语句;break;

......

default: 语句;

}

判断变量的值与case是否相等,如果相等则执行该case后的语句,一般每个case配有break退出switch结构。 如果都不相等,如果有default则执行default后的语句,default可选。

case 穿透: 如果一个case后缺省了break,那么程序会依次往下继续执行,不考虑与case是否匹配,直到执行到break才退出switch。

class EatDemo{
	
	 public static void main(String[] args){
		 
		 //输入对象
		 Scanner sc = new Scanner(System.in);
		 
		 System.out.println("输入星期几?【1-7】");
		 int day = sc.nextInt(); 
		 
		 switch( day  ){   支持 int short  char String(jdk1.7) enum枚举
			
			case 1: System.out.println("吃馍");
			        break;
			case 2: System.out.println("吃面");
			        break; 
			case 3:  
			case 4:  
			case 5: System.out.println("盐煎肉");		
			        break;		
			case 6: System.out.println("烧烤");		
			        break;	  
			case 7: System.out.println("泡面");		
			        break;	 
			default: System.out.println( "输入有误!" ); 		
		 } 
	 }
}

食谱案例

4.3 循环结构

重复执行某些语句。

  • while

while( 条件表达式 ){

循环执行的语句

}

当条件满足时,执行循环体中语句,语句执行完成后,再次判断条件,周而复始,直到条件不满足退出。

class WhileDemo{
	public static void main(String[] args){		
		//定义一个变量 计数器的功能
		int count = 1;
		while(  count <= 10  ){
   		    System.out.println("我是最棒的!"+count);
			// 当循环执行完一次计数 加1
			count++;
		}	
	}
}

案例 计算100内数字和

class SumOfNumDemo{
	public static void main(String[] args){
		int sum =0;
		int n = 1;
		while( n<=100  ){
			//把循环变量 累计到 sum上
			sum = sum + n;
			n++;
		}
		System.out.println( sum );
	}
}

案例1 水仙花数

class FlowerNum{
	 public static void main(String[] args){
       	//假设一个数	
		int m = 100;
		while( m <1000 ){
			//分解这个三位数
			int b = m/100;
			int s = m/10%10;
			int g = m%10;
			//判断这数是否满足水仙花数规则
			if( m == ( b*b*b + s*s*s + g*g*g )  ){
				System.out.println(m+"是一个水仙花数");
			}
			//找下一个
			m++;
		}
	 }
}
  • do-while

do{

循环执行的语句

}while( 条件表达式 );

现在执行 循环体,执行完后再判断条件是否满足,如果满足继续执行,周而复始,不满足则退出。

class DoWhileDemo{
	 
	public static void main(String[] args){
		int n = 0; 
	    do{
		  if( n%3==0 && n%5!=0  ){
			  System.out.println(n);
		  }	
		  n++;	
		}while( n<100);	 
	}
}

案例 找 100内能被 3整除 不能被5整除的数

  • for 循环

for( 初始化变量 ; 循环条件 ; 迭代 ){

循环语句;

}

基础用法

class ForDemo{
   public static void main(String[] args){
   	 /* 死循环
   	 for(;;){
   		System.out.println("我没有闪!"); 
   	 }
   	 */
   	 for( int i = 100  ;  i<10   ; i++   ){
   		 
   		 System.out.println("我没有闪!"+i);
   	 }
   	 System.out.println("over");
   }
}

案例: 登录,模拟错误重复登录3次

class ForDemo2{
	public static void main(String[] args){
		Scanner sc = new Scanner(System.in);
		for(int i=0;i<3;i++){
			System.out.println("账号");
			String name =  sc.next();
			
			System.out.println("密码");
			String pwd  =  sc.next();
			
			if( name.equals("admin") && pwd.equals("123")  ){
				System.out.println("登录成功");
			    break; // 立即退出循环
			}else{
				System.out.println("信息有误");
			}  
		}
	}
}
  • break 与 continue
class BreakAndContinueDemo{
	public static void main(String[] args){
		//模拟一个人的一生
		for(int i=0;i<100;i++){
            if( i==50 ){
				break;  //  结束当前循环(所在循环)
				// continue;//  跳过本次循环,立即进入下一次循环,忽略本次循环后续语句
				//return;   //  立即结束所在函数
			} 
            System.out.println( "今年"+i+"岁");	
		}
		System.out.println("gg");
	}
}
第五节、开发工具
5.1 介绍

开发工具通常使用集成开发环境,提升开发效率,在Java领域比较有代表的 Eclipse (早期非常),IDEA(目前流行)

  • Eclipse
  1. 开源免费
  2. 不够流畅,经常卡死,内存需求小。
  3. 基于插件来扩展功能, 其中myeclipse就是用 通过对Eclipse安装插件来扩展web开发。
  • IDEA
  1. 收费软件
  2. 内存开销大,流畅,界面友好
  3. 有丰富的插件。
5.2 eclipse 开发工具

体验Eclipse 软件:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-MbL21SIu-1606822094333)(E:\xa-2010\day4\笔记\image-20201120113201063.png)]

5.3 Idea 开发工具

安装:获得安装包,解压到指定目录即可

创建:Create New Projcet => 选Java => Next => 填写项目名

体验IDEA

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-RJD1PHoG-1606822094334)(E:\xa-2010\day4\笔记\image-20201120120707460.png)]

5.4 Idea 工具配置
  • 切换项目

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-kjZsNs8Q-1606822094336)(\image-20201120144240628.png)]

  • 隐藏 多余的文件和目录

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-JHnQPPe2-1606822094338)(\image-20201120144150700.png)]

  • 设置字体

    a) 界面字体大小

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Ci1EnhqW-1606822094341)(\image-20201120143832962.png)]

​ b) 代码字体大小

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-VFoJyLrB-1606822094342)(\image-20201120143939603.png)]

  • 插件安装

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-10L8cE3S-1606822094343)(\image-20201120144452087.png)]

  • 导入和打开项目

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-9psVlsjW-1606822094344)(\image-20201120150049944.png)]

第六节、函数与方法
6.1 基本概念

基本概念: 实现特定功能的一段代码,可以重复使用。

6.2 定义语法

定义语法:

public static 返回值类型|void 自定义方法名([数据类型 变量名,...]){

若干语句;

[return value]

}

参数列表: 定义函数执行期间需要的变量,可以定义0个或多个,定义时没有具体值,只有类型,方法调用时为其赋值,称为形参。

返回值类型:用于规此方法,返回数据的类型,必须要一致,如果函数不需要返回值,声明为 void。

{ }函数体 :装函数的实现逻辑代码

返回值 [return value]:如果返回值类型为void,就没有return。如果返回值有具体类型,这必须有return, 如果有返回值类型的函数 内部有分支,一定要保证,每个分支都有return 覆盖。

6.3 函数示例

定义一个 没有参数 没有返回值

public static void chineseSayHello(){
    System.out.println("你好!");
    System.out.println("我是渣渣辉");
}

定义一个有参数, 没有返回值

    public static void sumOfNum( int n  ){
        int sum =0;
        for(int i=0 ; i<=n ; i++){
            sum += i;
        }
        System.out.println("sum:"+sum);
    }

定义一个有参数 有返回值

public static String choujiang(int price){
        if( price >= 10 ){
            Random rd = new Random();
            //随机编号
            int i = rd.nextInt(10);
            //奖品名字
            String pjName="无";
            //匹配奖品
            switch (i){
                case 0: pjName="冰箱";break;
                case 1: pjName="娃娃";break;
                case 2: pjName="电视";break;
                case 3: pjName="洗衣机";break;
                default:pjName="谢谢惠顾";
            }
            //返回
            return pjName;
        }else{
            return "需要10元";
        }
}
6.4 函数调用

函数调用,目的是使用定义好的函数功能,调用函数需要遵循调用规则。调用函数时,会把实参 赋值给 形参

要求实参的个数 类型 顺序 和形参一致,然后进入调用函数中,执行其中的代码语句,此时形参才有值。

调用语法

[类型 变量名=] 函数名([实参,...])

  1. 调用 没有返回值的函数

函数名([实参,…])

sumOfNum(100);

如果有参数需要给实参。

  1. 调用 有返回值的 函数

接收变量 = 函数名([ 实参,… ])

String jp = choujiang(10);
System.out.println(jp);

需要使用变量接收返回值 , 如果有参数需要给实参。

函数调用实例

package p1;

public class MethodPractice {

    public static void main(String[] args) {
        double result  = area(10);
        System.out.println(result);

        double result2 =  length(100,50);
        System.out.println(result2);

        boolean result3=  isPrime(10);
        System.out.println(result3);

        int count = countPrime(2,100);
        System.out.println(count);
    }

    // 定义一个函数  计算  圆的面积并返回结果。
    public static double area( double  r ){
        double mj = 3.14*r*r;
        return mj;
    }
    // 定义一个函数  计算  长方形的周长 并返回结果。
    public static double length( int c , int k ){
        double zc = 2*(c+k);
        return  zc;
    }
    // 定义一个函数  统计 指定区间 质数的个数。
    public static int countPrime(int a, int b){
        int sum = 0;
        for(int i=a; i<=b; i++ ){
            // 检查这个i是不是质数,有一个现成的函数
            boolean xx= isPrime( i );
            if(xx){
                sum++;
            }
        }
        return sum;
    }
    //辅助函数 , 判断一个数是否为质数
    public static boolean isPrime( int n  ){
        boolean isPrime = true;
        for(int i=2;i<n;i++){
            if(n%i==0){
                isPrime = false;
            }
        }
        return  isPrime;
    }
}
6.4 return 特殊用法

通常情况,return 只会出现在有返回值声明的函数中,其作用就是返回一个数据。特殊的,return 出现在void 声明的函数中,也是可以的,但是不同用于返回一个数据,其作用是结束方法执行。

public static void inputNum(int n){
        if( n<100 || n>999 ){
            return;
        }
        //100行的功能逻辑
        System.out.println("这个三位数"+n+"好棒!");
}
6.6函数调用流程

从宏观看,调用一个函数,就会去执行函数中的语句,同时如果有参数的话,会把实参赋值给形参,当被调用函数中所有语句都执行完毕,这函数调用完成,程序回到调用出,继续往下一次执行。

从内存看,调用一个函数,会想线程栈中,压一个方法栈帧( 有局部变量表,方法出口 )当方法中的全部语句执行完毕,则移除栈帧,方法调用完毕。

6.7 递归

方法内部调用自身的一种行为。可以解决有规律且重复的问题,问题在于解决问题的方法就是本身,使用递归代码更精炼。

6.8 函数运用举例
package p2;
import javax.swing.JOptionPane;
public class Test {
    public static void main(String[] args) {
        // void showMessageDialog(null,String msg)  输入消息
        JOptionPane.showMessageDialog(null,"我是一个对话框");

        // String  showInputDialog(String msg)  输入对话框
        String name =  JOptionPane.showInputDialog("输入名字");
        System.out.println(name);

        //  int parseInt(String n)  把String 转 int
        String age =  JOptionPane.showInputDialog("年龄");
        int myage =   Integer.parseInt( age );
        System.out.println(myage+100);
        
    }
}
第七节、数组
7.1 概念

用于保存一组长度固定类型相同的变量集合。

7.2 定义数组
数据类型[]  数组名 = new 数据类型[长度]
示例:
int[] arr  =  new  int[5];    
示例:
double[] brr = new double[10];
示例:
String[] crr = new String[6];

数组是引用数据类型,占用两块空间,new 关键字的作用是去堆内存中去申请连续空间。

7.3 数组声明有初始化

数组也是变量,也可先声明,再实例化。

声明语法:
数据类型[] 数组名;
int[] arr;

实例化语法:
数组名 = new 类型[长度];
arr = new int[100]
7.4 元素访问

数组中的每个空间成为元素,对数组的每个空间存值或者取值叫做元素访问。数组元素访问,需要依靠下标完成,数组一旦实例化,下标就有了,从0开始 到数组 长度-1 ,如果使用超出范围的下标,将引发 ArrayIndexOutOfBoundsException 异常。数组的元素个数可以通过 数组名.length 来获得。

int[] arr = new int[4];
arr[0] = 1;
arr[1] = 2;
arr[2] = 3;
// 可以看见 数组有4个空间,所以有4个元素,通过下标为每个元素空间赋值。

System.out.println(arr[0]);
System.out.println(arr[1]);
System.out.println(arr[2]);
// 可以看见 通过变换下标,把每个元素都输出。
7.5 数组元素遍历

通常,数组的元素下标是连续变化的,这一点恰好可以联系到循环,可以使用循环的计数器来充当下标,这样就可遍历出数组的全部内容。

int[] arr = new int[4];
arr[0] = 1;
arr[1] = 2;
arr[2] = 3;
// 可以看见 数组有4个空间,所以有4个元素,通过下标为每个元素空间赋值。

/*
System.out.println(arr[0]);
System.out.println(arr[1]);
System.out.println(arr[2]);
*/
// 可以看见 通过变换下标,把每个元素都输出。
for(int i=0;i<arr.length;i++){
   System.out.println(arr[i]);
}
7.6 基本数据类型与引用数据类型

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-u0D7Z5vi-1606822094346)(\image-20201124095340194.png)]

java 中基本数据类型与引用类型在内存分配上的区别

值传递 VS 地址传递

1. 基本数据类型为值值传递 , 引用数据类型为地址传递。
2. 数组类型可以 设计为函数的参数 和返回值
        记住: 数组参数,接收的是 实参数组的地址     数组返回值,返回的是数组的地址。
3. 数组的扩容:
       1. 手动 , 对应下标赋值
       2. System.arrayCopy(原数组,原数组起始下标,新数组,新数组起始下标, 拷贝个数)
       3. Arrays.copyOf(原数组,新数组的长度 ) 返回了新的数组,需要接收。
4. 可变参数:
       函数名(数据类型... 参数名){
            //使用参数,当做数组使用即可
       }
5. Arrays.toString(数组)返回字符串       
7.7 数组排序
  • 冒泡
// 冒泡 排序:
    /*
    * 思想: 两两比较,把较大的往后交换。全部元素比较完毕为1趟,选出了一个最大的。 ,[8 7 6 5  4  3  2  1  9 ]
    *       重复以上步骤,直到全部排好。                                        [7 6 5 4  3  2  1  8  9 ]
    *       有多少趟? 基本有元素个数决定  比如10 需要 9
    * */
    public static void maopao( int[] arr ){
        //完成排序逻辑
        for(  int i = 0; i < arr.length - 1 ; i++    ){ //控制趟
            //嵌套内循环
            for(int j = 0;j < arr.length - 1 - i; j++  ){
                //两两比较大小
                if(  arr[j] > arr[j+1] ){
                     //交换
                     int temp = arr[j];
                     arr[j] = arr[j+1];
                     arr[j+1] = temp;
                }
            }
            //System.out.println(  "第"+i+"趟:"+ Arrays.toString(  arr)    );
        }
    }


  • 选择排序`
 // 选择 排序:
    /*  {1,10,32,56,21,36,9,45,22,67,30}
    * 思想: 先假设出最小值,为当前趟数对应下标值,然后依次和其他未元素进行比较,如果发现存在更小的元素,记录下这个最小值的下标。
    *        一趟结束后观察  min 下标有无变化,有变化则交换 无则不管。
    * */
    public static void choose(int[] data ){
        for(int i=0;i<data.length;i++){ // 控制趟数。
            //假设当前趟数出的元素就是最小的
            int min = i;
            //用假设的这个元素 依次和后续元素比较。
            for(int j=i+1; j<data.length;j++){
                if( data[min] > data[j]  ){
                    min = j; //如果有更小的记录下标
                }
            }
            //观察是否有变化
            if(min !=i){
                //交换
                int temp = data[min];
                data[min] = data[i];
                data[i] =temp;
            }
        }
    }

  • JDK 工具排序
java.util.Arrays.sort(T[] arr)
7.8 二维数组
7.81 概念

二维数组,指的是一个数组元素的类型又是一个数组,数组的数组。

7.82 定义语法
数据类型[][]  数组名 = new  数据类型[高维长度][低维长度]
    
示例:
int[][] arr = new int[3][4]
    
int[][] brr = new int[3][]
    
//int[][] crr = new int[][3] 错误必须指定高维度长度,可以省  
    

静态初始化:
int[][] drr = { {1,2,3},{23,44},{123,456,789}  };      
7.83 二维数组使用案例
    public static void main(String[] args) {
       
        //使用二维数组保存 一个电话簿
        /*
            张三 , 13677612831 , 北京
            张三 , 13677612831 , 重庆
            张三 , 13677612831 , xxx
            张三 , 13677612831
            张三 , 13677612831
            张三 , 13677612831
            张三 , 13677612831
         */
        String[][] books = new String[10][3];
        Scanner scanner = new Scanner(System.in);
        //是否继续
        boolean isContinue = true;
        //指定保存的位置下标
        int index = 0;
        while( isContinue  ){
             System.out.println("输入联系人的3个信息");
             String name =  scanner.next();
             String tel = scanner.next();
             String addr = scanner.next();
             books[index][0] = name;
             books[index][1] = tel;
             books[index][2] = addr;
             //改变下标保证下次往后添加
             index++;
             //保存不下了
             if(index==books.length){
                 break;
             }
             System.out.println("是否继续添加yes/no?");
             String option  = scanner.next();
             isContinue =  option.equals("no")?false:true;
        }
        //输出
        for(int i=0;i<books.length;i++){
            System.out.println("名字:"+books[i][0] + "\t电话:"+books[i][1] + "\t地址:"+books[i][2] );
        }
    }
7.84 杨辉三角
public static void main(String[] args) {
         int[][] data = new int[10][10];
         //初始化杨辉三角数据
         for( int i=0; i<data.length;i++ ){
              for(int j=0;j<=i;j++ ){
                  //填值
                  //第1列 固定为 1  最后一列 固定为1
                  if(j==0 || j==i ){
                      data[i][j]=1;
                  }else{
                      // 当前元素为  正上方元素 与 正上方前一个元素的和
                      data[i][j] = data[i-1][j]+ data[i-1][j-1];
                  }
              }
         }
         //遍历输出
         for (int i=0;i<data.length;i++){  // 10 -i =
             // 打印空格
             System.out.format("%"+ (10-i)*2 +"s","");
             //  打印数字
             for(int j=0;j<=i;j++){
                 System.out.format("%4d", data[i][j] );
             }
             System.out.println();
         }
}
第八节、面向对象

OOP(Object Oriented Programming) 面向对象的程序设计,指的是一种编程思想(思维),相较于面向过程,面向对象对功能的设计有一定简化面向对象,不关注问题细节实现本身, 是一种把业务功能实现委派个某些对象来实现,我们的关注点是对象。

面向过程:(Procedure Oriented)面向过程的程序设计思想,关注的是功能实现的具体细节。

以生活为例 区别两种编程思想:

理发:
Procedure Oriented: 1.找到头, 2.找推子,3 选发型,4剪.....  
Object Oriented Programming: 找Tony...

面向对象与面向过程并不冲突,而是互补,面向对象中对象的方法逻辑就是面向过程的思想。

8.1 基础概念
  • 对象

一个切客观存在的事物都可以视为对象,对象拥有具体的特征和行为。

类是一组具有相同或相似事物的统称,用于定义对象的共性属性和行为。

  • 类对象关系

类是对象的模板,对象是类的具体实例。

8.2 定义类
package com.qfedu;
/**
 * 定义一个类,程序员类(定义所有程序员对象的共同特性和行为,关注共性!!!!!)
 */
public class Coder {
    // 特征 : 属性, 变量(实例的变量)
    String name;
    int    age;
    String adrr;

    // 行为: 方法
    public  void coding(){
        System.out.println("敲代码中.....");
    }
    public  void eat(){
        System.out.println("干饭中.......");
    }
    public  void sayHello(){
        System.out.format("大家好! 我是来自%s的%s今年%d岁了\n", adrr,name,age);
    }
    public void study() {
        System.out.println("打开电脑");
        System.out.println("http://www.baidu.com");
        System.out.println("学习中.......");
    }
}
8.3 创建对象

面向对象编程,关注点为对象,所以需要先通过类来实例化对象,然后使用对象的功能。

创建对象语法:

类名  对象名 = new  类名()
Coder obj = new Coder();

对象通过 点 . 访问属性和方法

public static void main(String[] args) {
    Coder obj = new Coder();
    obj.name = "雷军";
    obj.age = 40;
    obj.adrr = "武汉";

    obj.sayHello();
    obj.eat();
    obj.coding();
}
8.4 实例变量

直接定义在类中,方法以外的变量为实例变量,实例变量是为每个实例声明的变量,通常设计类的时候用于描述该类事物特征。

public class Coder {

    // 特征 : 属性, 变量(实例的变量)
    String name;
    int    age;
    String adrr;

    // 行为: 方法
    public  void coding(){
        System.out.println("敲代码中.....");
    }

    public  void eat(){
        System.out.println("干饭中.......");
    }

    public  void sayHello(){
        System.out.format("大家好! 我是来自%s的%s今年%d岁了\n", adrr,name,age);
    }

    public void study() {
        System.out.println("打开电脑");
        System.out.println("http://www.baidu.com");
        System.out.println("学习中.......");
    }
}
8.5 实例方法

类中定义的实例方法,是由实例(该类的实例) 调用的方法,通常设计类的时候用来描述该类事物的行为功能。

定义语法:

修饰词  返回值类型  方法名( 参数列表 ){
    方法逻辑
}

class Teacher{
    
    //在类中定义实例方法
    public void teach(){
        System.out.println("今天来学习面向对象吧");
    }
    
}

实例方法 调用:

Teahcer obj = new Teacher();
obj.teach();
8.6 方法重载

当存在同一个行为可能有多种不同的实现方法时,通过方法重载机制,可实现多个方法使用相同的名字,通过参数来区分方法调用的效果,对代码的灵活性有显著提升。

方法重载要求:

  1. 同一个类中, 方法名相同。
  2. 参数列表不同(类型 个数 顺序 不完全相同)
  3. 与返回值类型,参数名字无关。
class Demo{
    // 计算  n 以内的整数和  sum(int n)
    public double sum(int n){
        int sum = 0;
        for(int i=0;i<=n;i++){
            sum += i;
        }
        return  sum;
    }
    // 计算  m  n 内的整数和 sum(int m, int n)
    public double sum(int m , int n){
        int sum = 0;
        for(int i=m;i<=n;i++){
            sum += i;
        }
        return  sum;
    }
}

class TestDemo{
    public static void main(String[] args){
       Demo obj = new Demo();
       double s1 =  obj.sum(10);   // 调用  public double sum(int n)
       double s2 =  obj.sum(10,20);// 调用  public double sum(int m , int n)
    }
}

调用重载方法,是通过给定的 实际参数 去匹配 最佳的方法执行。

8.7 构造方法

构造方法,又叫构造器,作用是创建对象,为属性赋初值。

特点:

  1. 没有返回值类型(注意不是写void)
  2. 构造方法名字 与 类名一致。
  3. 当没有自己编写构造方法时,系统提供一个默认构造方法(无参数)。
  4. 构造方法只能通过 new 触发调用,不可以使用句点调用。(this用法除外)
public class Student {
    //属性
    String name;
    int age;
    String sex;
    String major;
    //无参数构造器
    public  Student(){
        System.out.println("Student()");
    }
    //全参数构造器
    public Student(String sname, String ssex, int sage, String smajor){
        name =sname;
        age=sage;
        major = smajor;
        sex = ssex;
    }
}
8.8 构造方法重载

构造方法也是方法同样允许重载使用,一个类提供多种参数的构造器,方便后续创建对象时 有更多的初始化属性选择。

public class Student {
    //属性
    String name;
    int age;
    String sex;
    String major;
    //无参数构造器
    public  Student(){
        System.out.println("Student()");
    }
    public Student( String sname  ){
        name = sname;
    }
    public Student(String sname , String ssex){
        name = sname;
        sex =ssex;
    }
    public Student(String sname, String ssex, int sage, String smajor){
        name =sname;
        age=sage;
        major = smajor;
        sex = ssex;
    }
}

创建对象时,由参数去匹配 要使用哪个构造器。

8.9 this 关键字

this 是一个关键字,在类中无需声明直接使用,是一个引用,指向当前对象(谁调用就指谁),有两个作用。

  1. 在实例方法或者构造器中,用于区分实例变量和局部变量
// 有参构造器
public Movie(String movieName, String director, int time) {
    this.movieName = movieName;
    this.director = director;
    this.time = time;
}
  1. 调用本类构造器
public Movie(String movieName, String director ) {
    this.movieName = movieName;
    this.director = director;
}
// 有参构造器
public Movie(String movieName, String director, int time) {
    this(movieName,director);
    this.time = time;
}

因为构造方法不可以直接调用,通过this( ) 或者 this(参数) 调用,同时这种调用必须位于本构造器第一行。

8.10 类与类的关系
  • 依赖( 聚合 组合 )
  • 继承 (单独说)

每个类不应该是完全孤立,与类一般都会存在联系,如果一个类A使用到另一个类B,那么就说A依赖B.

比如:人打用手机打电话 。分析存在人对象 和手机对象 存在方法 拨号 通信

  • 聚合
package com.qfedu.day8;
/**
 * 定义一个手机类型
 */
public class Phone {
    //属性
    String name;
    int  ram;
    int  rom;
    String color;
    //构造器
    public Phone() {
    }
    public Phone(String name, int ram, int rom, String color) {
        this.name = name;
        this.ram = ram;
        this.rom = rom;
        this.color = color;
    }
    //实例方法
    public void call(String tel){
        System.out.println("正在呼叫"+tel);
    }
    public void message(String tel, String msg){
        System.out.println("发送"+msg+"给"+tel);
    }
    public void showProperties(){
        System.out.println("-------您手机的信息------");
        System.out.println("名字"+name);
        System.out.println("颜色"+color);
        System.out.println("内存"+ram+"GB");
        System.out.println("存储"+rom+"GB");
    }
}
package com.qfedu.day8;
/**
 * 定义一个人类
 */
public class Person {
    String name;
    String tel;
    //定义一个手机类型的属性
    Phone myPhone;

    public Person() {
    }
    public Person(String name, String tel) {
        this.name = name;
        this.tel = tel;
    }
    public Person(String name, String tel , Phone myPhone ) {
        this.name = name;
        this.tel = tel;
        this.myPhone = myPhone;
    }
    //实例方法
    public void callSomebody(  String tel  ){
          myPhone.call(tel);
    }
    public void sendMessage( String tel, String msg ){
          myPhone.message( tel,msg);
    }
}

package com.qfedu.day8;

public class TestPerson {

  public static void main(String[] args) {

      Phone phone = new Phone("华为MetaP40 Pro",8,128,"白色");

      Person p1 = new Person( "马生润","13672838283", phone );
      Person p2 = new Person( "小明","10086",null );
      Person p3 = new Person( "小东","10010",null );

      p1.callSomebody(  p2.tel   );
      p1.sendMessage( p3.tel,"你好啊");

  }
}
//  5岁的小明 开车10万的五菱MINI 去兜风
  • 组合

组合是也是一种聚合使用其他类,通常聚合的类可能存在多个,比如配一台电脑,可以组合各种配件。

public class Computer {

    // 显示器
    Screen screen;
    // 电源
    Power power;
    // 处理器
    Cpu cpu;
    // 内存
    Ram ram;

    public Computer() {
    }
    public Computer(Screen screen, Power power, Cpu cpu, Ram ram) {
        this.screen = screen;
        this.power = power;
        this.cpu = cpu;
        this.ram = ram;
    }
    // 显示属性
    public void displayInfo(){
        System.out.println("------------电脑配置---------------");
          ram.showProperties();
          power.showProperties();
          screen.showProperties();
          cpu.showProperties();
    }
}


其他类

//显示器
public class Screen {
    String name ;
    String size;
    String fbl;
    public Screen() {
    }
    public Screen(String name, String size, String fbl) {
        this.name = name;
        this.size = size;
        this.fbl = fbl;
    }
    public void showProperties(){
        System.out.println("显示器信息:"+name+", "+size+", "+fbl);
    }
}
//内存
public class Ram {
    String name;
    int  size;
    double hz;
    public Ram() {
    }
    public Ram(String name, int size, double hz) {
        this.name = name;
        this.size = size;
        this.hz = hz;
    }
    public void showProperties(){
        System.out.println("内存信息:"+ name+" ,"+size+"GB "+hz+"GHZ");
    }
}
// 其他类省略.......
第九节、面向对象三大特征

面向对象具备三大特性,分别是封装 继承 多态,几乎所有的所谓设计模式都是以此为基础。这些特征是面向对象语言所具备的,面向过程不支持此语法。

9.1 封装性
1 封装概念

隐藏对象内部细节,控制对象的修改访问权限。

2 封装实现方式

private 修饰符 ,在属性 和 方法前声明,表示此属性和方法为私有,只能在本类中访问。

为private 属性提供 公共访问方法。

案例

public class IGirl {
    //属性
    String name;
    private int age;
    int height;
    
    //set 赋值
    public void setAge(int age  ) {
        if (age < 0) {
            System.out.println("非法输入");
        } else {
            this.age = age;
        }
    }
    //get 取值
    public int getAge(){
        return this.age;
    }
}

public class TestGirl {

    public static void main(String[] args) {
        IGirl girl = new IGirl();
        
        //调用set方法赋值
        girl.setAge(-18);
        
        int age =   girl.getAge();
        System.out.println(age);
    }
}
9.2 继承
1 继承概念

两个类A,B存在 A is a B 关系,可以把共性属性和方法定义在B类中,通过继承原理,A类可以重用B类中的共性代码和属性。继承的思想是重用扩展,一个类可以通过继承获得 属性方法,同时也可以扩展出新的属性和方法。

2 继承语法

class A extends B{

}

这里 A 为子类 B为父类

3 继承举例

定义Animal 作为父类

public class Animal {
    //属性
    String name;
    int age;
    String gender;

    //构造器
    public Animal() {
    }
    public Animal(String name, int age, String gender) {
        this.name = name;
        this.age = age;
        this.gender = gender;
    }
    //实例方法
    public void eat(){
        System.out.println(name+"吃......");
    }
    public void sleep(){
        System.out.println(name+"睡......");
    }
}

定义子类

public class Dog extends Animal {
    public Dog() { }
    public Dog(String name, int age, String gender ){
        this.name = name;
        this.gender = gender;
        this.age = age;
    }
    public void  run(){
        System.out.println(name+"跑........");
    }
    public void  lookDoor(){
        System.out.println(name+"看门.......");
    }
}
public class  Bird  extends  Animal {
    public Bird() { }
    public Bird(String name, int age, String gender ){
        this.name = name;
        this.gender = gender;
        this.age = age;
    }
     public void fly(){
         System.out.println(name+"飞.......");
     }
}

编写测试类

public class TestAnimal {
    public static void main(String[] args) {
        Bird bird = new Bird("鹦鹉",10,"雌");
        //继承的方法
        bird.eat();
        bird.sleep();
        //自己独有的方法,扩展的方法
        bird.fly();

        Dog dog = new Dog("旺财",11,"雄") ;
        //继承的方法
        dog.eat();
        dog.sleep();
        //自己独有的方法,扩展的方法
        dog.lookDoor();
        dog.run();
    }
}
鹦鹉吃......
鹦鹉睡......
鹦鹉飞.......
旺财吃......
旺财睡......
旺财看门.......
旺财跑........
4 单继承性

Java中,类是单继承的,一个类最多一个直接父类,但是可以支持多级继承比如A 继承B ,B继承C。

class A {
    int a;
    public void ma(){
        System.out.println("ma()");
    }
}
class B extends A {
    int b;
    public void mb(){
        System.out.println("mb()");
    }

}
class C extends B {
    int c;
    public void mc(){
        System.out.println("mc()");
    }

}

public class TestExtends {

    public static void main(String[] args) {
        C obj = new C();
    }

}

C 类可以 访问 a b c 三个属性 ma mb mc 三个方法。

5 不可继承内容

一个类继承另一个类后,并不是全盘继承父类全部内容,有些内容是不可以继承的比如

1 构造器 不可继承

构造器是构造当前类对象的方法,要求与类同名,子类无法继承父类的构造器来当自己的构造器,子类必须自己定义本类的构造器。

2 私有属性 不可继承

父类的私有属性,由于封装性问题,只能在父类本类中使用,子类无法直接继承使用。

3 父类中default 属性和方法 子类在非同包 不可继承。

由于default 的访问性质,极限是同胞,跨包无法访问,故子类不可直接继承使用。

6 访问修饰符

java 中提供了 3个关键字,共4种访问级别控制:

  • private

    表示私有 ,被他修饰的属性 方法 为私有, 只能在本类中访问。

  • default

    属性方法前,不写!!!!!!访问修饰符 表示默认,只能同包访问。

  • protected

    表示 受保护, 兼容 default 性质, 同时扩展了 异包子类可访问。

  • public

    表示公开, 任意位置可以访问。

总结:private -> default -> protected -> public 访问级别从严到宽。

7 方法重写

当 子类重父类继承到方法,但是继承来的方法并不使用,或者并不能达到子类的要求,此时,子类可以对方法内容重新编写实现,这个行为 称为方法 重写 或者 重载

具体要求:

  1. 子类 重写方法时,要求 签名一致 (返回值 方法名 参数列表)
  2. 子类 重写方法是, 要求 访问权限 不能更严。

可以在 重写的方法上使用 @Override 注解 ,来检测重写语法的正确性。

//父类
public class Teacher {
    public void teach(){
        System.out.println("上课......");
    }
}
//子类
public class EnglishTeacher extends Teacher {

    // 重写方法
    @Override
    public void teach() {
        System.out.println("hello");
    }
}
8 继承中对象创建过程

在存在继承的体系关系中,创建子类对象,比先创建父类对象,简单理解就是一个完整的子类对象中,包含一个父类对象实例,这个实例一般在子类中通过super访问。请思考几个问题?

问题1:为什么要创建子类对象?

答: 因为子类需要继承父类的实例变量,二实例变量必须存在实例,才会存在,所以必须以一个父类的实例来承载实例变量空间,从而被子类继承并使用。

问题2:什么时候创建的父类对象?

答: 在子类的构造器中,第一行代码默认会去调用父类的无参构造**【调用方式super()】** 写不写都有。当然也可调用父类有参构造。

9.super关键字

super 关键字是一个关键字,可以在子类中直接使用,表示的是子类对象空间中的那个父类对象引用。super 存在两个作用:

  1. 可以用来区分 父类和子类中同名的实例变量和方法

使用 super.属性名 或者 super.方法名

  1. 可以用来 调用父类构造器,用户初始化从父类继承来的那部分属性(尤其是在父类属性被私有化时)。

super() 或者 super(参数)

在子类构造方法中 使用super() 或者 super(参数) 务必保证调用位于当前构造器的第一行

9.3 多态
1 概念

多态是,面向对象三大特征中的最后一个特征,语法很简单,实际上只是一种用法。 总结一句话就是, 父类类型的引用可以指向任何子类对象。

Animal animal = new Dog();

Animal animal = new Cat();

这里 Dog 和 Cat 都是 Animal 的子类。所以多态是建立在继承之上的一种特性。没有继承就没有多态。

2 编程现象

一旦使用多态用法,那么通过父类类型的引用就只能调用 在父类中声明的属性和方法, 子类特有的方法无法调用

这样的好处是,屏蔽了各种子类的不同点。通过多态,只能观察(调用)到子类的共同行为。

public static void main(String[] args){
      Person person = new Student("小红",20);
      //可以调用Person父类中定义的方法
      person.eat();
      person.sleep();
      person.sayHello();

      //不可调用 子类特有的属性和方法 ,编译看左边,运行看右边
      //person.lookAll(); 
      //person.study();
}

这里 Student 是 Person 的子类。

3 多态的应用场景

多态通常就有两个应用场景,这并不是直接体现的,而是隐含体现的。

  • 父类类型做

    父类类型做参数,可以保证各种子类对象都可接收。

    //实例方法: 多态运用场景1, 父类类型作为参数,可以接受不同子类对象。
    public void travel(Transport transport, String start, String end ){
        System.out.println(age+"岁的"+name+","+job+"乘坐");
        transport.run(start,end);
    }
    

    这里 Transport transport 父类类型参数,使得 Subway对象 Car对象 AirPlane对象都可接收。

  • 父类类型做 参数类型

    返回值的类型为父类类型,这样可以使得方法可以返回 各种子类对象实例。

    //实例方法:多态运用场景2, 父类类型作为返回值类型。可以返回不同子类对象  
    public Food buy(){
        Food food = null;
        Random rd = new Random();
        int i =  rd.nextInt(3)+1;
        switch (i){
            case 1: food =  new Mo("肉夹馍");break;
            case 2: food =  new HotPort("桥头火锅");break;
            case 3: food =  new Beef("牦牛肉干");break;
        }
        return food;
    }
    

    这里 方法返回值类型为Food ,使得 Mo对象 Hotport 对象 Beef 对象都可返回。

3 类型转换
  • 自动类型提升

引用数据类型转换分为向上转型,向下转型,向上转型也叫自动类型提升,它就是多态的核心。简单的说就是可以直接把一个子类对象用父类类型的变量来保存。

Animal animal = new Dog();

这里 new Dog() 就是一个对象, 而这个对象被保存到一个 Animal的引用中。

  • 强制类型转换

把一个父类类型的引用 还原成它真实指向对象的类型的过程

Animal animal = new Dog();

Dog dog = (Dog)animal;

需要注意的是 务必保证 强转的合法性,因为父类类型引用只能转换成它真实指向对象的类型,如果不是会报错比如:

Animal animal = new Dog();

Cat cat = (Cat)animal;

这里将会引发 java.lang.ClassCastException 。因为 animal 这里真实指向的对象为 Dog 而不是 Cat,不能强转。

4 类型判断

因为强制类型转换存在安全性问题,所以强制转换前,需要提前判断使用 instanceof 关键字判断。

语法为 引用变量 instanceof 类型 如果前者是后者类型 返回true 否则 false

Animal animal = new Dog();

if ( animal instanceof Dog ){

​ Dog dog = (Dog)animal;

}

if ( animal instanceof Cat ){

​ Cat cat = (Cat)animal;

}

第十节、三大关键字
1. abstract 关键字

概念

abstract 意思为抽象的,可以来描述抽象的事物,和抽象的行为,在程序中也就是可以定义抽象类和抽象方法。

抽象类本质还是类,作用还是描述一类事物,只是这类事物比较抽象(某些行为,不够具体 很难实现)

抽象类成分

* 抽象类中可以定义什么呢?
*
* 定义属性
*
* 定义构造器
*
* 定义实例方法
*
* ...............
* 可以这么说,普通类有的成分它都具备,不能实例化本身的实例。

抽象类的意义

* 抽象类存在的价值?
* 1 . 可以作为父类使用,提取共性属性和行为。
* 2 . 可以建立多态使用方式

抽象方法

* 抽象方法:
* 一般在父类中,这个方法无法给出具体实现。抽象方法使用 abstract修饰,没有方法体。
*
* 特点:  1. abstract修饰,没有方法体。
*        2. 抽象方法所在类,必须是抽象类。
*        3. 继承抽象父类,必须重写全部的抽象方法,除非子类也是一个抽象类。

实例:

public  abstract    class Animal { //定义抽象类
    private String name;
    private int age;

    public Animal() {
    }

    public Animal(String name, int age) {
        this.name = name;
        this.age = age;
    }
    //省略gets/sets
 
    public abstract  void eat(); //定义抽象方法

}
public class Dog extends Animal {
    public Dog() {
    }
    public Dog(String name, int age) {
         super(name, age);
    }
    @Override
    public void eat() {           //重写抽象方法
        System.out.println("狗吃骨头......");
    }
}

public class TestAnimal {
    public static void main(String[] args) {
        Animal animal = new Dog("旺财",10);
        animal.eat();
        System.out.println(animal.getName()+animal.getAge());
    }
}
2 static 关键字

学习static 可以从以下 层次来。

  • 第一个层次

static 是一个关键字,可以修饰属性和方法,被static 修饰的属性和方法称为,静态属性和静态方法,区别于实例属性,静态属性,只有一份,通过类名访问。 同理静态方法也是通过类名直接调用。 总之静态属性和方法不依赖于对象。而是依赖于类。

class Foo{
    
    public static int num; //静态属性
    public static foo(){   //静态方法
       
    }
}
class Test{
    public static void main(String[] args){
        Foo.num=100; //通过类名 访问静态属性 
        Foo.foo();   //通过类名 访问静态方法
    }
}
  • 第二个层次

静态方法中,可以访问静态属性,静态方法。不可访问实例属性,和实例方法,以及实例相关的this super 关键字。

class Foo{
    public int age;        //实例属性
   
    public static int num; //静态属性
    
    
    public void   bar(){   //实例方法
         sout( age );  //可以
         sout( num );  //可以
    }
    public static foo(){   //静态方法
         //sout( age ); // 不可
         //bar()        // 不可
         //sout(this)   // 不可
         //sout(super)  // 不可 
         sout( num );

    }
}
  • 第三个层次

静态代码块,用于初始化静态属性的代码块,类加载时执行,一个类只加载一次,所以静态代码块,也只会执行一次。关于静态属性的初始化问题,根据赋值语句的先后顺序来判断。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-AWBxCPMn-1606822094349)(E:\xa-2010\day12\笔记\类加载过程.png)]

一个类加载后, 在准备阶段开辟了静态属性的空间,但是并不是立即赋值的。

static int age =10 ; 即便是写成一句话,也是分为两个阶段。

准备 : int age =0

初始化: age =10;

3 final 关键字

final 意为最终的,表示不可"更改"的含义,可以修饰 类,方法,变量(属性)。

修饰类,表示最终类:

final class Animal{

}

class Dog extends Animal{ //Error 会报错


}

使用final 控制一个类不可继承。 String 就是一个最终类。

修饰方法, 表示最终方法:

class Animal{
    public  final   void eat(){
        System.out.println("不知道怎么吃.....");
    }
}

class Cat extends  Animal{
    @Override
    public void eat() { //Error 会报错
        System.out.println("重写......");
    }
}

使用final 控制一个方法不可以被重写。

修饰变量(属性):

class Animal{

    final  int  leg ;

    public Animal() {
        leg=100;
    }

    public Animal(String name){

        leg = 1000;
    }
}

修饰属性,一定要保证,可以初始化到,赋值一次,赋值后不可修改。

public static void main(String[] args){
     final int a = 10;
     a = 100; //Error 会报错
}

修饰局部变量,只能赋值一次。

思考? abstract 可不可以与 private static final 关键字连用

不可以。矛盾。

4 附JVM内存分区图

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-4VxP0gtT-1606822094352)(E:\xa-2010\day12\笔记\jvm.jpg)]

this.name = name;
    this.age = age;
}
//省略gets/sets

public abstract  void eat(); //定义抽象方法

}
public class Dog extends Animal {
public Dog() {
}
public Dog(String name, int age) {
super(name, age);
}
@Override
public void eat() { //重写抽象方法
System.out.println(“狗吃骨头…”);
}
}

public class TestAnimal {
public static void main(String[] args) {
Animal animal = new Dog(“旺财”,10);
animal.eat();
System.out.println(animal.getName()+animal.getAge());
}
}


###### 2  static 关键字

学习static 可以从以下 层次来。

* 第一个层次

static 是一个关键字,可以修饰属性和方法,被static 修饰的属性和方法称为,静态属性和静态方法,区别于实例属性,静态属性,只有一份,通过类名访问。 同理静态方法也是通过类名直接调用。 总之静态属性和方法不依赖于对象。而是依赖于类。

```java
class Foo{
    
    public static int num; //静态属性
    public static foo(){   //静态方法
       
    }
}
class Test{
    public static void main(String[] args){
        Foo.num=100; //通过类名 访问静态属性 
        Foo.foo();   //通过类名 访问静态方法
    }
}
  • 第二个层次

静态方法中,可以访问静态属性,静态方法。不可访问实例属性,和实例方法,以及实例相关的this super 关键字。

class Foo{
    public int age;        //实例属性
   
    public static int num; //静态属性
    
    
    public void   bar(){   //实例方法
         sout( age );  //可以
         sout( num );  //可以
    }
    public static foo(){   //静态方法
         //sout( age ); // 不可
         //bar()        // 不可
         //sout(this)   // 不可
         //sout(super)  // 不可 
         sout( num );

    }
}
  • 第三个层次

静态代码块,用于初始化静态属性的代码块,类加载时执行,一个类只加载一次,所以静态代码块,也只会执行一次。关于静态属性的初始化问题,根据赋值语句的先后顺序来判断。

[外链图片转存中…(img-AWBxCPMn-1606822094349)]

一个类加载后, 在准备阶段开辟了静态属性的空间,但是并不是立即赋值的。

static int age =10 ; 即便是写成一句话,也是分为两个阶段。

准备 : int age =0

初始化: age =10;

3 final 关键字

final 意为最终的,表示不可"更改"的含义,可以修饰 类,方法,变量(属性)。

修饰类,表示最终类:

final class Animal{

}

class Dog extends Animal{ //Error 会报错


}

使用final 控制一个类不可继承。 String 就是一个最终类。

修饰方法, 表示最终方法:

class Animal{
    public  final   void eat(){
        System.out.println("不知道怎么吃.....");
    }
}

class Cat extends  Animal{
    @Override
    public void eat() { //Error 会报错
        System.out.println("重写......");
    }
}

使用final 控制一个方法不可以被重写。

修饰变量(属性):

class Animal{

    final  int  leg ;

    public Animal() {
        leg=100;
    }

    public Animal(String name){

        leg = 1000;
    }
}

修饰属性,一定要保证,可以初始化到,赋值一次,赋值后不可修改。

public static void main(String[] args){
     final int a = 10;
     a = 100; //Error 会报错
}

修饰局部变量,只能赋值一次。

思考? abstract 可不可以与 private static final 关键字连用

不可以。矛盾。

4 附JVM内存分区图

[外链图片转存中…(img-4VxP0gtT-1606822094352)]

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值