1.前言
1.1 计算机的基础知识
计算机(Computer)全称:电子计算机,俗称电脑。是一种能够按照程序运行,自动、高速处理海量数据的现代化智能电子设备。由硬件和软件所组成,没有安装任何软件的计算机称为裸机。常见的形式有台式计机、笔记本计算机、大型计算机等
1.1.1 计算机硬件
计算机硬件(Computer Hardware)是指计算机系统中由电子,机械和光电元件等组成的各种物理装置的总称。这些物理装置按系统结构的要求构成一个有机整体为计算机软件运行提供物质基础。
计算机通常由CPU、主板、内存、电源、主机箱、硬盘、显卡、键盘、鼠标,显示器等多个部件组成。
1.1.2 计算机软件
计算机软件是使用计算机过程中必不可少的东西,计算机软件可以使计算机按照事先预定好的顺序完成特定的功能,计算机软件按照其功能划分为系统软件与应用软件
系统软件: DOS(Disk Operating System), Windows, Linux, Unix, Mac, Android, iOS
应用软件:office QQ聊天 YY语言 扫雷
1.2 常用的dos指令
命令 | 操作符号 |
---|---|
盘符切换命令 | 盘符名: |
查看当前文件夹 | dir |
进入文件夹 | cd 文件名 |
推出文件夹命令 | cd … |
退出到磁盘根目录 | cd / |
清屏 | cls |
查看本机ip | ipconfig |
是否通信 | ping |
暴力删除 | rd /s /q |
询问是否删除 | rd /s |
创建文件夹 | copy con 文件名称 |
1.3Java一些相关历史
1.Java的诞生时间:1995年
2.java之父:詹姆斯高斯林
Java平台版本
1 javaSE:针对桌面应用程序和商务应用程序的解决方案
2 JavaME:针对嵌入式设备的一种解决方案
3 JavaEE:针对企业级开发环境的一种解决方案
1.4 Java的环境搭建以及PATH变量的配置
Java的环境搭建
JDK:JAVA的开发工具包,里面包含了jre和一些工具包
JRE:JAVA的运行环境,包含了一些核心类库
JVM:JAVA的虚拟机,所有程序的运行都得依靠JVM
path变量的配置
在此电脑—右键—属性---->高级系统---->环境变量---->系统变量
新建变量名:JAVA_HOME
变量值:Jdk安装目录的路径
2.编写HelloWorld
2.1程序编写步骤说明
开发环境搭建好后,我们就可以开始编写程序了
java程序开发的三个步骤:编写---->编译----->运行
2.2编写程序
calss HelloWorld{
public static void main(String[] args){
System.out.println("HelloWorld");
}
}
文件名要和类名保持一致,注意大小写
2.3编译java源文件
在DOS命令行中,进入Java源文件的目录,使用 javac 命令进行编译
javac 文件名.java
javac HelloWrold.java
2.4 运行java程序
在DOS命令行中,进入Java源文件的目录,使用 java 命令进行运行。
java 类名字
java HelloWorld
3.Java的基本语法
3.1关键字
- 关键字(keyword)
用做专门用途的字符串
特点:关键字中所有字母都为小写
class—定义类的
public—权限访问足够大
static —静态修饰符(共享/共用),讲面向对象中说
void —这些关键字— Java方法定义的格式
3.2 标识符
标识符(identifier)
Java 对各种变量、方法和类等要素命名时使用的字符序列称为标识符。
标识符的组成规则
1)可以是26个英文字母(大小写都可以)
2)可以是0-9的数字
3)可以是$或者_下划线
4)Java定义标识符:严格区分大小写注意事项
1)定义标识符(类名/接口名/方法名/常量/变量名):名字都不能以数字开头
2)定义标识符:起名字,不要出现Java中的关键字
3)起名字,做到四个字"见名知意"
3.3 变量
作用:用于在内存中保存数据
Java 定义变量的格式:数据类型 变量名 = 变量值;
eg:
public static void main(String[] args){
//变量的定义
int myAge = 12;
//变量的使用
System.out.println(myAge);
//变量的声明
int myNumber;
//变量的赋值:初始化
myNumber = 1001;
System.out.println(myNumber);
}
变量的三要素
1)限定范围—就是限定变量的数据类型
2)变量名—满足标识符的规范(见名知意)
3)初始化值----必须要限定的数据类型要一致!
3.3.1数据类型的分类
数据类型 | 长度 |
---|---|
byte | 1字节 |
int | 4字节 |
short | 2字节 |
long | 8字节 |
float | 4字节 |
double | 8字节 |
char | 2字节 |
boolean | 1字节 |
注意事项
整数类型的长整型
浮点类型的单精度类型,在定义变量的时候,需要在初始化值的后面加上一个标记
long x = 10000000000L ; //L或者l
float f = 12.56F ; //F或者f
3.3.2 java中的隐式转化
**隐式转换:**基本数据类型的默认类型提示
byte,short,char三者之间不转换,一旦参与运算,优先提升为int类型,—long—
float—double;
int a = 3 ;
byte b = 4 ;
//int类型接收的
int result = a +b ; //a+ int类型的b---将byte类型提示为int,结果为int
类型
3.3.3java中的显示转化
强制类型转换(强转)
就是将的大的数据类型—小的数据类型格式
目标数据类型 变量名 = (目标类型)(表达式或者初始化值) ;
int a = 3 ;
byte b = 4 ;
//byte类型接收结果
// byte result = a +b ; //a+b--->int类型 编译报错
byte result = (byte)(a+b) ; //解决方案:强制类型转换
3.3.4进制的转化
3.4 运算符
基本运算符:
算术运算符
比较(关系)运算符
逻辑运算符(使用最多的)
逻辑单与&
逻辑单或|
逻辑异或^
逻辑非!
后面者两个开发中经常用大的
逻辑双与&&
逻辑双或||
三目运算符(三元运算符
3.4.1 算术运算符
class OperatorDemo{
public static void main(String[] args){
//定义两个变量
int a = 3 ;
int b = 4 ;
//+,-,*,/,%(模:求余数)
System.out.println("(a+b):"+(a+b)) ;
System.out.println("(a-b):"+(a-b)) ;
System.out.println("(a*b):"+(a*b)) ;
System.out.println("(a/b):"+(a/b)) ;
//就先出现小数,需要类型提示,分子分母上给乘以double类型的值
System.out.println("(a/b):"+(a*1.0/b)) ;
System.out.println("(a%b):"+(a%b)) ;
// /:取整,小数在进行除,无限近似于某个值 jdk--->
// BigDecimal:小数的精确计算
}
}
扩展的算数运算符
扩展的算术运算符:++,–
情况1:单独使用:比较简单
无论++或者–在数据的前面还是后面,都是对这个变量本身自增1或者自减1
情况2:参与运算使用
1)如果++或者–在数据的前面,先进行自增或者自减,然后参与运算;
2)如果++或者–在数据的后面,先运算,然后进行自增或者自减
3.4.2 赋值运算符
在扩展的赋值运算符里面,
+=,-=,*=,/=,%= 隐藏了强制类型转换
s += 1 等价于 s = (short)(s + 1);
//改进
int s = 1 ;
s +=1 ; ===等价 s = s +1 ;
3.4.3 比较运算符
这些运算符:无论这些符号连接的表达式是简单的还是复杂,结果应该布尔类型,true/false
表达式:
这些运算符号–连接起来多个变量
注意:
==不能写成 =
class OperatorDemo{
public static void main(String[] args){
//<,>,<=,>=,==,!=
//定义三个变量
int a = 3 ;
int b = 4 ;
int c = 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)<=(b+c)) ;
System.out.println(a!=b) ;
System.out.println(a==c) ;
System.out.println("---------------------------------") ;
//==不能写成 =
int m = 10 ;
int n = 20 ;
//两个数据比较:使用boolean接收
boolean flag = (m==n) ;
//int无法转换为boolean
//boolean flag = (m=n) ;//将n的值赋值给m,将m的值留下来赋值
给flag,而flag变量是boolean
System.out.println(flag) ;
}
}
3.4.4 逻辑运算符
(登录/注册,判断用户是否登录成功了或者判断用户是否注册成功)进行业务逻辑判断;
基本的逻辑运算符
逻辑单与& ----并列关系
特点:有false,则false;
逻辑单或| ----或的关系
特点:有true,则true
逻辑异或^
相同则为false,不同则为true
逻辑非!
非true,则false;非false,则true;偶数给非是它本身
class OperatorDemo{
public static void main(String[] args){
//定义三个变量
int a = 3 ;
int b = 4 ;
int c = 5 ;
//逻辑单与&
System.out.println((a>b) & (a>c)) ;//false & false =false
System.out.println((a<b) & (a>c)) ;//true & false = false
System.out.println((a>b) & (a<c)) ; //false & true = false
System.out.println((a<b) & (a<c)) ;//true & true =true
System.out.println("------------------------------") ;
//逻辑单或|
System.out.println((a>b) | (a>c)) ;//false | false = false
System.out.println((a<b) | (a>c)) ;//true | false = true
System.out.println((a>b) | (a<c)) ; //false | true = true
System.out.println((a<b) | (a<c)) ;//true | true = true
System.out.println("------------------------------") ;
//逻辑异或^
System.out.println((a>b) ^ (a>c)) ;//false ^ false = false
System.out.println((a<b) ^ (a>c)) ;//true ^ false = true
System.out.println((a>b) ^ (a<c)) ; //false ^ true = true
System.out.println((a<b) ^ (a<c)) ;//true ^ true = false
System.out.println("------------------------------") ;
//逻辑非!
//非true,则false;非false,则true;偶数给非是它本身
System.out.println(!(a>b)) ;
System.out.println(!!(a>b)) ;
}
}
扩展的逻辑运算符
逻辑双与&& —并列关系,必须同事满足条件,才成立;
逻辑双或|| — 或的关系:有一个满足条件 成立;
3.4.5三元运算符
格式:
(简单或者复杂的表达式)? 执行成立的结果:执行不成立的结果;
执行流程:
1)先判断表达式是true还是false,如果是true,执行成立的
结果;
2)如果是false,执行不成立的结果;
if (a>b)?a:b
//a大取a否则取b
//如果有一个变量
int x = 100 ;
//%:求余
// String s= (x % 2 ==0)?"偶数":"奇数" ; //String类型:引用类型
3.5 流程控制语句
3.5.1 顺序结构语句
顺序结构语句:从进入到程序的入口之后,代码从上而下依次加载
3.5.2 选择结构语句
3.5.2.1if选择语句1
if(表达式){
语句;
}
判断表达式是否成立,如果成立,则执行语句,否则不执行
import java.util.Scanner ;
class IfDemo{
public static void main(String[] args){
//创建键盘录入对象
Scanner sc = new Scanner(System.in) ;
//提示并录入数据
System.out.println("请输入一个数据x:") ;
int x = sc.nextInt() ;
//判断
if(x >=10){
System.out.println("x大于等于10") ;
}
System.out.println("over") ;
}
}
3.5.2.2 if选择语句2
if(表达式){
语句1 …;
}else{
语句2…;
}
1)首先判断表达式是否成立,如果成立,则执行语句1…
2)如果不成立,执行语句2…
class HomeWork9{
public static void main(String[] args){
Scanner sc = new Scanner(System.in);
System.out.println("请输入两个数");
double a = sc.nextDouble();
double b = sc.nextDouble();
double c ;
if(a>10.0&&b<20.0){
c = a+b;
}else{
c = a*b;
}
System.out.println(c);
}
}
3.5.2.3 if选择语句3
if(表达式1){
语句1 …;
}else if(表达式2){
语句2…;
…
}else{
语句n…;
}
1)先判断表达式1是否成立,成立,执行语句1
2)如果不成立,继续判断表达式2是否成立,成立,则执行语句2,
import java.util.Scanner;
class HomeWork10{
public static void main(String[] args){
Scanner sc = new Scanner(System.in);
System.out.println("请输入狗子的年龄");
int dog = sc.nextInt();
double ren = 10.0;
if (dog<0){
System.out.println("请输入正确的狗子年龄");
System.exit(0);
}else if(dog<=2&&dog>=0){
ren = 10.5+10.5*(dog-1);
}else if (dog>2){
ren = 10.5+10.5+4*(dog-2);
}System.out.println(ren);
}
}
3.5.2.4 switch-case
public class SwitchCaseTest {
public static void main(String[] args){
int number = 2;
switch(number){
case 0:
System.out.println("zero");
break;
case 1:
System.out.println("one");
break;
case 2:
System.out.println("two");
break;
default:
System.out.println("other");
}
}
}
根据 switch 表达式中的值,依次匹配各个 case 中的常量
一旦匹配成功,则进入 case 结构中执行相应语句,直至遇到 break 结束,跳出 switch - case 结构
switch 结构中的表达式,只能是如下的 6 种数据类型之一:byte, short, char, int, 枚举类型(JDK 5.0 新增), String 类型(JDK 7.0 新增)
case 之后只能声明常量。不能声明范围
break 在 switch - case 中是可选的
凡是可以使用 switch - case 的结构,都可以转换为 if - case。反之,不成立。
我们写分支结构时,当发现即可以使用 switch - case,(同时,switch 中表达式的取值情况不太多),又可以使用 if - case 时,我们优先选择使用 switch - case。
switch - case 执行效率稍微高一点。
3.5.2.5 for循环
for(初始化语句;条件表达式;控制体语句){
循环体语句;
}
遍历 100 以内的偶数
for (int i = 1; i <= 100; i++) {
if (i % 2 == 0) {
System.out.println(i);
}
}
记录 100 以内所有偶数的和
int sum = 0;
for (int i = 1; i <= 100; i++) {
if (i % 2 == 0) {
System.out.println(i);
sum += i;
}
}
System.out.println(sum);
3.5.2.6 while循环
初始化语句;
while(条件表达式){
循环体;
控制体语句;
}
do-while
初始化语句;
do{
循环体语句;
控制体语句;
}
while(条件表达式) ;
遍历 100 以内的偶数
public class WhileTest {
public static void main(String[] args){
//遍历100以内的所有偶数
int i = 1;
while (i <= 100) {
if (i % 2 == 0) {
System.out.println(i);
}
i++;
}
}
}
for和while最多以及for和while死循环的格式(while死循环格式)
for和while区别:
共同点:循环的思想,解决代码冗余问题
不同点:
for循环,明确次数
while,不明确次数
格式不同:上面格式
内存角度考虑是否耗费内存资源
for循环结束,无法访问这个变量
while循环结束,依然访问这个变量值;
3.6 jvm内存分配
栈内存:存储局部变量用的这个内存区域
堆内存:new 出来的对象 存储这个区域
方法区: 字节码文件区域----方法调用过程需要加载类
里面存储很多的方法,这些方法被调用,加载进
栈内存
static区域 ----- main方法就是被static修饰的
常量池 ----- 常量的都是在常量池
后面和cpu以及系统相关
寄存器:
本地方法区:
java语言开源,但是很多底层一些东西(线程–依赖于进程),底层c语言操作的
jdk源码上:方法上 关键字native:非java语言实现
3.7 方法
3.7.1 .没有返回值类型的方法的定义以及调用
没有具体返回值类型的方法定义格式
public static void 方法名(形式参数类型1 变量名1,参数类型2 变量名2){
完成业务之后,输出…
}
调用格式:
单独调用
方法名(实际参数1,实际参数2…) ;
import java.util.Scanner ;
class Demo{
public static void main(String[] args){
//键盘录入一个数据
Scanner sc = new Scanner(System.in) ;
//提示并录入
System.out.println("请您输入一个数据1-9:") ;
int number = sc.nextInt();
//调用一个方法:打印出nn乘法表
printNN(number) ;
}
//定义一个方法:打印nn乘法表
public static void printNN(int num){
//形式参数,只是用来"完成自己的业务操作"
for(int x = 1 ; x <=num; x ++){//num=9 行数
for(int y = 1 ; y <=x ; y ++){//列数 和行数相关
System.out.print(x+"*"+y+"="+(y*x)+"\t") ; //"\t"
制表符 类似于tab键 缩进 , 转移字符 "\x" ,X任意字符 \n :代表换行符号
}
System.out.println() ;
}
}
3.7.2 方法重载
方法重载:
方法名相同,参数列表不同,与返回值无关的这些方法;
参数列表不同:
参数个数不同
参数类型不同
参数类型的顺序
.判断以下哪些方法是重载关系?
public static void open(){}
public static void open(int a){}
static void open(int a,int b){}
public static void open(double a,int b){}
public static void open(int a,double b){}
public void open(int i,double d){}
public static void OPEN(){} //跟别的方法不一样
public static void open(int i,int j){}
public static void open(int x,int y){} //和上面的方法一模一样
4.数组
4.1 数组的概述
数组一种容器 ,容器只能存储同一种类型的元素
数组的定义格式
两种
数据类型[] 数组名称;
int[] arr ; //定义了一个int类型的数组arr变量
数据类型 数组名称[] ;
int arr[] ; //定义了一个int类型的arr数组变量
初始化两种
1)动态初始化
数据类型[] 数组名称 = new 数据类型[数组长度];
int[] arr = new int[3] ;
int arr[] = new int[3] ;
2)静态初始化
数据类型[] 数组名称 = new 数据类型[]{元素1,元素2....} ;
简写格式
数据类型[] 数组名称 = {元素1,元素2....} ;
int[] arr = {11,22,33} ;
创建一个数组的注意事项
初始化的时候不能动静结合: 不能够同事动态和静态初始化,只能有一种
//创建一个数组
//不能够同事动态和静态初始化
int[] arr = new int[3]{1,2,3} ;
int[] arr = new int[3] ;//要么这个格式,动态初始化
int [] arr = {1,2,3} ; //要么这个格式 静态初始化,
int[] array = new int[3] ; 这句话完了哪些事情? ----内存干了什么事
情
1)需要在栈内存中开辟 空间, int[] array这个变量
2)new int[3] ; 需要在堆内存中申请空间
3)为这个堆内存中的这些数组的元素,进行系统默认初始化,int类型的元素在
数组中默认值0
4)系统初始化完毕,为堆内存空间产生一个空间地址值,
5)将堆内存空间地址值赋值给栈内存的变量array
6)栈内存变量 array指向堆内存地址
4.2 数组的常见算法
4.2.1 冒泡排序
冒泡排序:
* 两两比较,将较大的值往后放,第一次比较完毕,最大值出现在最大索引处;
* 依次这样比较,可以得到排好序的数组;
*
* 规律
* 1)两两比较,将较大的值往后放,
* 2)第一次有0个不比
* 第二次有1个不比
*
* ....
* 每次比较,就会减少一次比较
* 比较的次数:数组长度-1次
public class BubbleSortDemo {
public static void main(String[] args) {
//已知数组:
int[] arr = {24,69,57,86,13} ;
//遍历
System.out.println("排序前:") ;
printArray(arr);
System.out.println("----------------------------------------------");
//调用冒泡排序的方法
bubbleSort(arr);
//打印
printArray(arr) ;
}
/**
* 定义方法
* 两个明确
* 1)明确返回值类型:void
* 2)明确参数类型以及参数个数
* int[] arr数组
*/
public static void bubbleSort(int[] arr){
for(int x = 0 ; x < arr.length-1; x++){//比较的次数
for(int y = 0; y < arr.length-1-x;y++){
//前面元素和后面元素比较
if(arr[y]> arr[y+1]){
//互换
int temp = arr[y] ;
arr[y] = arr[y+1] ;
arr[y+1] = temp ;
}
}
}
}
//遍历数组,打印元素
public static void printArray(int[] arr){
System.out.print("[") ;
for(int x = 0 ; x < arr.length; x ++){
if(x==arr.length-1){
//取到最大索引值
System.out.println(arr[x]+"]");
}else{
//没有取到最大索引值
System.out.print(arr[x]+", ");
}
}
}
}
4.2.2 数组的逆序
/**
*
* 需求:将数组进行逆序
*
* 规律:
*
* 角标x = 0 ,
* 将arr[0]元素和arr[arr.length-1-0] 互换
* arr[1]元素和arr[arr.length-1-1] 互换
* arr[2]元素和arr[arr.length-1-2] 互换
* ...
* ...
* 需要保证数组长度 arr.length/2
* int[] arr = {69,57,13,24,87....} ;
*/
public class ArrayDemo4 {
public static void main(String[] args) {
//创建一个数组
int[] arr = {69,57,13,24,87} ;
System.out.println("逆序前:" );
//调用数组的遍历功能----将数组的元素一一打印 [元素1, 元素2, 元素3, ...元素n] ;
printArray(arr) ;
System.out.println("------------------------------------------------") ;
System.out.println("--------------------下面使用方法改进-------------------------");
System.out.println("使用方法改进的逆序后:");
// reverseArray(arr);//逆序
reversArray2(arr) ;//第二种方式
printArray(arr);
}
//方式2:
public static void reversArray2(int[] arr){//{69,57,13,24,87}
//for遍历数组
//索引值 start初始索引值 ,end :最终索引值
for(int start = 0,end = arr.length-1;start < end;start++,end--){
//继续中间变量互换
int temp = arr[start] ; //arr[0] = 69
arr[start] = arr[end] ; //arr[arr.length-1] = 87
arr[end] = temp; // 69
}
}
//方式1:
public static void reverseArray(int[] arr) {
for(int x = 0; x < arr.length/2 ; x++){
//x=0 ,第一个角标
//定义一个中间变量
int temp = arr[x] ; //arr[0]
//arr[0] = arr[arr.length-1-0]
arr[x] = arr[arr.length-1-x] ;
//arr[arr.length-1-0] = arr[0]
arr[arr.length-1-x] = temp ;
}
}
//遍历数组的方法
public static void printArray(int[] array){
System.out.print("[");
//遍历数组
for(int x = 0 ; x < array.length ; x ++){
//如果x角标==array.length-1 ,最大索引值,它对应的元素就是最后一个元素
if(x==array.length-1){
//输出最后元素和右]
System.out.println(array[x]+"]");
}else{
//中间元素以及", "
System.out.print(array[x]+", ");
}
}
}
}
4.2.3 最值问题
数组中的基本应用
*
* 最值问题 (最大值/最小值)
*
* 已知一个数组,静态初始化,完成获取数组中最大值
*
* 分析:
*
* int[] array = {65,45,76,87,13} ;
*
* 1)定义一个参照物 array[0]就是最大值
*
* 2)从角标1开始遍历数组的其他元素
* 3)判断:使用后面的元素依次和参照物比较
* 如果后面元素比参照物,将最大值修改了
* 4)获取最大值;
public class ArrayDemo {
public static void main(String[] args) {
//创建一个数组静态初始化
int[] array = {65,45,76,87,13} ;
//1)定义一个参照物
int max = array[0] ;
//2)从角标1开始遍历数组的其他元素
for(int x =1 ;x < array.length ; x++){
//array[x]就可以获取到了
/*
* 3)判断:使用后面的元素依次和参照物比较
* 如果后面元素比参照物,将最大值修改了*/
if(array[x]> max){
//后面的元素比较大
max = array[x] ;
}
}
System.out.println("数组中的最大值是:"+max);
System.out.println("-----------------------------------------") ;
//学习了方法,上面代码进行改进
//赋值调用
int max2 = getArrayMax(array) ; //实际参数
System.out.println("max2:"+max2);
System.out.println("-----------------------------------------") ;
//获取数组最小值
int min = getArrayMin(array);
System.out.println("min:"+min);
}
/**
* 定义一个方法, 获取数组最小值
* 两个明确
* 1)明确返回值类型 int
* 2)明确参数类型以及参数个数
* int[] /1个参数
*
*/
public static int getArrayMin(int[] arr){
//定义一个参照物 是最小值
int min = arr[0] ;
//从角标1开始遍历数组
for (int i = 1; i < arr.length; i++) {
//判断
//如果后面的元素比min还小,后面的元素是最小值
if(arr[i] < min){
min = arr[i] ;
}
}
return min ;
}
/**
* 定义一个 求 数组最大值的方法
* 两个明确:
* 1)明确返回值类型 :int
* 2)明确参数类型以及参数个数
* 数组/ 1个
*/
public static int getArrayMax(int[] arr){
//1)定义参照物
int max = arr[0] ;
//2)从角标1开始遍历数组,获取每一个元素
for(int x = 1 ; x < arr.length ; x ++){
//判断
if(arr[x] > max){
//将后面的元素赋值给max
max = arr[x] ;
}
}
return max ;
}
}
4.3 数组常见的异常
ArrayIndexOutOfBourdsException:数组角标越界异常
合理范围:[0, arr.length - 1]
越界:arr[-1], arr[arr.length]
NullPointException:空指针异常
eg.
int[] arr = null;
arr[0];
5.面向对象
5.1 面向对象的思想特征
什么是面向对象? Java语言 —对比 面向过程: 代表 c语言
面向对象的思想特点是什么?
面向对象的三大特征: 封装,继承,多态 (整个java最重要的)
Java重要特点:代码的健壮性(里面涉及Java面向的对象特征以及java设计模
式)
面向对象的特点
1)更符号生活中的思想行为习惯
2)让复杂的事情简单化
3)从执行者变成了指挥者
面向对象的三大特征
封装
继承
多态
5.2 类
类,是能够描述现实世界事物一组属性和行为的集合;
类和事物的关系:一一对应的关系
事物:一定现实真实存在的
学生事物
属性: 姓名,身高, 年龄 等等…
行为: 主要目的学习…
Java中规定,需要定义类描述这个事物 ,Java中最基本单元就是类
代码体现 描述哪一个事物
class 类名{ //类名:满足标识符的规范: 见名知意
}
基本类型作为形式参数和引用类型
(数组,类,接口) 作为形式参数的特点?
基本类型作为形式参数,形式参数改变不影响实际参数;
引用类型作为形式参数,形式参数的改变直接影响实际参数;
类 描述现实世界事物的一组属性和行为,代码体现出来对某个事物的描述
以及在对应的主方法中测试
1)手机有品牌(brand),价格,颜色,内存等属性,
手机可以打电话,发短信,打游戏等行为,
请使用面向对象的方式描述手机并且进行定义一个PhoneTest类,在主方法中测
试手机类
2)学生有姓名,年龄,性别属性
学生主要行为就是学习,还可以玩游戏,
请使用面向对象的方式描述学生类并且定义一个StudentTest类,在主方法中测
试学生类
类:是描述事物的属性和行为的集合
*
* 描述学生事物
* 属性:姓名,年龄,性别...
* 行为:学习,玩游戏,抽烟...
*
* 具体的学生: ---- 描述具体的学生事物----代码中体现创建这个类对象 :创建具体的对象的格式
* 类名 对象名 = new 类名();
*
*
* 张三,20,男 对象名.成员变量名 = 赋值;//成员变量赋值
* 学习JavaEE 对象名.成员方法名(); //调用成员
*
* 使用面向对象方式描述这个学生事物 --定义一个类, 类Java中最基本单元
*
* class Student{ //见名知意
* //代码描述事物的属性:成员变量:类中方法外
* }
*
*/
//学生类:描述学生事物
public class Student {
//成员变量------学生事物的属性 (类中,方法外)
String name ; // 学生的姓名
int age ; // 学生的年龄
String gender ; //学生的性别
//成员方法----学生事物的行为: 行为:学习,玩游戏,抽烟...
//去掉static
//学习
public void study(){
System.out.println("正在学习JavaEE") ;
}
//玩游戏:
public void playGame(String gameName){ //玩什么游戏 "csGo" "吃鸡"
System.out.println("喜欢玩"+gameName);
}
//抽烟
public void smoke(String somkeBrand){ //抽烟的类型 "华子"...
System.out.println("喜欢抽"+somkeBrand) ;
}
}
5.2.1 this关键字
this:代表当前类对象的地址值引用 Student s = new Student() ; s---->空间地址
值的引用;
this的出现:
为了防止局部变量隐藏了成员变量,
构造方法
public Phne(String brand ,int price){
this.brand = brand ;
thi.price = price ;
}
setxxx()
public void setBrand(String brand){
this.brand = brand ;
}
this的用法:
this.变量名; 变量名:访问本类的成员变量名
this.方法名() ; 访问的本类的成员方法
public class Test {
private String name;//姓名
private String sex;//行别
private int age;//年龄
public Test(String name, String sex, int age) {
this.name = name;
this.sex = sex;
this.age = age;
}
}
5.2.2 匿名对象类
就是没有名字的对象
标准的写法:
类名 对象名 = new 类名();
匿名对象的格式
new 类名(); 直接在堆内存开辟空间,使用完毕就要被回收,可以节省内
存
匿名对象的好处
1)匿名对象可以作为参数传递 :可以把上面那个代码改进
2)匿名对象可以节省内存空间,因为压根没有栈内存空间,不需要开辟,直接开
辟堆内存空间
3)匿名对象一般适用于一次即可,使用完毕,直接被jvm的GC(垃圾回收器)的回
收;
class StudentTest{
public static void main(String[] args){
//匿名对象:
//需求:访问StudentDemo类的method方法
new StudentDemo().method(new Student()) ;
}
}
5.2.3 static关键字
static本身的含义:共享,共用,可以多个对象去共用;
被static修饰的成员变量或者成员方法---->随着类的加载而加载,优先于对象存在
被static访问方式的变量/方法—>静态变量/静态方法:
类名.变量名;
类名.方法名() ;
static使用场景:
一般就工具类(自定义的)或者jdk提供工具类:java.util.Arrays:数
组工具类
java.lang.Math:数学运算的工具类
java.util.Collections:针对集合工具类
他们的方法都是提供—static修饰的 (查看jdk的api文档)
一般说的成员的东西:都行需要对象来访问的
类名 对象名 = new 类名() ;
成员变量----非静态的
成员方法----非静态的
class Demo{
public static int num = 20 ;
public static void method(){
System.out.println("method Demo") ;
}
}
class MyMain{
public static void main(String[] args){
//访问num,调用method
5.2.4 代码块
静态代码块 执行一次完毕;
构造代码块:每次执行构造方法之前,如果代码中有构造代码块,先执行构造代码块
静态代码块,构造代码块,构造方法的优先级
静态代码块 > 构造代码块 > 构造方法
5.2.5 继承
多个类的共性内容抽取出来到独立的类中,多个类和这个类产生一个关
系"extends
Jdk提供了Object类: 上帝(默认代表所有的类的父类)
class Fu2 {}
class Fu extends Fu2{}
class Zi extends Fu{} 只支持这种单继承
不能写成
// class Zi extends Fu,Fu2{} :Java语言不支持多继承
继承的特点:只支持单继承,不支持多继承,但是可以多层继承
5.2.5.1 继承的方法构造问题
子类继承父类,子类的构造方法是不能继承父类的构造方法的,但是可以通过关键字
super来访问父类的构造方法;
super():访问父类的无参构造方法
super(xxx):访问父类的有参构造方法
this():访问自己本类的无参构造方法
this(xxx):访问自己本来的有参构造方法
子类继承父类,子类的所有构造方法都默认访问父类的无参构造方法(因为子类的构造方
法中的数据,可能来自父类,需要父类先初始化!)
子类的构造方法中第一句话都隐藏 :super() ;
子类继承父类,如果父类中没有无参构造方法,但是存在有参构造方法,子类构造方法
出现什么问题?
报错,因为父类没有无参构造方法了,而存在有参构造方法,系统不会在无参构
造方法了;
方案1:
手动添加父类的无参构造方法
方案2:在不手动给出父类无参构造方法,如何解决呢?
让子类的所有构造方法间接访问父类的有参构造方法super(xxx)
方案3:只要保证所有的子类的构造方法中某一个让父类初始化即可!
class Fu{
// 手动添加父类的无参构造方法
//public Fu(){
//}
public Fu(String name){
System.out.println("Fu的有参构造方法"+name) ;
}
}
class Zi extends Fu{
public Zi(){
//隐藏super() ;
//直接访问父类的有参
super("hello") ;
// this("高xxx"); //访问本类的有参构造方法
System.out.println("Zi的无参构造方法") ;
}
public Zi(String name){
// 隐藏super();
// super("hello") ;
this() ;//访问本类的无参构造方法
System.out.println("Zi的有参构造方法"+name) ;
}
}
//实际写代码:继承关系:
//子类无参 访问父类无参
//子类有参访问 父类有参
5.2.5.2继承关系中成员变量的访问问题
子类继承父类,如果子类的成员变量名称和父类的成员变量名称不一致,分别访问即可;
如果子类的成员变量和父类的成员变量名称一致:
1)先在子类的局部位置找,是否存在,存在,就使用;
2)如果子类的局部位置没有,在子类的成员位置中找,是否存在,存在就使用;
3)如果子类的成员位置也没有,然后再父类的成员位置找,是否存在,存在就使用;
4)如果父类的成员位置也没有,(父类没有它的父类),就报错,整个类中没有变量;
遵循 “就近原则”
5.2.5.3 继承关系中成员方法的访问问题
子类继承父类,成员方法(公共方法)名称不一致,分别调用即可 ;
如果成员方法名一样,系统认为子类需要重写父类的方法,必须保证 子类的方法和父类一模一样---->子类将父类的方法覆盖.方法重写,访问子类的功能;‘’
如果创建对象的时候,创建的父类对象
Fu fu = new Fu() ; fu .方法名() ; 访问的父类的成员方法
5.2.6 final关键字
final:表示最终的,无法更改的,状态修饰符;
修饰类,该类不能被继承
修饰变量,此时变量是一个常量
编译时期常量 : final修饰的基本类型,基本数据类型的数据值不能在改
变 (不需要jvm加载)
public static final int num = 100 ;
运行时期常量: final修饰的引用类型数据,引用类型:类,数组,接口 都需
要加载
地址值不能在改变
public static final Integer i = new Integer(100) ;
修饰成员方法,该方法不能被重写
5.3 多态
5.3.1多态的前提条件以及成员访问特点
多态的前提条件:
1)必须有继承关系
2)存在方法重写
3)父类引用指向子类对象 Fu fu = new Zi() ; 向上转型
Fu fu = new Zi() ;
多态的成员访问特点:
1)成员变量: 编译看左,运行看左
2)成员方法:编译看左,运行看右,存在方法重写
3)静态的方法:算不上重写,跟类相关的,编译看左,运行看左;
4)构造方法:分层初始化,先执行父类初始化,在执行子类初始化
5.3.2 多态的弊端与解决方案
不能访问子类的特有功能;
多态的格式:
Fu fu = new Zi() ; //向上转型
解决方案
1)创建具体的子类对象
Zi zi = new Zi() ; //Zi:子类名
不好:需要重新开辟堆内存空间,消耗内存空间;
2)向下转型
Zi z = (Zi)fu; //符号强转的语法
z.特有功能() ;
不需要单独去开辟堆内存空间
5.4 接口
接口—体现事物本身以外的额外功能,需要事物要对接口的功能要进行实现,才具备!
- 接口的定义:
interface 接口名{} 接口和类名的命名规范同理,遵循"大驼峰命名法" - 接口的成员特点:
1)成员变量:只能是常量,存在默认修饰符 :public static final
2)成员方法:只能是抽象方法,存在默认修饰符 public abstract
3)构造方法:没有构造方法的—通过子实现类的构造方法来实例化 - 接口本身意义:
对外暴露这些功能,让子实现类实现 ! - 如何实例化
接口通过它的子实现类进行实例化(前提,这个类实现 implements 接口)
class 子实现类名 implements 接口名{//实现
}
//定义接口
interface Inter{
// int num = 20 ; //隐藏了默认修饰符public static final 可以省略不写的
public static final int num = 20 ;
/*void show(){
System.out.println("show Inter");
}*/
//void show() ; //省略了默认修饰符 public abstract ,可以省略不写
public abstract void show() ;
/* public Inter(){ //不能这样写
}*/
}
//提供具体的子实现类
//实现
class InterImpl implements Inter{//实现类必须实现接口的抽象方法,否则报错
@Override
public void show() {
System.out.println("show InterImpl");
}
}
//测试类
public class InterfaceDemo {
public static void main(String[] args) {
//创建Inter对象
//Inter inter = new Inter() ; //接口不能实例化: Inter is abstract
//所以,通过接口指向子实现类名
//接口名 对象名 = new 子实现类名() ; //接口多态
Inter inter = new InterImpl() ;
System.out.println(inter.num); //编译看左,运行看左
//inter.num = 30 ; //报错:final修饰的变量:最终的.无法更改的, 不能在被赋值
System.out.println(Inter.num) ; //接口比抽象类还抽象 之前:类名.变量名; 变量被static修饰
//接口名.变量名 ; 变量被static修饰
}
}