Java基础教案
怎么学习Java:多想,多练
思想是学出来的,我给大家一个问题,如何来解决它,现在来说很多人是没有思路的
我要做的就是给大家这样一个思路,学的多了,练得多了,在遇到问题的时候,也就
逐渐的形成了这个解决问题的思维
为什么很多公司招有3-5年工作经验的开发人员,工资又高,是因为家有一老如有一宝
公司还是喜欢招年轻人的工作有动力。招有工作经验多的人是因为他在这么多年的工作
中遇到的问题多,解决的问题,他的经验就是他宝贵的财富。
Java语言介绍
Java是一种编程语言,如C++,C,PHP等。语言是沟通交流,传递信息的工具。
我与大家之间通过汉语交流,那么java就是人类与计算机之间沟通交流,传递信息的工具。
Java的三大平台
JavaSE Java的标准平台:包含了Java的基础的功能,学习的语法,内置的API方法
JavaEE Java的企业级应用平台:JavaSE的基础上,扩展了一些API,用于B/S结构的企业应用的开发
JavaME Java的移动应用平台:JavaSE缩微版,给嵌入式系统或移动端系统使用过时
Java语言特点
1.跨平台 平台-操作系统任何平台上编写的Java程序,可以在另外的平台上执行JDK Java的开发环境JRE Java的运行环境 - Java虚拟机java文件 ->(编译)class文件 ->Java虚拟机中运行2.面向对象:以人类正常思维开发和设计软件,开发程序开发方法:支撑大型的关系复杂系统的构建3.多线程:支持多任务场景4.分布式:支持网络应用5.简单:比C++简单 指针,回收(内存泄露)Java中没有指针, 系统自动回收
变量和运算符
Java中的变量
什么是变量:指在内存中开辟的存储空间,用于存放在运算过程中用到的数据。
(大家住在G2,公寓需要开通一个房间给大家,提高大家居住)
(插卡游戏机中,破解版的坦克大战,魂斗罗可以无限设置多少条命,我们在游戏中改变的
哪一个数据就是变量,用于表示玩家的生命数)
如何声明变量
例:Intid=123; (int是变量的类型id是变量名123是变量的赋值)Java中规定在使用一个变量前,必须对该变量进行声明并初始化声明就是给变量一个数据类型,初始化就是对变量赋值方式:声明的同时初始化,先声明后初始化变量是一个代词:指代的是内存中的数据变量是可变化的量,改变的是该变量所指代的数据。
变量的命名:
可以由字母,数字,”_”和“$”组成。不能以数字开头,区分大小写,不能使用java的关键字和保留字可以使用中文命名但不建议使用。建议:见名知意 驼峰命名法
Java中的8中基本数据类型
整数类型:byte1Byteshort2Byteint4Byte(整数的默认类型)long8Byte浮点数类型float4Bytedouble8Byte(浮点数的默认类型)字符类型char2Byte 存储一个字符(英文,汉字...)布尔类型boolean1Bytetrue(真)false(假)
基本数据类型之间的转换
1.自动类型转换(隐式转换):从小到大2.强制类型转换 :intnum=(int)5.21; Double ->int会造成精度的缺失,对数据产生影响。 Byteshortchar转为int(三种类型实际存储的数据都是整数) 整数直接量可以直接赋值给Byteshortchar(大->小 系统帮忙转了) Byteshortchar三种类型参与运算时,先一律转成int再进行运算
Java中的运算符
除法(/)适用于两个整数,结果舍弃小数部分取余(%) 适用于整数,char,浮点数:结果取决于除数的正负。自增(++):使变量的值+1;自减(--):使变量的值-1;注意:参与运算时,运算符写在变量前,变量后的效果不同关系运算符:用于判断数据之间的大小关系:(>,<,>=,<=,==,!=)关系运算的结果为boolean(true/false)逻辑运算符: &&(与) ,||(或),!(非)&&(与):多个条件同时满足。整个表达式为true||(或):多个表达式中,只要有一个满足,整个表达式为true。!(非):非真则假,非假则真。短路问题11&17运算 二进制 (1-1为1其余为0)参与逻辑运算的表达式的结果都是布尔值。特殊的运算符:+=,-=,*=,/=三目运算表达式:(boolean)表达式?表达式1:表达式2先计算(boolean)表达式,若为true,则整个表达式返回表达式1若为false则整个表达式返回表达式2移位运算符(了解)<< 左移>> 右移2<<3==162的 二进制表示10%216的 二进制表示10000%16负数N(-35)转成二进制先将35的二进制数求出00100011全部位安位取反11000100再加1:11000101
流程控制语句
分支结构:if:if(逻辑表达式){ 语句块 } 如果逻辑表达式成立,则执行语句块代码If( ){ }else{ } ;if(){ }elseif(){ }switchcase:--breakIf-else-if:相对灵活 ;switchcase:结构更清晰循环结构:for,wihle,do-whilewhile:while( 表达式){ 语句块 } :先判断在执行do{ 语句块}while(表达式):先执行一次,在判断for(表达式1; 表达式2; 表达式3){ 循环体 } 一般用于固定次数的循环表达式1:循环变量的初始化表达式2:循环条件表达式3:循环变量的改变Break;跳出循环,使用continue跳过本次循环进入下次循环
or循环输出1 到100
while循环输出1-100
计算2000年1月1日到2008年1月1日相距多少天
输出1 到100的累加和
求100以内所有偶数的和
求整数1~100的累加值,但要求跳过所有个位为3的数
循环输入大于0的数字进行累加,直到输入的数字为0,就结束循环,并最后输出累加的结果
打印出?100~999之间的所有“水仙花数”。所谓“水仙花数”,是指一个3
位数,其各位数字立方和等于该数本身
输入一个整数N,判断该数是不是质数,如果是质数输出"N是一个质数",否
则输出"N不是质数"。提
示:除了1和它本身不能被任何数整除
求9的阶乘;9!=123456789?
猜数字游戏.
数组
什么是数组:
什么是数组:Java中用于存储数据的容器。
数组的声明和创建:引用数据类型的方式
数组的初始化:
1.int[] arr=newint[]{1,2,3,4,5};2.int[]arr=newint[5];3.int[] arr={1,2,3,4,5};
数组元素的访问:
在JAVA中通过下标访问数组的元素,数组的下标从0开始,表示第一个元素
数组的属性:长度length,表示数组的长度
利用数组的属性length,遍历数组
for(inti=0; i
数组的异常:当访问数组下标超过数组大小时,会报异常,数组下标越界
方法的定义及调用
微信红包小程序publicclassWeiCat{ publicstaticvoidmain(String[] args) {// TODO Auto-generated method stubStringwid="cl666";//微信号Stringpwd="cl123456";//微信密码StringpayID="888888";//支付密码double balance=800;//红包零钱double money=0;Stringupay; Scanner scan=newScanner(System.in);while(true){ System.out.println("微信号");Stringuwid=scan.next(); System.out.println("请输入密码");Stringupwd=scan.next();if(uwid.equals(wid)&&upwd.equals(pwd)){//登陆成功break; }else{//登陆失败System.out.println("请重新登陆"); } } System.out.println("1.发红包 2.转账 3.提现 4.充值"); int num=scan.nextInt();switch(num){case1: System.out.println("请输入红包金额"); money=scan.nextDouble();if(money>balance){ System.out.println("红包零钱不足"); }else{ System.out.println("请输入支付密码"); upay=scan.next();if(upay.equals(payID)){ System.out.println("红包发生成功"); balance-=money; }else{ System.out.println("支付密码有误"); } }break;case2:break;case3:break;case4:break;default: System.out.println("选项无效"); } }}
什么是方法:完成某个特定功能的语句。 特定功能就是一段具有运算功能的代码随着学习的深入,代码量会随之增多。之前都写在一个main方法中 ,如果代码量达到几千行 甚至一万行的话 ,对于程序的可视化效果 与分析都非常不好,所以使用方法将代码进行简化生活案例:电饭煲 自动贩卖机 压汁机特点:使用者无需了解工具具体的内部实现 只需了解工具的使用规则方法的例子:System.out.print(); 方法的特点 都有小括号Arrays.sort()Arrays.copyOf() 具有运算的功能使用方法编程的优点:保证一个方法 只做一件事 银行:存钱( ) 取钱( ) 余额( ) 操作( 存钱 取钱 余额)减少代码的复用 ,便于程序的维护 方法的特点:方法的调用者无需知道方法的内部实现 只需了解方法需要的参数即可方法的定义:[ 访问控制符 ][ 修饰符 ]返回值类型 方法名([参数类型 参数名]){ }[ 访问控制符 ][ 修饰符 ]:后续进行讲解返回值类型:该方法运算结果的数据类型(Object,基本数据类型,引用类型) 如果声明的返回值类型与实际返回的类型不同,会编译报错 方法名([参数类型 参数名]):统称参数列表 方法名:作为调用该方法的标识 参数:作为方法中运算时用到的数据,个数没有限制,若有参数,要声明参数类型 方法体:是一个语句块,执行特定的功能代码return:返回值的关键字方法的分类:根据参数个数: 有参方法 无参方法根据返回值类型 有返回值的方法 无返回值的方法
参数与返回值类型的多样化
1. 参数:3个 类型:Stringintint返回值类型:boolean在保存了多个学生姓名的数组中,指定查找区间,查找某个学生姓名并显示是否查找成功
publicstaticbooleanselectName(String str ,intstart,intend ){if(start<0){ start=0; }if(end>=names.length-1){ start=names.length-1; }for(inti=start ;start<=end;i++){if(names[i].equals(str)){returntrue; } }returnfalse; }
2.参数:1个 类型:int[ ] 返回值:double/int有5位学员参加了Java知识竞赛的决赛,输出决赛的平均成绩和最高成绩
//求平均成绩publicstaticdoublegetAvg(int[] score){intsum=0;for(inti=0;i
//求最大值publicstaticdoublegetMax(int[] score){ Arrays.sort(score);returnscore[score.length-1]; }
3.参数:1个 类型:int[ ] 返回值:int[ ]在保存多个学生成绩的数组中,将学生的成绩安装升序排序
publicstaticint[] sortArray(int[] score){ Arrays.sort(score);returnscore; }
publicstaticint[] sortArray1(int[] score){inttemp;for(inti=0;iscore[j+1]){ temp=score[j]; score[j]=score[j+1]; score[j+1]=temp; } } }returnscore; }
4.参数:0类型:无 返回值:int求1—100之间的整数和
publicstaticintgetSum(){intsum=0;for(inti=1;i<=100;i++){ sum+=i; }returnsum; }
5.参数:2个 类型:int返回值:int求两个整数区间的和
publicstaticintgetSum(inta,intb){intsum=0;for(inti=a;i<=b;i++){ sum+=i; }returnsum; }
6.参数:3个 类型:int返回值:double求三个整数的和
publicstaticintgetSum(inta1,inta2 ,inta3){returna1+a2+a3; }
7.参数:1个 类型:char[ ] 返回值:boolean用户随机输入5个字符,判断是否为“回文”(例:abcba,12321)
publicstaticbooleancheckFlag(char[] c){booleanflag=true;for(inti=0;i
8.参数:3个 类型:int返回值:int随机输入不相同的三个整数 比较出其中的最大值
publicstaticintgetMax(inta,intb,intc){if(a>b&&a>c){returna; }elseif(b>a&&b>c){returnb; }elseif(c>a&&c>b){returnc; }return0; }
9.参数:2个 类型:int返回值 :int求两个整数之间存在多少个奇数
publicstaticintcountNum(inta,intb){intcount=0;for(inti=a;i<=b;i++){if(i%2!=0){ count++; } }returncount; }
10.参数:1个 类型:int返回值 :boolean随机输入一个年份 判断是否为闰年
publicstaticbooleancheckYear(intyear){if(year%4==0&&year%100!=0||year%400==0){returntrue; }returnfalse; }
11.参数:1个 类型:char[ ]返回值:无输入一行字符,分别统计出其中英文字母、数字和其它字符的个数
有一个方法被调用代码为int[] arrs = sort(newStudent(12)) 求该方法的声明代码答案:publicint[] sort(Student arr)有一个方法被调用代码为String[][] strs = sort(15),该方法的声明代码为答案:publicString[][] sort(intn)
参数的传递:
参数传递的过程实际就是把实参的值传递给形参的过程
方法的调用
在同一个类中static修饰的方法可以直接通过方法名进行调用在不同的类中static修饰的方法 通过类名.方法名进行调用非static修饰的方法 通过对象.方法名进行调用
方法的重载
在同一个类中 允许同时存在多个方法名相同的方法
规则:
方法名必须相同
参数列表不同
参数个数不同
参数类型不同
与返回值类型无关
总结和练习
总结练习: 猜字符游戏
1.设计数据结构---变量
2.设计程序结构—方法
3.设计实现----方法的实现
publicclassGuess{publicstaticvoidmain(String[] args){// TODO Auto-generated method stubScanner scan=newScanner(System.in); String[] c=getChar();// for(String c1:c){// System.out.print(c1+" ");// }System.out.println("开始猜吧.."); String[] cs;intcount=0;while(true){ System.out.println("请输入第1个字母"); String input1=scan.next(); System.out.println("请输入第2个字母"); String input2=scan.next(); System.out.println("请输入第3个字母"); String input3=scan.next(); System.out.println("请输入第4个字母"); String input4=scan.next(); System.out.println("请输入第5个字母"); String input5=scan.next(); cs=newString[]{input1,input2,input3,input4,input5};int[] result=getResult(c,cs); System.out.println("位置正确个数:"+result[0]); System.out.println("字符正确个数:"+result[1]);if(result[0]==5&&result[1]==5){break; } count++; } System.out.println("您一共猜了"+count+"次"); }publicstaticString[] getChar(){ Random r=newRandom();intindex; String[] ch=newString[5]; String[] cs={"A","B","C","D","E","F","G","H","I","J","K","L","M","N","O","P","Q","R","S","T","U","V","W","X","Y","Z"};boolean[] flag=newboolean[cs.length];for(inti=0;i
面向对象
面向对象:是一种编程思想,是对人类思维进行归纳总结,在计算机中模拟现实世界的开发方法是以对象为核心,围绕对象进行操作
面向过程: 通常分析出解决问题需要的步骤,然后用方法把这些步骤实现,最后一次调用这些方法。缺乏对参数的封装。
面向过程主要考虑的是程序的流程和算法而数据只是在需要时插入到算法中。
为什么使用面向对象:
可以解决复杂的关系和逻辑
利用人类的思维进行编程
支持程序扩展,维护性更换
如何实现面向对象:了解类和对象
类:具有一类事物共同特征和行为的抽象。
鸟:- - - 就是抽象出来的对这类事务的描述 - - - 计算机中叫做 类(一种引用类型)
特征:翅膀 脚 眼睛 行为:飞 吃
抽象中可能发生的问题:
认知可能不准确 - - - 强调”共有的” 没有忽略次要特征(与业务相关的特征)
对象:类在现实生活中的实例
Java程序完成类的创建
创建类的对象
操作累的属性和方法
构造方法:
在创建对象时,通过构造方法完成对象的内存开辟和初始化
构造方法的特点:
在开发中如果没有编写构造方法,系统会提共一个默认的无参构造方法,
但是若定义了任何类型的构造方法,系统则不会提供默认构造器
构造方法可以重载
构造方法不可以有返回值
通过有参构造方法初始化属性
This关键字:表示当前对象的引用
使用情况:成员变量(属性)与局部变量重名
在一个构造器中 调用其他重载的构造器
需要返回当前对象的引用
publicclassCar{intnum=0;publicCargetCar(){ num++;returnthis; }publicCargetCar(){ num++;returnnewCar(); }publicvoidsayNum(){ System.out.println(num); } }
对象的内存模型
栈:保存基本数据类型的局部变量和引用类型的引用。 特点:存取速率块,效率高堆:new出来的对象都保存在堆中 特点:存储对内存空间要求较大的变量匿名对象 (newPerson().sayHi();) 该对象只使用一次垃圾回收器: Java的垃圾回收机制是自动的,实际上是JVM内部运行的一个优先级比较低的后台线程 垃圾回收机制仅仅作用于堆内存中,与栈无关 垃圾:堆中的内容不存在任何引用指向它 内存泄露:不再使用的内存没有被及时的回收NewXd(); - -匿名对象
### 扑克游戏 :publicclassPoke{privateString size;//牌号privateString color;//花色privateintcode;//大小publicintgetCode(){returncode; }publicvoidsetCode(intcode){this.code = code; }publicStringgetSize(){returnsize; }publicvoidsetSize(String size){this.size = size; }publicStringgetColor(){returncolor; }publicvoidsetColor(String color){this.color = color; } @OverridepublicStringtoString(){return"size="+ size +", color="+ color +", code="+ code; }}publicclassPokes{privateString[] colors={"红桃","黑桃","方片","梅花"};privateString [] sizes={"2","3","4","5","6","7","8","9","10","J","Q","K","A"};//生成52张扑克publicPoke[] getPoke(){intn=0; Poke[] p=newPoke[52];for(inti=0;i
* 随机发牌
* 庄家 玩家
* 1. 各发一张牌
* 庄家底牌显示 提示玩家 是否看底牌 不看得分翻倍
* 2.发第二张牌
* 第二张牌显示 提示是否看底牌 不看得分翻倍
* 3.发第三张牌
* 直接翻牌
* 发牌结束 双方比较大小
*/// TODO Auto-generated method stubPokes ps=newPokes(); Poke[] p=ps.getPoke();intscore=1000; System.out.println("欢迎来到 炸金花 PK大赛");while(score>0){ boolean[] flag=newboolean [p.length];intsz;intsx; Scanner scan=newScanner(System.in);int[] xscore=newint[3]; System.out.println("第一轮发牌"); Poke pz1=getPoke(p,flag); System.out.println("庄家: 底牌"); Poke px1=getPoke(p,flag); System.out.println("玩家: 底牌"); System.out.println("玩家是否看牌:1.是 2.不是");intnum=scan.nextInt();if(num==1){ System.out.println("玩家:"+px1.getColor()+px1.getSize()); }else{ System.out.println("玩家未看底牌"); } System.out.println("请下注"); xscore[0]=scan.nextInt(); System.out.println("玩家下注:"+xscore[0]);if(num==2){ xscore[0]*=2; } System.out.println("第二轮发牌"); Poke pz2=getPoke(p,flag); System.out.println("庄家:"+"底牌"+" "+pz2.getColor()+pz2.getSize()); Poke px2=getPoke(p,flag);if(num!=1){ System.out.println("玩家:"+"底牌"+" "+px2.getColor()+px2.getSize()); System.out.println("玩家家是否看牌:1.是 2.不是"); num=scan.nextInt();if(num==1){ System.out.println("玩家:"+px1.getColor()+px1.getSize()+" "+px2.getColor()+px2.getSize()); }else{ System.out.println("玩家未看底牌"); } }else{ System.out.println("玩家:"+px1.getColor()+px1.getSize()+" "+px2.getColor()+px2.getSize()); } System.out.println("请下注"); xscore[1]=scan.nextInt(); System.out.println("玩家下注:"+xscore[1]);if(num==2){ xscore[1]*=2; } System.out.println("第三轮发牌"); Poke pz3=getPoke(p,flag); System.out.println("庄家:"+"底牌"+" "+pz2.getColor()+pz2.getSize()+" "+pz3.getColor()+pz3.getSize()); Poke px3=getPoke(p,flag);if(num!=1){ System.out.println("玩家:"+"底牌"+" "+px2.getColor()+px2.getSize()+" "+px3.getColor()+px3.getSize()); System.out.println("玩家家是否看牌:1.是 2.不是"); num=scan.nextInt();if(num==1){ System.out.println("玩家:"+px1.getColor()+px1.getSize()+" "+px2.getColor()+px2.getSize()+" "+px3.getColor()+px3.getSize()); }else{ System.out.println("玩家未看底牌"); } }else{ System.out.println("玩家:"+px1.getColor()+px1.getSize()+" "+px2.getColor()+px2.getSize()+" "+px3.getColor()+px3.getSize()); } System.out.println("请下注"); xscore[2]=scan.nextInt(); System.out.println("玩家下注:"+xscore[2]);if(num==2){ xscore[2]*=2; } Poke[] pokez={pz1,pz2,pz3}; Poke[] pokex={px1,px2,px3}; System.out.println("请双方亮牌"); System.out.println("庄家:"+pz1.getColor()+pz1.getSize()+" "+pz2.getColor()+pz2.getSize()+" "+pz3.getColor()+pz3.getSize()); System.out.println("玩家:"+px1.getColor()+px1.getSize()+" "+px2.getColor()+px2.getSize()+" "+px3.getColor()+px3.getSize()); sz=setScore(getTpye(pokez)); sx=setScore(getTpye(pokex)); String result=show(sz,sx,pokez,pokex);if("玩家赢".equals(result)){ score+=xscore[0]+xscore[1]+xscore[2]; System.out.println("本轮玩家赢"); }else{ score-=xscore[0]+xscore[1]+xscore[2]; System.out.println("本轮庄家赢"); } System.out.println("玩家积分"+score); } }publicstaticPokegetPoke(Poke[] p,boolean[] flag){ Random r=newRandom();intindex;do{ index=r.nextInt(p.length); }while(flag[index]); flag[index]=true;returnp[index]; }//比较牌面大小publicstaticStringgetTpye(Poke[] pz){ Poke p;for(inti=1;ipz[j+1].getCode()){ p=pz[j]; pz[j]=pz[j+1]; pz[j+1]=p; } } }if(pz[0].getSize().equals(pz[1].getSize())&&pz[1].getSize().equals(pz[2].getSize())){return"三条"; }if(pz[0].getSize().equals(pz[1].getSize())||pz[1].getSize().equals(pz[2].getSize())||pz[0].getSize().equals(pz[2].getSize())){return"一对"; }if(!pz[0].getSize().equals(pz[1].getSize())&&!pz[1].getSize().equals(pz[2].getSize())&&!pz[0].getSize().equals(pz[2].getSize()) &&(pz[0].getCode()+1!=pz[1].getCode()||pz[1].getCode()+1!=pz[2].getCode())){return"单牌"; }if(pz[0].getCode()+1==pz[1].getCode()&&pz[1].getCode()+1==pz[2].getCode() &&pz[0].getColor().equals(pz[1].getColor())&&pz[1].getColor().equals(pz[2].getColor())){return"同花顺"; }if(pz[0].getCode()+1==pz[1].getCode()&&pz[1].getCode()+1==pz[2].getCode()){return"顺子"; }if(pz[0].getColor().equals(pz[1].getColor())&&pz[1].getColor().equals(pz[2].getColor())){return"同花"; }returnnull; }//比较输赢publicstaticStringshow(intpz,intpx,Poke[] pz1,Poke[] px1){if(pz==px){if(pz1[2].getCode()>px1[2].getCode()){return"庄家赢"; }else{return"玩家赢"; } }if(pz>px){return"庄家赢"; }else{return"玩家赢"; } }//牌面积分publicstaticintsetScore(String type){intscore=0;if(type.equals("同花顺")){ score=6; }if(type.equals("三条")){ score=5; }if(type.equals("同花")){ score=4; }if(type.equals("顺子")){ score=3; }if(type.equals("一对")){ score=2; }if(type.equals("单牌")){ score=1; }returnscore; }}
面向对象高级特性
为什么使用继承:
不同的类之间存在一些相同的属性和方法
所以将类中相同的属性和方法提取到公共类中
StudentTeather
name : Stringname : String
age : intage : int
sid : inttyear : int
eat();eat();
exam();checkPaper();;
什么是继承:Java中通过extends 关键字让一个类继承另一个类,被继承的类叫父类(超类,基类),新的类叫子类(派生类)。子类可以拥有父类所有的属性和方法继承的语法和规则: 语法:publicclassStudentextendsPerson{ 属性 方法 }继承的优点:代码的复用。例:创建一个建设银行的ATM类 ,实现密码校验方法,取款方法,手机充值方法创建一个工商银行的ATM类,实现密码校验方法,取款方法,转账方法发现:其实密码校验以及取款是每个银行的ATM都存在的功能,在编码时写了重复代码,这时可以创建ATM类,让它实现校验密码和取款的方法。而其它的ATM类继承该类,就可以使用这些方法了。Java中是单一继承,一个类只能有一个父类子类实例化的过程: 子类实例化会先实例化其父类,父类构造器调用完毕,才执行子类构造器 子类继承父类,在子类的构造方法的第一句一定会调用父类的构造方法 如果父类没有明确的构造方法,父类使用的是默认构造器。 子类在继承父类时,在子类构造方法中会默认调用父类的默认构造器super()可以不写 子类在自己的构造器中使用super关键字调用父类的构造器super(参数1,参数2,...) 如果子类调用了父类的无参构造器 而父类中没有无参构造器则会编译报错 Super和this: Super(); 指向父类的引用 调用父类的构造器,只能出现在子类的构造器中, 且必须在第一行super()中有无参数,决定了调用哪个构造器。 在同一个构造器中,不能同时出现super和this
思考以下代码的运行结果
publicsclassCar{privateint site =4;//座位数Car(){ System.out.println ("载客量是"+site+"人);
}
public void setSite(int site){
this.site = site;
}
void print(){
System.out.print("载客量是"+site+"人");
}
}
class Bus extends Car {
Bus(int site){
setSite(site);
}
}
public static void main(String[] args) {
Bus bus = new Bus(20);
bus.print();
}
封装: 对类中的属性和方法规定访问权限,保护类中数据的安全 将类中的信息(属性和方法)隐藏起来,不允许外部程序之间访问,而是通过该类 提供的方法进行访问 活中的例子:到饭馆吃饭,你只需要跟服务员讲你要吃什么饭菜服务员就会跟后台厨房的厨师说明一下 等待一段时间后,饭菜就被服务员直接递送到你面前,作为客户的你是不知道也无需知道饭菜的具体做法, 后台厨房的厨师及做饭菜的过程就是被封装的细节,而服务员则是公开暴露的访问路径, 你只能通过服务员点餐然后获得饭菜,而不能直接去到后台厨房要求厨师如何做饭菜; 类中存在属性name ,调用类随意对属性进行赋值 ,不会符合规范 没有意义。 这是由于调用类可以直接访问到类中的属性 访问权限:用来控制类的成员和类的使用范围private:私有地default:默认地protected:受保护的public:公共的public和 默认 可以修饰类 get方法和set方法访问类中的属性
多态:子类和父类之间,不同的子类之间对于同一行为,有不同的实现方式
例:王者荣耀中的英雄都有技能 但不同的英雄技能不同
每个形状都有面积 但不同的形状面积不同
体现:方法的重写/override
方法的签名相同(方法名,参数列表) ,方法体不同。
例:定义形状类 定义求面积 周长的方法 定义圆形类 声明属性半径 继承 形状类 由于不同形状求面积方法不同 需要重写父类的原始方法classShape{doublec;publicdoublearea();}classSquareextendsShape{publicSquare(doublec){this.c = c; }publicdoublearea(){return0.0625*c*c; }}classCircleextendsShape{publicCircle(doublec){this.c = c; }publicdoublearea(){return0.0796*c*c; } }
重写方法被调用时,看对象类型。子类对象的重写方法被调用时,引用类型无论是父类还是子类,运行的都是子类重写后的版本。
方法重写后的调用原理
code..
可以通过super.方法名 在子类重写方法中调用父类方法。 重写方法的注意事项:1.方法名相同 ,参数列表相同2.子类方法的返回值类型void等于父类,基本类型等于父类3.子类方法抛出的异常小于或等于父类4.子类方法的访问权限大于或等于父类 重载和重写的区别: 重写:遵循“运行期”的绑定,根据对象类型进行调用 重载:遵循“编译器”的绑定,根据参数列表不同进行调用
以下代码中 那些是方法的重载,那些是方法的重写 以及运行结果publicclassOverrideOverloadDemo{publicstaticvoidmain(String[] args){ Goo g =newGoo(); Eoo e =newEoo(); g.show(e); Foo f =newFoo(); g.show(f); Eoo e1 =newFoo(); g.show(e1); Foo f1 =newFoo(); g.show(f1); }}//overloadclassGoo{voidshow(Eoo e){ System.out.println("父类参数"); e.show(); }voidshow(Foo f){ System.out.println("子类参数"); f.show(); }}classEoo{voidshow(){ System.out.println("父类show方法"); }}classFooextendsEoo{voidshow(){ System.out.println("子类show方法"); }}
引用数据类型的转换:
“麻烦你,小王。帮我把那个东西拿过来好吗”
在生活中,你肯定用过这个词--东西。
小王:“你要让我帮你拿那个水杯吗?”
你要的是水杯类的对象。而东西是水杯的父类。通常东西类没有实例对象,但我们有时需要东西(父类)的引用指向它的子类实例。
父子类之间的转换:
上溯造型(向上造成):子类对象- - > 父类对象,造成子类特有的,扩展的属性和方法失效,只能有父类继承的属性和方法。
优点:有利于程序的维护和扩展。
publicclassMaster{privateString name ="";// 主人名字privateintmoney =0;// 元宝数/**
* 有参构造方法。
* @param name 主人名字
* @param money 元宝数
*/publicMaster(String name,intmoney){this.name = name;this.money = money; }publicvoidsetName(String name){this.name = name; }publicvoidsetMoney(intmoney){this.money = money; }publicintgetMoney(){returnmoney; }publicStringgetName(){returnname; }/**
* 主人给Dog喂食。
*/publicvoidfeed(Dog dog){ dog.eat(); } }
publicclassPet{privateString name ="无名氏";// 昵称privateinthealth =100;// 健康值privateintlove =0;// 亲密度/**
* 方法eat(),负责宠物吃饭功能。
*/publicvoideat();/**
* 有参构造方法。
* @param name 昵称
*/publicPet(){ }publicPet(String name){this.name = name; }publicvoidsetName(String name){this.name = name; }publicvoidsetHealth(inthealth){this.health = health; }publicvoidsetLove(intlove){this.love = love; }publicStringgetName(){returnname; }publicintgetHealth(){returnhealth; }publicintgetLove(){returnlove; } }
publicclassDogextendsPet{privateString strain;// 品种/** * 有参构造方法。 *@paramname 昵称 *@paramstrain 品种 */publicDog(String name, String strain){super(name);this.strain = strain; }publicStringgetStrain(){returnstrain; }/**
* 重写吃食方法。
*/publicvoideat(){if(getHealth()>=100){ System.out.println("狗狗"+this.getName() +"吃饱了,不需要喂食了!"); }else{this.setHealth(this.getHealth()+3); System.out.println("狗狗"+this.getName() +"吃饱啦!健康值增加3。"); } }}
如果再领养新种类XXX的宠物,就需要给XXX喂食,怎么办?
添加XXX宠物类,继承Pet类,实现吃食方法
修改Master类,添加给XXX宠物喂食的方法
可以发现随着程序的不断扩展,需要对源程序进行不断的修改,这不符合程序的设计原则
频繁修改代码,程序的可扩展性、可维护性变得很差
使用多态优化设计 修改Master 类的eat()方法 将参数 改为Pet类型 实现一个方法可以 对所有宠物喂食publicvoidfeed(Pet pet){//父类的引用指向子类的对象pet.eat(); } 调用Master类的喂食方法时可以传入其子类对象 从而调用不同子类的喂食方法
下溯造成:父类-- >子类 直接强转会报类型转换错误,要求父类对象必须是由子类对象向上转换过的,才可以向下转换 类型转换这部分在讲解时,讲解时学生能够知道有这样一种写法。 但是大多数学生不理解为什么要这么去写。所有需要设置一个案例,使学生能够理解向上造型的用途。 例:生产汽车根据不同的的参数 返回不同类型的汽车类 但方法的返回值是 汽车的父类 抽象类abstract:该类不需要创建对象,提出了一个概念,其中的方法有子类实现。 特点:抽象类不能实例化 抽象类中可以有普通方法,可以有抽象方法 向子类提供父类的定义,抽象类就是给其他类继承的 子类继承抽象类:普通类必须实现抽象方法,抽象子类不实现 抽象类作用:为子类提供一个公共的类型; 抽象类的应用——模板设计模式 例如,现在有三类事物: (1)机器人:充电,工作; (2)人:吃饭,工作,睡觉; (3)猪:进食,睡觉。 现要求实现一个程序,可以实现三种不同事物的行为。 所有的子类如果要想正常的完成操作,必须按照指定的方法进行覆写才可以 而这个时候抽象类所起的功能就是一个类定义模板的功能。 定义一个Employee抽象基类 公司有以下几种员工: 开发人员:工资计算方式,每月固定工资 销售人员:底薪+提成 小时工:按工作时间付工资,每小时30元 创建不同类型的3名员工对象,计算他们应付的月工资之和
publicabstractclassEmployee{privateString name;publicEmployee(String name){this.name ="@"+ name +"@"; }protectedabstractintpaySalary();}
//开发人员publicclassDeveloperextendsEmployee{privateintsalary;publicDeveloper(String name,intsalary){super(name);this.salary = salary; }@Override//方法重写注解protectedintpaySalary(){returnsalary; }}
//销售人员publicclassSaleManextendsEmployee{privateintsalary;privateintcomm;//提成publicSaleMan(String name,intsalary,intcomm){super(name);this.salary = salary;this.comm = comm; }@OverrideprotectedintpaySalary(){returnsalary + comm; }}
//小时工publicclassHourlyWorkerextendsEmployee{privateinthours;//这个月工作了多少小时publicHourlyWorker(String name,inthours){super(name);this.hours = hours; }@OverrideprotectedintpaySalary(){return30*hours; }}
publicclassMain{publicstaticvoidmain(String[] args){ Employee[] employees =newEmployee[3]; employees[0] =newDeveloper("张三",5000); employees[1] =newSaleMan("李四",2000,500); employees[2] =newHourlyWorker("冯六",200);//计算总工资inttotal =0;for(inti =0; i < employees.length; i++) { total += employees[i].paySalary(); } System.out.println("总共需要支付"+ total); }}
关键字final修饰类: 该类不能被继承 修饰属性和变量:赋值后不允许修改数值,地址不能改变 修饰方法:方法不能被重写final练习演示 思考一个有趣的现象:byteb1=1;byteb2=3;byteb3=b1+b2;//当程序执行到这一行的时候会出错,因为b1、b2可以自动转换成Int类型的变量,运算时java虚拟机对它进行了转换,结果导致把一个int赋值给byte-----出错如果对b1 b2加上final就不会出错finalbyteb1=1;finalbyteb2=3; 关键字abstract和final不能同时使用 接口 Interface:几类完全不同的事物,拥有同样的行为,这种行为定义在接口中。接口是一种标准,一种协议,一种规范 USB接口本身没有实现任何功能 USB接口规定了数据传输的要求 USB接口可以被多种USB设备实现 接口的特点: 接口不是类 接口中定义的只能是抽象方法,无论是否书写abstract关键字 接口中属性,必须是final修饰—常量 ,无论是否写了final一个类可以实现多个接口, 接口可以继承接口(多继承) 实现接口的演示publicinterfaceUsbInterface{//USB接口提供服务。voidservice();}publicclassUDiskimplementsUsbInterface{publicvoidservice(){ System.out.println("连接USB口,开始传输数据。"); } } 接口在多态中的体现:1.继承或实现2.重写3.父类(接口)的声明指向子类的对象 接口和抽象类的区别: 一个是类,一个是接口 抽象类可以有抽象方法,也可以有普通方法,接口中都是抽象方法 抽象类中可以有普通的属性,接口中是常量
接口使用练习publicclassUnionPayTest{publicstaticvoidmain(String[] args){ ICBCImpl card1 =newICBCImpl(10000,"qwer12"); Scanner scan =newScanner(System.in); System.out.println("请输入密码:");if(card1.checkPwd(scan.next())){ System.out.println("请输入金额:");if(card1.drawMoney(scan.nextDouble())){ System.out.println("所剩金额:"+card1.getBalance()); }else{ System.out.println("金额不足"); } }else{ System.out.println("密码错误"); } }}interfaceUnionPay{publicdoublegetBalance();//查看余额publicbooleancheckPwd(String input);//检查密码publicbooleandrawMoney(doublenumber);//取钱}interfaceICBCextendsUnionPay{publicvoidpayOnline(doublenumber);//在线支付}interfaceABCextendsUnionPay{publicbooleanpayTelBill(String phoneNum,doublesum);//支付电话费}classICBCImplimplementsICBC{privatedoublemoney;//账户余额privateString pwd;//账户密码publicICBCImpl(doublemoney,String pwd){this.money = money;this.pwd = pwd; }publicdoublegetBalance(){returnmoney; }publicbooleancheckPwd(String input){if(pwd.equals(input)){returntrue; }else{returnfalse; } }publicbooleandrawMoney(doublenumber){if(money-number>0){ money-=number;returntrue; }else{returnfalse; } }publicvoidpayOnline(doublenumber){if(money>=number){ money-=number; } }}classABCImplimplementsABC{privatedoublemoney;privateString pwd;publicABCImpl(doublemoney,String pwd){this.money = money;this.pwd = pwd; }publicdoublegetBalance(){returnmoney; }publicbooleancheckPwd(String input){if(pwd.equals(input)){returntrue; }returnfalse; }publicbooleandrawMoney(doublenumber){if(money-number>-2000){ money-=number;returntrue; }else{returnfalse; } }publicbooleanpayTelBill(String phoneNum,doublesum){if(phoneNum.length()==11&& money-sum>-2000){ money-=sum;returntrue; }else{returnfalse; } }}
静态static: 类和对象的关系,类是对象的模板,类中有属性和方法 Static修饰属性:所有对象共享该属性 Static修饰方法:所有对象共享该方法 被static修饰的属性和方法属于类,而不属于某个对象 静态方法中不能直接使用非静态属性和方法,只能调用其他的静态属性和方法 非静态方法可以直接调用普通资源和静态资源static可以修饰的元素和使用特点static可以修饰 属性 方法 和 代码块static修饰属性 :静态变量 所有对象共享 在类被载入时创建,只要类存在,static变量就存在 通过类名.属性名 / 对象.属性名 进行访问static修饰方法:静态方法 不需要实例化对象 可以直接通过类名.方法名 访问 实例化对象后 可以 对象.方法名 访问 注意事项: 静态方法只能直接访问静态变量 不能直接访问成员变量 静态方法中不能使用super和this关键字 静态方法不能被覆盖(重写)static修饰块:静态块 有static修饰的语句块 不包含任何方法体的代码块 当类被加载时 静态块被执行 并且只执行一次 常用于类属性的初始化变量的作用域: 类变量: 用static修饰的成员变量,它们在类被载入时创建,只要类存在,static变量就存在 实例变量: 类体中声明的成员变量,即非static的属性,创建对象后存在 局部变量: 方法体中声明的变量,方法中的参数,或代码块中声明的变量,都是局部变量。局部变量只在方法调用的过程中有效,方法调用结束后失效 单例模式:在系统中该类只有一个实例化对象 在系统中某些类只需要一个对象就可以完成所有操作,会将类设计为单例模式以节省系统的开销 分为:饿汉模式 ,懒汉模式 Java的异常处理机制是Java程序在编译或运行期间,发生的不可预期的意外,造成程序不能继续执行的情况Java中的异常是被管理起来的,当程序发生异常,会创建出一个异常的对象Throwable 所有异常的父类Error错误:天灾 人力不可抗拒 计算机硬件的问题,比如:硬盘坏了,内存掉电java.lang.Exception 异常: 人祸 主要是因为程序开发者不严谨造成的问题,可以通过代码来修补和解决 检查性异常(编译) 强制要求在代码中处理异常 运行时异常(运行) java.lang.RuntimeException 非检查性异常 不强制在代码中处理异常 java.lang.ArrayIndexOutOfBoundsException 数组下标越界异常 IndexOutOfBoundsException 下标越界异常 java.lang.ArithmeticException 除数为0异常 (整数) 浮点数:6.0/0Infinity无穷大NaN非数 Not aNumberjava.lang.NullPointerException 空指针异常 (重点) 调用了null值的属性或方法 (null值没有任何属性和方法)if(o !=null){ o.toString(); }else{ .. } java.lang.ClassCastException 引用数据类型类型转换异常 父类向子类转换时发生的异常(下溯造型时发生) binstanceofBtrue变量b是B类的一个对象 flase 变量b不是B类的一个对象if(oinstanceofB){ B b = (B)o; }else{ .. } 异常的处理1.上报/抛出throw人工制造异常 throws 表示某个方法向上抛出异常 面试:throw和throws的区别2.捕获try{ 尝试执行代码 }catch(Exception e){ 发生异常时捕获,执行此处 }finally{ 无论如何都会执行 } final和finally的区别? final: 最终关键字 修饰类:不能被继承 修改方法:不能被重写 修改属性:常量finally:异常捕获最终块:finally中的代码在try包的概念: 什么是包 包的作用: 例window文件系统 使用文件夹可以解决文件同名问题 使文档分门别类易于查找 包的命名方式:组织的域名反写 Java源文件与包的位置关系
将一个正整数分解质因数。例如:输入90,打印出90=233*5。
提示:对n进行分解质因数,应先找到一个最小的质数k,然后按下述步骤完成:
(1)如果这个质数恰等于n,则说明分解质因数的过程已经结束,打印出即可。
(2)如果n>k,但n能被k整除,则应打印出k的值,并用n除以k的商,作为新的正整数你n,重复执行第一步。
(3)如果n不能被k整除,则用k+1作为k的值,重复执行第一步