javaSE基础
变量
1、变量就是数据存储空间的表示。
2、标识符命名规则:变量名=首字母+其余部分
①首字母:字母、下划线、“$”符号(开头)
②其余部分:数字、字母、下划线“$”
③应避开关键字:int int = 10;(不可)
④符合驼峰命名法:若名字由多个单词组成,从第二个单词开始,首字母均大写:myShoolScore
⑤不能使用保留字来命名(51个关键字)如下:
数据类型:
Boolean int long short byte float double char class interface
流程控制:
if else do while for switch case default break continue return try catch finally
修饰符:
public protected private final void static strictfp abstract transient
synchronized volatile native
动作:
package import throw throws extends implements this Super instanceof new
保留字:
true false null goto const
数据类型
①java语言是强类型语言,对每一种数据都定义了明确的具体数据类型,在内存中分配了不同大小的内存空间。
数据类型 | 基本类型 | 布尔类型boolean | 默认值false |
数值类型 | 整数类型byte/short/int/long/char 默认值0,0,0,0,\u0000 | ||
封装类* int Integer * short Short * long Long * byte Byte * boolean Boolean * float Float* * double Double * char Character |
|||
浮点类型float/double 默认值0.0F,0.0Double | |||
引用类型 | 类class | ||
接口interface | |||
数组 | |||
空类型null |
布尔型(boolean): true(正确)/false(错误) 在java当中两个数字比较, 使用==号 |
字符型(char): 候只能定义单个字符, 也就是单个汉字, 使用单引号。 |
字节型(byte): |
短整型(short): |
整型(int): |
长整型(long): 需要在后面加上l, 表示定义的是长整型 |
单精度浮点型(float): |
双精度浮点型(double): |
引用数据类型 (String): 注意:表示字符串的时候, 使用""引号 |
②基本类型转换:
自动类型转换(隐含转换)
byte->short(char)->int->long->float->double
在某种条件下,系统自动完成类型转换也称隐含转换:两种类型兼容、目标类型大于源类型、对于表达式,如果一个操作数为double型,则整个表达式可
提升为double型。
强制类型转换(显示转换)
使用强制转换,可能丢失精度
在一定条件下,程序员手动完成的类型转换:两种类型兼容、一般目标类型小于源类型。
③变量作用域
全局变量:在整个类中都可以使用的变量。
局部变量:在某一个方法或者是一个模块当中能够使用的变量。
package com.eduask.tzy; public class VarDemo { public static void main(String[] args) { // 自动类型转换 byte num1 = 10; int num2 = num1; System.out.println(num2); long num3 = num2; System.out.println(num3); float f = 10.5f; double d = f; System.out.println(d);//10.5 int num4 = 100; float num5 = num4; System.out.println(num5);//100.0 char c1 = 'a'; int num6 = c1; System.out.println(c1);//a System.out.println(num6); System.out.println(c1+10);//107 //强制类型转换 int num7 = 10; short num8 =(short)num7; System.out.println(num8); float num9 = (float)10.25; System.out.println(num9);//10.25 int num10 = 65; char num11 = (char) num10; System.out.println(num11);//A int num12 = 10; double num13 = 10.6; double res = num12+num13; System.out.println(res);//20.6 } }
数据类型案例
运算符
①程序是由许多语句组成的,语句的基本单位是表达式。表达式由操作数和运算符组成。
②运算符:
一、算术运算符
算术运算符主要用于进行基本的算术运算,如加法、减法、乘法、除法等。
Java 中常用的算术运算符:
其中,++ 和 -- 既可以出现在操作数的左边,也可以出现在右边,但结果是不同滴;单独使用++ - -的时候都是自身加减1。
例1:
运行结果:
a:6
b:6
例2:
运行结果:
a:6
b:5
一定要注意哦!自增和自减运算符只能用于操作变量,不能直接用于操作数值或常量!例如 5++ 、 8-- 等写法都是错误滴!
PS:% 用来求余数,也称为”取模运算符“
package com.eduask.tzy; public class VarDemo { public static void main(String[] args) { int age1=24; int age2=18; int age3=36; int age4=27; int sum=age1+age2+age3+age4; double avg=sum/4; int minus=Math.abs(age1-age2); int newAge=--age1; System.out.println("四个年龄的总和:"+sum);//四个年龄的总和:105 System.out.println("四个年龄的平均值:"+avg);//四个年龄的平均值:26.0 System.out.println("age1 和 age2年龄差值:"+minus);//age1 和 age2年龄差值:6 System.out.println("age1自减后的年龄:"+newAge);//age1自减后的年龄:23 } }
例子
例3:
package com.eduask.tzy; public class VarDemo { public static void main(String[] args) { int number1 = 5; int number2 = 6; String str = "今天天q不错13123###"; System.out.println(number1+number2+str);//11今天天q不错13123### } }
注意:String字符串在拼接的时候,我们通常用"+"来拼接
注意:如果是不同类型的字符串拼接,如int和String拼接,如果int类型的变量在前面,
则+号会进行运算后在拼接后面的字符串,如果是字符串在前面,那么后面的int类型的变量
直接就拼接在String字符串后面了。
例如:int number1 = 5;
int number2 = 6;
String str = "今天天q不错13123###";
System.out.println(number1+number2+str);
符号:换行(\n) 制表符(\t) \(\\) 双引号(\”\”) 单引号(\”)
二、赋值运算符
赋值运算符是指为变量或常量指定数值的符号。如可以使用 “=” 将右边的表达式结果赋给左边的操作数。
Java 支持的常用赋值运算符,如下表所示:
package com.eduask.tzy; public class VarDemo { public static void main(String[] args) { int one = 10 ; int two = 20 ; int three = 0 ; three=one+two; System.out.println("three = one + two ==> "+three);//three = one + two ==> 30 three+=one; System.out.println("three += one ==> "+three);//three += one ==> 40 three-=one; System.out.println("three -= one ==> "+three);//three -= one ==> 30 three*=one; System.out.println("three *= one ==> "+three);//three *= one ==> 300 three/=one; System.out.println("three /= one ==> "+three);//three /= one ==> 30 three%=one; System.out.println("three %= one ==> "+three);//three %= one ==> 0 } }
例子
三、比较运算符
比较运算符用于判断两个数据的大小,例如:大于、等于、不等于。比较的结果是一个布尔值( true 或 false )。
Java 中常用的比较运算符如下表所示:
注意哦:
1、 > 、 < 、 >= 、 <= 只支持左右两边操作数是数值类型
2、 == 、 != 两边的操作数既可以是数值类型,也可以是引用类型
package com.eduask.tzy; public class VarDemo { public static void main(String[] args) { int a=16; double b=9.5; String str1="hello"; String str2="imooc"; String str3="imooc"; System.out.println("a等于b:" + (a == b));//a等于b:false System.out.println("a大于b:" + (a > b));//a大于b:true System.out.println("a小于等于b:" + (a < b));//a小于等于b:false System.out.println("str1等于str2:" + (str1.equals(str2)));//str1等于str2:false System.out.println("str3等于str2:" + (str3.equals(str2)));//str3等于str2:true } }
例子
ps: 1、java中equals和==的区别 值类型是存储在内存中的堆栈(简称栈),而引用类型的变量在栈中仅仅是存储引用类型变量的地址,而其本身则存储在堆中。
2、==操作比较的是两个变量的值是否相等,对于引用型变量表示的是两个变量在堆中存储的地址是否相同,即栈中的内容是否相同。
3、equals操作表示的两个变量是否是对同一个对象的引用,即堆中的内容是否相同。
4、==比较的是2个对象的地址,而equals比较的是2个对象的内容,显然,当equals为true时,==不一定为true。
四、逻辑运算符
逻辑运算符主要用于进行逻辑运算。Java 中常用的逻辑运算符如下表所示:
逻辑与& 逻辑或| (上面是短路与或的写法:常用)
我们可以从“投票选举”的角度理解逻辑运算符:
1、 与:要求所有人都投票同意,才能通过某议题
2、 或:只要求一个人投票同意就可以通过某议题
3、 非:某人原本投票同意,通过非运算符,可以使其投票无效
4、 异或:有且只能有一个人投票同意,才可以通过某议题
当使用逻辑运算符时,我们会遇到一种很有趣的“短路”现象。
譬如:( one > two ) && ( one < three ) 中,如果能确定左边 one > two 运行结果为 false , 则系统就认为已经没有必要执行右侧的 one < three 啦。
同理,在( one > two ) || ( one < three ) 中,如果能确定左边表达式的运行结果为 true , 则系统也同样会认为已经没有必要再进行右侧的 one < three 的执行啦!
package com.eduask.tzy; public class VarDemo { public static void main(String[] args) { boolean a = true; // a同意 boolean b = false; // b反对 boolean c = false; // c反对 boolean d = true; // d同意 //a与b都必须要同意才能通过 System.out.println((a && b) + " 未通过");//false 未通过 //a与b必须有一人同意才能通过 System.out.println((a || b) + " 通过");//true 通过 //a为反对才能通过 System.out.println((!a) + " 未通过");//false 未通过 //c与d中必须有且只有一人同意才能通过 System.out.println((c ^ d) + " 通过");//true 通过 } }
例子
五、条件运算符
条件运算符( ? : )也称为 “三元运算符”。
语法形式:布尔表达式 ? 表达式1 :表达式2
运算过程:如果布尔表达式的值为 true ,则返回 表达式1 的值,否则返回 表达式2 的值
例如:
因为,表达式 8>5 的值为 true ,所以,返回: 8大于5
package com.eduask.tzy; public class VarDemo { public static void main(String[] args) { int score=68; String mark =(score>=60)?"及格":"不及格"; System.out.println("考试成绩如何:"+mark);//考试成绩如何:及格 } }
例子
六、位运算符(就是对二进制的直接运算,所有位运算都会把值转为二进制进行运算 )
&(与) AND 只有对应的两个二进位均为1时,结果才为1,否则为0;
|(或) OR 只要对应的两个二进位有一个为1时,结果位就为1;
^(异或) XOR 当两对应的二进位相异时,结果位为1;
~(非) NOT 其功能是对参与运算的数的各二进位按位求反;
>>(右移) 往右位移,正数左边补0,负数补1;
<<(左移) 往左位移,右边补0
>>>(右移,左边空出的位以0填充) 往右位移,左边补0;
顾名思义,位运算符用于位运算,那就只能对整型或者字符型进行运算。而除了~(非)是一元运算符之外其他的都为二元运算符。
package com.eduask.tzy; public class VarDemo { public static void main(String[] args) { //计算机内部的数据都是以二进制形式存在的 /* * 而二进制在计算机内部又有多种编码方式存在 * 计算机内部对二进制进行运算用的是补码。 * 比如:1-1=1+(-1)=0;(这样就没有减法了) * 原码:(byte 8位) 3 :0000 0011 第一位是符号位,0代表正,1代表负。 * * 反码:正数的反码和原码一致,负数的反码,保留符号位,其余按位取反。 * 如:(byte 8位) -3 :1000 0011(原码)-->1111 1100(反码) * * 补码:正数的反码和原码和补码都一样,负数的补码=反码+1; * 如:(byte 8位) -3 :1000 0011(原码)-->1111 1100(反码)-->1111 1101(补码) * 负数的原码和补码之间的转换 * 负数的原码=负数的补码-1 在取反 * 负数的原码=负数的补码取反+1 * 10001(原码)--》11110+1=11111; * 11111-1 = 11110--》10001; * 11111--》10000+1=10001; * 总结 负数原码取反+1是补码 补码取反+1是原码. */ int num1 = 128; int num2 = 129; System.out.println("num1与num2的结果是"+(num1&num2));//num1与num2的结果是128 /* 0000 0000 0000 0000 0000 0000 1000 0000(补) 0000 0000 0000 0000 0000 0000 1000 0001(补) ------------------------------------------ 0000 0000 0000 0000 0000 0000 1000 0000(补) */ System.out.println("num1或num2的结果是"+(num1|num2));//num1或num2的结果是129 /* 0000 0000 0000 0000 0000 0000 1000 0000(补) 0000 0000 0000 0000 0000 0000 1000 0001(补) ------------------------------------------ 0000 0000 0000 0000 0000 0000 1000 0001(补) */ System.out.println("num1非的结果是"+(~num1));//num1非的结果是-129 /* 0000 0000 0000 0000 0000 0000 1000 0000(补) ------------------------------------------ 1111 1111 1111 1111 1111 1111 0111 1111(补) ------------------------------------------ 1000 0000 0000 0000 0000 0000 1000 0001(负数的原码) */ System.out.println(2<<3);//=2*2^3 16 /* 0000 0000 0000 0000 0000 0000 0000 0010(补) 0000 0000 0000 0000 0000 0000 0001 0000(补) */ System.out.println(-2<<3);//=-2*2^3 -16 /* 1000 0000 0000 0000 0000 0000 0000 0010(原码) 1111 1111 1111 1111 1111 1111 1111 1101(反) 1111 1111 1111 1111 1111 1111 1111 1110(补) 1111 1111 1111 1111 1111 1111 1111 0000(补)左移三位 ----------------------------------------------- 1000 0000 0000 0000 0000 0000 0000 1111 +1 ----------------------------------------------- 1000 0000 0000 0000 0000 0000 0001 0000 -16 */ System.out.println(16>>3);//=16/2^3 2 /* 0000 0000 0000 0000 0000 0000 0001 0000(补) 0000 0000 0000 0000 0000 0000 0000 0010(补) */ System.out.println(-16>>3);//=-16/2^3 -2 /* 1000 0000 0000 0000 0000 0000 0001 0000(原码) 1111 1111 1111 1111 1111 1111 1110 1111(反) 1111 1111 1111 1111 1111 1111 1111 0000(补) 1111 1111 1111 1111 1111 1111 1111 1110(补)右移三位 ----------------------------------------------- 1000 0000 0000 0000 0000 0000 0000 0001 +1 ----------------------------------------------- 1000 0000 0000 0000 0000 0000 0000 0010 */ System.out.println(-16>>>3); /* 1000 0000 0000 0000 0000 0000 0001 0000(原码) 1111 1111 1111 1111 1111 1111 1110 1111(反) 1111 1111 1111 1111 1111 1111 1111 0000(补) 0001 1111 1111 1111 1111 1111 1111 1110(补)无符号右移三位 */ //=2^29-2 536870910 } }
例子
if语句-------switch语句
分支结构 if 嵌套 (想写多少写多少) |
switch分支语句: switch(整型|字符|String|枚举){ case 常量1:{《--等于常量1:执行 |
package com.eduask.tzy; public class VarDemo { public static void main(String[] args) { int cash = 500; if (cash == 500) { System.out.println("一定在做梦"); } System.out.println("哈哈"); /*一定在做梦 * 哈哈*/ //当if语句块中只有一条指令的时候,可以省略大括号。不推荐省略。 } }
例子1
package com.eduask.tzy; public class VarDemo { public static void main(String[] args) { int cash = 500; char currency = '$'; if (cash >= 500) { System.out.println("买别墅"); }else{ System.out.println("买公寓"); } //买别墅 int a = 10; int b = 1; int c ; if(a<b){ c=a; }else{ c=b; } System.out.println(c);//1 //条件表达式(三元运算符)简单if...else...语句 c = (a<b)?a:b; System.out.println(c); if(cash>=500){ if(currency=='$'){ System.out.println("买独栋别墅"); }else{ System.out.println("买联排别墅"); } }else{ System.out.println("买公寓"); } //买独栋别墅 //多重if...else if(cash>500){ System.out.println("买环内"); }else if(cash>300){ System.out.println("买内环"); }else if(cash>200){ System.out.println("买外环"); }else if(cash>100){ System.out.println("买外环外"); }else{ System.out.println("努力赚钱"); } //买内环 } }
例子2
package com.eduask.tzy; import java.util.Scanner; public class VarDemo { public static void main(String[] args) { Scanner sc = new Scanner(System.in); System.out.println("请输入1-5之间的一个数"); int number = sc.nextInt(); /*if(number==1){ }else if(number==2){ }else if(number==3){ }else if(number==4){ }else if(number==5){ }else{ }*/ /*1、case后面列出的常量不能重复; *2、break是可以省略的,但是case相当于开关,打开了如果不关那么会把后面所有的语句执行完或者执行碰到第一个break结束; *3、case的顺序是可以颠倒的;default也可以放在开头,但是一般不这么写 *4、swicth使用来匹配常量的、能匹配的类型有byte,short,int,char,String(jdk1.7才有),enum(jdk1.5才有) *5、switch和多重if...else语句比较 *switch适合做等值判断,不适合区间判断 *多重if语句功能比switch更全面; **/ switch(number){ case 1: System.out.println("您输入的是1**"); break; case 2: System.out.println("您输入的是2**"); break; case 3: System.out.println("您输入的是3**"); break; case 4: System.out.println("您输入的是4**"); break; case 5: System.out.println("您输入的是5**"); break; default: System.out.println("error"); // break;//可以去,因为在末尾 } } }
例子3
package com.eduask.tzy; import java.util.Scanner; public class Demo { public static void main(String[] args) { /*做万年历 * 1、请出入年 * 2、判断闰年 * 3、判断月*/ int year; int month; int days = 0 ;//保存日期 boolean isRn;//闰年保存true,否则false; System.out.println("****使用万年历****"); Scanner sc = new Scanner(System.in); System.out.println("请输入年"); year = sc.nextInt(); System.out.println("请输入月"); month = sc.nextInt(); if((year%400==0)||(year%4==0&&year%100!=0)){ isRn = true; }else{ isRn = false; } if(isRn){ System.out.println(year+"闰年"); }else{ System.out.println(year+"非闰年"); } // if(month==1||month==3||month==5||month==7||month==8||month==10||month==12){ // days = 31; // }else if(month==2){ // if(isRn){ // days=29; // }else{ // days=28; // } // }else if(month==4||month==6||month==9||month==11){ // days=30; // }else{ // System.out.println("输入有误"); // } switch(month){ case 1: case 3: case 5: case 7: case 8: case 10: case 12: days = 31; break; case 2: if(isRn){ days=29; }else{ days=28; } break; case 4: case 6: case 9: case 11: days =30; break; default: System.out.println("输入有误"); } System.out.println(year+"年"+month+"月"+days+"日"); } }
一波万年历
循环
重复做一件事儿就是循环
语法: 无限循环(死循环):服务器不停止就永远不会结束 双重for循环(循环的嵌套): } 循环的跳出 break:打破,直接跳出(停止当前循环) continue:越过,直接越过当前循环,后面的循环依然要执行 break和continue都跟for循环是一一对应的, 可以加入标记(后跟标签)跳转至该标签处。如在某个循环外 a: while(true){break i ;} |
while循环: do while循环: 例子: 先执行DO里面的过程,在判断WHILE条件 (至少执行一次) |
package com.eduask.tzy; import java.util.Scanner; public class Demo { public static void main(String[] args) { Scanner sc = new Scanner(System.in); System.out.println("请输入整数"); int number = sc.nextInt(); while(number!=0){ int res = number%10; System.out.print(res); number/=10; } } }
例1
package com.eduask.tzy; import java.util.Scanner; public class Demo { public static void main(String[] args) { int n = 0;//要被加的数 int sum = 0;//累加求和 do{ n++; sum+=n; }while(sum<=0); System.out.println("sum:"+sum); System.out.println("n:"+n); //sum:1 n:1 } }
例2
package com.eduask.tzy; import java.util.Scanner; public class Demo { public static void main(String[] args) { for (int i = 0; i < 10; i++) { System.out.println(i); }//0-9 System.out.println(""); System.out.println(""); System.out.println(""); // for循环的3个表达式都可以省略 // 表达式1可以省略,我们可以把他放在for语句之前 // 表达式二省略会导致死循环,条件永远为true // 表达式3省略,可能也会导致条件永远成立,会形成死循环 int j = 0; for (; j < 10;) { j++; System.out.println(j); }//1-10 } }
例3
注意:
①while循环是不确定型循环(循环次数不确定)
②for循环确定型循环(循环次数确定)
③while循环和for循环可以相互转换
package com.eduask.tzy; import java.util.Scanner; public class Demo { public static void main(String[] args) { /*做万年历 * 1、请出入年 * 2、判断闰年 * 3、判断月*/ int year; int month; int days = 0 ;//保存日期 boolean isRn;//闰年保存true,否则false; int totalDays =0; System.out.println("****使用万年历****"); Scanner sc = new Scanner(System.in); System.out.println("请输入年"); year = sc.nextInt(); System.out.println("请输入月"); month = sc.nextInt(); if((year%400==0)||(year%4==0&&year%100!=0)){ isRn = true; }else{ isRn = false; } if(isRn){ System.out.println(year+"闰年"); }else{ System.out.println(year+"非闰年"); } //计算年的总天数 for(int i=1900;i<year;i++){ if((i%400==0)||(i%4==0&&i%100!=0)){ totalDays += 366; }else{ totalDays += 365; } } //计算输入月份之前的天数 for(int i =1;i<=month;i++){ switch(i){ case 1: case 3: case 5: case 7: case 8: case 10: case 12: days = 31; break; case 2: if(isRn){ days=29; }else{ days=28; } break; case 4: case 6: case 9: case 11: days =30; break; default: System.out.println("输入有误"); } // 输入月的天数保存到days中,但没有累加进去 if(i!=month){ totalDays += days; } } // 求出星期几,其实就是前面的\t的个数 int beforeDays; beforeDays = 1+totalDays%7; if(beforeDays==7){ beforeDays=0;//代表星期天,0个\t } System.out.println("星期天\t星期一\t星期二\t星期三\t星期四\t星期五\t星期六"); for(int i=0;i<beforeDays;i++){ System.out.print("\t"); } for(int i=1;i<days;i++){ System.out.print(i+"\t"); //满7个换行 if((i+beforeDays)%7==0){ System.out.println(); } } } }
完善万年历
数组
一维数组 它是一种数据结构,用来存储元素。 语法: 1)数据类型 [] 数组名 = new 数据类型 [元素个数]; 2)数据类型 数组名 [] = new 数据类型 [元素个数]; 3)数据类型 [] 数组名 = null; 数组名 = new 数据类型 [元素个数]; 4)数据类型 [] 数组名 = new 数据类型 []{定义具体的元素}; 5)数据类型 [] 数组名 = {定义具体的元素}; 注意:此语法定义的数组元素个数(数组长度)的通过大括号里面的定义的具体元素的个数决定的 注意:new 相当于在内存里面开辟的一个空间用来存储数据 数组的取值: 数组名[下标位数] 可以使用for循环来赋值或者取值,其中的条件可以调用数组的.length属性 注意:数组下标位数是从0开始计数的 数组在使用new关键字开辟内存空间时候,如果没有给其元素赋值,那么不同的数据类型都有一个默认值 int---->0 double---->0.0 String---->null char---->' '(是个空格) boolean---->false 数组常见异常: java.lang.ArrayIndexOutOfBoundsException(数组下标越界) 访问的数组元素下标超过了数组本身的长度。或者是负数 java.lang.NullPointerException(空指针异常) 在数组当中,它的元素是null,在你取值的时候,就会报空指针异常 |
二维数组: 然后再去取一维数组中的元素 静态初始化:int [][] arrayes = {{12},{123,3333,5555},{22,12}}; 动态初始化:String[][] arrStr = new String[3][]; arrStr[0]=new String[1]; arrStr[1]=new String[3]; arrStr[2]=new String[2]; arrStr[0][0]=new String("12"); arrStr[1][0]=new String("123"); arrStr[1][1]=new String("3333"); arrStr[1][2]=new String("5555"); arrStr[2][0]=new String("22"); arrStr[2][1]=new String("12"); |
package com.eduask.tzy; import java.util.Scanner; public class Demo { public static void main(String[] args) { // 先声明后创建 int[] array = new int[3]; int[] array4 = new int[3]; char[] array1 = new char[2]; String[] array2 = new String[3]; System.out.println(array.length); System.out.println(array[0]); System.out.println(array1.length); System.out.println(array1[0]);// 一个空格 System.out.println(array2.length); System.out.println(array2[0]);// null // 静态赋值 array[0] = 21; array[1] = 24; array[2] = 24; // array[3]=2; java.lang.ArrayIndexOutOfBoundsException // 动态赋值 Scanner input = new Scanner(System.in); for (int i = 0; i < array4.length; i++) { System.out.println("请输入数组值"); array4[i] = input.nextInt(); } // 通过for循环进行统一遍历 for (int i = 0; i < array4.length; i++) { System.out.println(array4[i]); } /* * forecah循环 语法: foreach(数据类型 变量名 : 数组(集合)) { 循环体 } * 注意:增强for循环一般不用于对数组元素的值进行修改,而是多用于对数组元素值的输出。 例子: */ // int[] array3 = {10,20,30}; int[] array3 = new int[] { 1, 2, 3, 5, 4, 7, 8, 9, 6, 4, 7, 7 }; for (int i : array3) { System.out.println(i); } } }
例1
package com.eduask.tzy; import java.util.Scanner; public class Demo { //线性查找法 public static void main(String[] args) { int [] array = {10,100,80,50,70,60,90}; System.out.println("请输入要查找的数"); Scanner sc = new Scanner(System.in); int number = sc.nextInt(); int index = -1;//保存找到数所在的数组中的下标,找不到=-1 for (int i = 0; i < array.length; i++) { if(array[i]==number){ index = i+1; break; } } if(index!=-1){ System.out.println("找到,在数组中第"+index+"位置"); }else{ System.out.println("您要查找的数不存在"); } //输入200 您要查找的数不存在 输入 70 找到,在数组中第5位置a } }
线性查找法
package com.eduask.tzy; import java.util.Scanner; public class Demo { public static void main(String[] args) { // 线性查找法二分查找法(必须是有序的) int[] array = { 1, 2, 3, 4, 5, 7, 9, 13, 14, 18 }; System.out.println("请输入要查找的数"); Scanner sc = new Scanner(System.in); int number = sc.nextInt(); int index = -1;// 保存找到数所在的数组中的下标,找不到=-1 int start = 0;// 起始下标 int end = array.length - 1;// 终止下标 int middle; while (start <= end) { // 找到中间下标所对应的元素值 middle = (start + end) / 2; if (number == array[middle]) { index = middle + 1; break; } // 假如要查找的那个数大于中间比较的那个数, // 去掉左边所有的数 if (number > array[middle]) { start = middle + 1; } if (number < array[middle]) { end = middle - 1; } } if (index != -1) { System.out.println("找到,在数组中第" + index + "位置"); } else { System.out.println("您要查找的数不存在"); } } }
二分查找法
常用的数组查找算法:
线性查找法:它又称之为顺序查找,在一列给定的值中进行搜索,从一端开始逐一检查每个元素,直到找到所需元素的过程;
二分查找法:它又称之为折半查找法。将数组中间位置记录的关键字与查找关键字比较,如果两者相等,则查找成功;否则利用中间位置记录将数组分成前、后两个子数组,
如果中间位置纪录的关键字大于查找关键字,则进一步查找前一子数组,否则进一步查找后一子数组。重复以上过程,直到找到或找不到为止。
常用的数组排序算法:
冒泡排序法:比较相邻的元素。如果第一个比第二个大,就交换他们两个,对每一对相邻元素做同样的工作,从开始第一对到结尾的最后一对,最后元素应该会是最大的数,
针对除了最后一个元素以外所有的元素重复以上的步骤。直到没有任何一对数字需要比较。
package com.eduask.tzy; public class Demo { public static void main(String[] args) { int[] array = { 1, 5, 3, 2, 6, 7, 9, 13, 51, 20 }; //N个数比较轮数为N-1次 for (int i = 0; i < array.length-1; i++) { //每一轮比较的次数为N-1-i; for (int j = 0; j < array.length-1-i; j++) { if(array[j]>array[j+1]){ //两个数做交换.通过设置临时变量 int temp = array[j]; array[j] = array[j+1]; array[j+1] = temp; } } } for (int i : array) { System.out.print(i+" "); } //1 2 3 5 6 7 9 13 20 51 } }
冒泡排序法
选择排序法:首先在未排序的序列中找到最小的元素,存放到排序序列的起始位置,然后,再从剩余未排序的元素中继续寻找最小元素,然后放到排序序列的末尾。以此类推。
package com.eduask.tzy; public class Demo { public static void main(String[] args) { int[] array = { 1, 5, 3, 2, 6, 7, 9, 13, 51, 20 }; int min = 0;//保存最小元素值的下标 for (int i = 0; i < array.length-1; i++) { min = i; //查找最小数在数组中的下标 for (int j = i+1; j < array.length; j++) { if(array[min]>array[j]){ min=j;//保存最小数的下标 } // 如果第i个最小的数位置不在i上,则进行交换 if(i!=min){ int temp = array[i]; array[i] = array[min]; array[min] = temp; } } } for (int i : array) { System.out.print(i+" "); } //1 2 3 5 6 7 9 13 20 51 } }
选择排序法
插入排序法:它是通过构建有序序列,对于未排序数据,在已排序序列中从后向前扫描,找到相应位置并插入。从后向前扫描过程中,需要反复把已排序元素逐步向后挪位,
为最新元素提供插入空间。
package com.eduask.tzy; public class Demo { public static void main(String[] args) { int[] array = { 20,25,15,42,36,16,12 }; for (int i = 1; i < array.length; i++) { int temp = array[i]; //把下标保存起来 int j = i; while(j>0&&temp<array[j-1]){ array[j] = array[j-1]; j--; } array[j]=temp;//插入数据 } for (int i : array) { System.out.print(i+" "); } //12 15 16 20 25 36 42 } }
插入排序法
一维数组之arrays类用法:
package com.eduask.tzy; import java.util.Arrays; public class Demo { public static void main(String[] args) { int[] arraySrc1 = { 1,3,4,5,6,2 }; int[] arrayDes1 = Arrays.copyOf(arraySrc1, 10); for (int i : arrayDes1) { System.out.print(i+" "); }//1 3 4 5 6 2 0 0 0 0 // Arrays.copyOf(original, newLength)复制指定的数组,截取或用 0 填充(如有必要),以使副本具有指定的长度。 System.out.println("\n\r*****************"); // Arrays.copyOfRange(original, from, to) 将指定数组的指定范围复制到一个新数组。 int[] arrayDes2 = Arrays.copyOfRange(arraySrc1,2,4); for (int i : arrayDes2) { System.out.print(i+" "); } System.out.println("\n\r*****************"); // Arrays.equals(a, a2)如果两个指定的 int 型数组彼此相等,则返回 true。 int[] arraySrc2 = { 1,3,4,5,6,2 }; boolean flag = Arrays.equals(arraySrc1,arraySrc2); System.out.println(flag);//true System.out.println("\n\r*****************"); int [] arrayDes3=new int[10]; // Arrays.fill(int[] a, int val) 将指定的 int 值分配给指定 int 型数组的每个元素 // Arrays.fill(arrayDes3,3); 会有10个3 // Arrays.fill(int[] a, int fromIndex, int toIndex, long val) // 将指定的 long 值分配给指定 long 型数组指定范围中的每个元素。 Arrays.fill(arrayDes3,2,5,3); for (int i : arrayDes3) { System.out.print(i+" "); }//0 0 3 3 3 0 0 0 0 0 System.out.println("\n\r*****************"); // Arrays.sort(int[] a);对指定的 int 型数组按数字升序进行排序。还可以对指定位置进行排序 Arrays.sort(arraySrc1); for (int i : arraySrc1) { System.out.print(i+" "); }//1 2 3 4 5 6 System.out.println("\n\r*****************"); // Arrays.binarySearch(a, key)使用二分搜索法来搜索指定的 int 型数组,以获得指定的值 int index = Arrays.binarySearch(arraySrc1, 5); System.out.println(index); System.out.println("\n\r*****************"); // System.arraycopy(Object src, int srcPos, Object dest, int destPos, int length) // 从指定源数组中复制一个数组,复制从指定的位置开始,到目标数组的指定位置结束。 int[]arrayDes5 = new int[10]; System.arraycopy(arraySrc1, 0, arrayDes5, 2, 5); for (int i : arrayDes5) { System.out.print(i+" "); }//0 0 1 2 3 4 5 0 0 0 } }
Arrays类使用
二维数组的建立
package com.eduask.tzy; import java.util.Arrays; public class Demo { public static void main(String[] args) { int[][] array =new int[3][]; // 每个高维数组指向一个低维的int数组 array[0]=new int[2]; array[1]=new int[3]; array[2]=new int[4]; //给低维的数组进行赋值 array[0][0]=1; array[0][1]=2; array[1][0]=3; array[1][1]=4; array[1][2]=5; array[2][0]=6; array[2][1]=7; array[2][2]=8; array[2][3]=9; for (int[] is : array) { System.out.print(is+" "); }//[I@659e0bfd [I@2a139a55 [I@15db9742 for (int[] is : array) { for (int i : is) { System.out.print(i+" "); }// 1 2 3 4 5 6 7 8 9 } } }
二维数组的建立
package com.eduask.tzy; public class Demo { public static void main(String[] args) { //杨辉三角 int row = 8;//行数 int[][]p = new int[row][row]; for (int i = 0; i < p.length; i++) { for (int j = 0; j <= i; j++) { //第一列和对角线列的元素值为1 if(j==0||j==i){ p[i][j]=1; }else{ //其他元素的值是其正上方和其左上方元素的和 p[i][j]=p[i-1][j]+p[i-1][j-1]; } } } for (int i = 0; i < p.length; i++) { for (int j = 0; j <= i; j++) { System.out.print(p[i][j]+" "); } System.out.println(); } } }
杨辉三角
面向对象
结构化程序设计——面向过程 程序=算法+数据结构 算法第一,数据结构第二 |
面向对象——oop 程序=对象+对象+。。。 数据第一,算法第二 关键:让每一个对象负责执行一组相关任务 |
面向对象编程的特性: 万物皆对象 程序是一组对象彼此之间的发送消息 |
面向对象的优点: 便于程序模拟实现世界中的实体: 用类封装建模实体对象的状态和行为。 隐藏细节: 对象的行为和状态被封装在类中,外界通过公开的接口- -调用类的方法来获得状态信息,不需关注内部细节如何实现。 可重用: 可以通过类模版,创建多个对象实例,重用类的定义代码。 |
Java对象的内存管理机制: 使用new创建对象,在堆内存分配对象空间、初始化。 在方法栈中定义局部变量,持有对堆内存中对象的引用。 方法执行完返回,占内存自动释放,局部变量销毁。 如果堆内存中对象没有变量引用它,成为垃圾, 由垃圾回收器回收,释放所占堆内存。 |
Java垃圾回收器: Java运行时系统有一个垃圾回收线程负责清除 不再使用的对象,俗称垃圾回收器。 垃圾回收器定期扫描内存,对于被使用的对象 加上标记,按可能的路径扫描结束后清除未加 标记的对象。 被回收的对象是: 不再被任何变量引用的对象; 引用变量自动放弃; 人为将引用变量置为null; |
类: 类是创建对象的模版和蓝图; 类是一组类似对象的共同抽象定义; 定义一个类的步骤: 1、定义类名; 2、编写类的字段代表属性; 3、编写类的方法代表行为; 类的建模是一个抽象和封装的过程: 抽象:去掉不关注的、次要的信息而保留重要的信息; (如:一个人有可以做很多事,但是程序只保留了需要他做的事.) 封装:信息打包,将抽象出来的属性和行为包装在一个类中; package com.eduask.tzy; public class Student { public String number; public String name; public int age; public String major; public void attendClass(){ System.out.println("上课方法"); } public void exam(){ System.out.println("我在考试"); } } 学生类建模 Eclipse如何导入看源码 Window -----> Preferences -----> java -----> Installed JREs 选中jre7,点击右边的Edit按钮,找到rt.jar文件,选择其中的Source attachment双击 选中External location,再点击External File,找到JDK下面的src压缩文件,然后Ok即可 Eclipse如何导入看源码 1、面向对象编程(OOP,Object Oriented Programming) 1)面向对象编程的理解: 万事万物都能看作成一个类,这个类里面,有不同的属性(特征),也有不同的方法(行为,功能)。 如:人类,它的属性有:眼睛,鼻子,耳朵,身高,体重等。 它的方法有:吃饭,睡觉,打篮球,上网,跳舞等。 2)什么是类: class就是类,拥有相同属性和相同方法的一组对象就是类。 如:鱼和鸭子,同样可以看成一类,为什么呢?因为它们有共同的特点,比如可以游泳,可以拿来当食物。 如果我们以游泳来分类,则可以分为动物类。如果我们以可以吃的角度去考虑,我们可以归为食物类。 注意:在我们定义的实体类里面,可以有自定义的类的属性 例子: public class Person { public Header header; //这里的Header就是我们自定义的类型,header可以作为Person的一个属性 } 这里的Header必须要实例化(new),然后给其赋值后,再将header这个实例赋值给person.herder 语法: 修饰符 + class + 类名{ 类的属性 类的方法 } 注意:类名首字母一定要大写。 3)如何实例化对象 关键字:new 语法: 类名 对象名 = new 类名(); 这里的实例化语法是,无参数的构造方法(构造函数)。 4)类的属性 语法:修饰符 数据类型 属性名; 例子:public String name; //名称 如何调用:实例名.属性名 5)方法 什么是方法,所谓的方法就是对象的行为,或者是功能。 方法分为4类: 1)无参数无返回值 语法:修饰符 + void + 方法名(); 2)无参数有返回值 语法:修饰符 + 返回值类型 + 方法名(); 3)有参数无返回值 语法:修饰符 + void + 方法名(参数类型 参数1,参数类型 参数2.....); 4)有参数有返回值 语法:修饰符 + 返回值类型 + 方法名(参数类型 参数1,参数类型 参数2.....); 如何调用方法: 实例名.方法(参数列表); 以上所有方法,方法名必须要满足驼峰命名法(首字母小写,后面的单词首字母大写) 注意:如果是有返回值的方法,需要通过关键字return来返回具体的值,具体的值必须满足 方法上面定义的返回值的类型。如果想要输出返回值,则需要在输出语句中去调用此方法。 方法如果是没有返回值的则直接进行 对象.方法 调用。 6)构造器(构造方法,构造函数) 构造器分为两类: 1)有参构造 带有参数的构造器,其中的参数,可以是多个的,最好是每个参数都能对应一个属性,如果 多写的参数没有具体的属性与其对应,并不会影响其结果,但是必须要给此参数赋值。 例子: public Person(String name,int age,String address){ this.name = name; this.age = age; } 说明: 1)这里的this代表类实例本身。 2)这里的address参数是没有具体的属性与其对应,但是不影响结果,在调用的时候,这个address 必须被赋值 3)申明构造器时,构造器的名字必须和类名一致 2)无参构造 在java定义实体类的时候,如果我们不写构造器,则java还有一个默认的无参的构造器。 注意:如果说我们没有创建构造器的时候,java有个默认的无参构造。 如果一旦创建了构造器,则默认的构造器就消失了。 文字说明 包:** 1)标准java库是由一系列包组成,包括java.lang,java.util,java.net等等。 标准Java包就是层次型包结构,就如同硬盘上嵌套的子目录一样,我们可以使用嵌套层次结构来组织包。 2)Java的包是为了更好的规划代码,防止命名冲突和混乱。所以Java出现了打包机制。 3)当把类组织起来放进一个包内之时,也就给包中的成员赋予了相互访问的权限,您就 “拥有”了该包内的程序代码。 4)包访问权限把类聚集在一个包中这一做法提供了意义和理由. 5)不同包下可以有相同名字的类,在包A下可以条用包B下的相同名字的类,使用包全称 例子: com.bao.tzy1.House house = new com.bao.tzy1.House(); 说明:是在tzy2里面调用tzy1里面相同名字的House类,如果我们需要使用另一个包里面全部类, 则可以通过通配符*来调用如:import com.bao.tzy.*;导入包使用关键字import 语法: package com.bao.tzy2; //当前包 import com.bao.tzy1.*; //导入包 包(package) package com.eduask.tzy; public class Demo { /* 构造器分为两类: 1)有参构造 带有参数的构造器,其中的参数,可以是多个的,最好是每个参数都能对应一个属性,如果 多写的参数没有具体的属性与其对应,并不会影响其结果,但是必须要给此参数赋值。 例子: public Person(String name,int age,String address){ this.name = name; this.age = age; } 说明: 1)这里的this代表类实例本身。 2)这里的address参数是没有具体的属性与其对应,但是不影响结果,在调用的时候,这个address 必须被赋值 3)申明构造器时,构造器的名字必须和类名一致 2)无参构造 在java定义实体类的时候,如果我们不写构造器,则java还有一个默认的无参的构造器。 注意:如果说我们没有创建构造器的时候,java有个默认的无参构造。 如果一旦创建了构造器,则默认的构造器就消失了。*/ public static void main(String[] args) { Student st = new Student(); st.setName("小名"); st.setAge(15); System.out.println(st.getName()+st.getAge());//年龄太小了 小名25 Student st1 = new Student(); System.out.println(st1.toString());//Student [name=null, age=0] Student st2 = new Student("张三",33); System.out.println(st2.toString());//Student [name=张三, age=33] } } class Student { private String name; private int age; public String getName() { return name; } public void setName(String name) { this.name = name; } public int getAge() { return age; } public void setAge(int age) { if(age<25){ System.out.println("年龄太小了"); this.age =25; }else{ this.age = age; } } public Student(String name, int age) { super(); this.name = name; this.age = age; } @Override public String toString() { return "Student [name=" + name + ", age=" + age + "]"; } public Student() { super(); } } 构造器案例 1、访问修饰符 1)默认的(什么都不写) 只能在相同包的类才能调用,但是子类不能调用父类的属性。 2)public(公共的) 在同一个工程下,任意包下都可以使用。 3)private(私有的) 只能在当前类使用,超过当前类是不能使用的 1)要获取private的属性,则必须要提供公共get set方法,get方法是获取值 set方法是赋值。然后在其他的类里面进行调用get set方法即可访问 到私有的属性 2)get set 方法的快捷键是: Generate Getters and Setters 4)protected(受保护的) 只能在相同包的类才能调用,但是子类可以调用父类的属性。 2、非访问修饰符 1)static 1)使用了static静态关键字的方法或属性,则不需要用关键字new来创建对象调用方法和属性,只需要类名.方法名 或者类名.属性 2)局部变量是不能够用static修饰的,一般定义静态变量是在类上方 3)局部变量不能被声明为 static 变量。 4)静态方法不能使用类的非静态变量。 例子: public static void show(){ System.out.println("张三"); } 如果声明了静态方法或变量,值是放在方法区,因为方法区是一个数据共享区;所以不管什么变量访问它,都是同一份. 在静态方法中不能直接访问实例方法和实例变量. 在静态方法中不能使用 this 和 super 关键字. 静态方法不能被 abstract 修饰. 静态的成员变量可以使用类名或者是对象进行访问,非静态成员变量只能使用对象进行访问. 静态函数可以直接访问静态的成员,但是不能够直接访问非静态成员.,非静态函数可以访问静态和非静态成员. 当类被加载时,静态代码块只能被执行一次。类中不同的静态方法代码块按他们在类中出现的顺序被依次执行. 当多个修饰符连用时,修饰符的顺序可以颠倒,不过作为普遍遵守的编码规范,通常把访问控制修饰符放在首位, 其次是 static 或 abstact 修饰符,接着就是其他的修饰符 内部类: 一个类的内部,有另外一个类(可以有多个) 1)如果在内部类里加上了修饰符static,则我们可以直接通过 外层类.内层类 实例名 = new 外层类.内层类(); 例子: Person.Student student = new Person.Student(); 2)如果在类文件上面导入了内部类,例子如:import com.hygj.sta.Person.Student; 我们就可以直接使用内部类建立实例:Student st = new Student(); 3)如果内部类不是static的,那么我们必须先new一个外层的类的实例,然后再外层实例.new 内部类(); 例子: Person person = new Person(); Student student = person.new Student(); 说明:Person是外层类,Student是内部类 2)final(最终的) 1)被final修饰过的实例(对象),是不能够改变它的内存地址的,也就是说不能改变被final修饰过的引用。 2)如果是被final修饰的对象,则对象里面的属性的值是可以更改的,但是如果用final修饰的属性,则是不能 改变它的值的。 3)类中的 Final 方法可以被子类继承,但是不能被子类修改。 4)final 类不能被继承,没有类能够继承 final 类的任何特性。 final 变量必须被显式初始化,并且只能被赋值一次值 final 修饰基本类型变量的时候, 该变量不能重新赋值 final 修饰引用类型变量的时候, 该变量不能重新指向其他对象 final 修饰的方法为最终的方法, 该方法不能被重写 private 类型的方法都默认为是final方法,因而也不能被子类重写 final 修饰的类为最终的类, 不能被继承 3)abstract 修饰符 抽象类不能被实例化. 抽象类中可以没有抽象方法,但包含了抽象方法的类必须被定义为抽象方法. 如果子类没有实现父类中所有的抽象方法,子类也必须定义为抽象类. 抽象类不能被定义为 private、final、和 static 类型. 没有抽象的构造方法. 抽象方法没有方法体,如果一个方法没有方法体,那么该方法必须声明为抽象的方法. 非抽象类继承抽象类的时候,必须要把抽象类中的所有抽象方法实现. 4)注意:以下修饰符一起用是无意义的,会导致编译错误: abstract 与 private abstract 与 final abstract 与 static 修饰符 this关键字 作用:当成员变量和局部变量或者参数同名的时候用this进行区分。 1)我们在一个构造器里,可以调用其他的构造器(都在同一个类),通过this关键字。 例子: this(); // 这是调用无参构造 2)调用本类的构造函数的this语句必须放在构造函数的第一行,因为要让初始化操作先完成。 super关键字 1)super作用:调用父类的方法和属性或者构造器,通过super关键字 2)当子类与父类有同名的属性时,可以通过“super.此属性”,显式的调用父类中声明的属性,若想调用子类的同名的属性“this.此属性” 3)当子类重写父类的方法以后,在子类中若想再显式的调用父类被重写的方法,就需要使用“super.方法”,如果要调用自身的则使用“this.方法” 4) a)super修饰构造器:通过在子类中使用“super(形参)”来显式的调用父类中指定的构造器 b)在构造器内部,“super(形参)”必须声明在首行! 同this一样 c)在构造器内部,“this(形参)”或“super(形参)”只能出现一个 d)当构造器中,不显示的调用“this(形参)”或者“super(形参)”其中任何一个的时候,调用的则是默认的父类空参的构造器 e)为防止出错,每个类中最好都写上空参的构造器 this super关键字 |
对象: 对象是类的事例化结果; 对象是实实在在的存在,代表现实世界的某一事物 对象的声明、创建、赋值有三个步骤:(以下123对应) 1 3 2 Dog myDog = new Dog() 1、要求Java虚拟机分配空间给引用变量(栈),并将此变量名 命名为myDog。此引用变量将永远被固定为Dog类型。换句话 说,它是个控制Dog的遥控器,不会是Cat或比卡丘的遥控器。 2、要求Java虚拟机分配空间(堆)给新建立的Dog对象; 3、将新的Dog赋值给myDOg这个引用变量。换言之,就是 设定遥控器 使用成员访问符"."操作对象: 给对象属性赋值:对象名.属性 对对象发送消息即可调用方法:对象名.方法(); package com.eduask.tzy; public class Dog { public String brand;//品种 public int age; public String toString(){ return "这是一条"+age+"岁的"+brand; } public static void main(String[]args){ Dog myDog = new Dog(); myDog.age=12; myDog.brand="中华田园犬"; System.out.println(myDog.toString()); //这是一条12岁的中华田园犬 } } Dog类-->实例化中华田园犬 |
对象的两个关键特性: 行为:对象能干什么 状态:对象的属性,行为的结果 方法的定义和调用: 把方法当作一个模块,是个黑匣子,完 成某个特定的功能,并返回处理结果。 方法分类: 返回值为(空)void的方法; 带具体返回类型的方法; 不带参数的方法; 带参数的方法; 方法返回值: 如果方法有返回值,方法中必须使用 关键字return返回该值,返回值类型 为该方法所定义的返回值类型。 方法内可以调用其他方法。 对对象发送消息即可调用方法:对象名.方法(); Java调用带参数的方法采用值传递方式: 如果参数是基本数据类型,参数传递是将参数的 数值传递给方法; 如果参数是对象或数组,参数传递是将对象或 数组的引用值传递给方法; 总之:传递参数时都有一个值拷贝的过程。 package com.eduask.tzy; public class MethodDemo { public void method1() { System.out.println("返回值类型为空且无参数的方法"); } public String method2() { return "带有具体返回值类型且无参数的方法 "; } public void method3(String name) { System.out.println("返回值类型为空且带参数的方法,参数值为:" + name); } public String method4(String name, int age) { return "带有具体返回值类型且有多个参数的方法,参数的值为: " + name + "," + age; } // 传递基本数据类型 public void operatorData(int age) { age++; System.out.println(age); } // 传递引用数据类型的方法 public void operatorArray(int[] array) { array[2] = 100; System.out.println(array[2]); } public static void main(String[] args) { MethodDemo md = new MethodDemo(); md.method1();// 返回值类型为空且无参数的方法 System.out.println(md.method2());// 带有具体返回值类型且无参数的方法 md.method3("张三");// 返回值类型为空且带参数的方法,参数值为:张三 System.out.println(md.method4("李四", 15));// 带有具体返回值类型且有多个参数的方法,参数的值为: 李四,15 // 测试基本数据类型参数 int age = 10; md.operatorData(age); System.out.println(age);// 10 // 测试引用数据类型参数(注意其实传递的是堆内存地址) int[] array = { 1, 2, 3, 4 }; md.operatorArray(array); System.out.println(array[2]); } } 方法的调用 |
注:
类和对象的区别:类是静态定义;对象是动态事例;程序代码操作的是对象而非对象;建模得到的是类而非对象。
类和对象的联系:类是对象的定义;对象的产生离不开类这个模版;类存在的目的就是为了实例化对象。
变量的作用域:
变量声明的位置决定了变量的作用域;
变量的作用域确定可在程序中按变量名访问该变量的区域;
全局变量:在整个类中都可以使用的变量;
局部变量:在某一个方法或者是一个模块当中能够使用的变量。
String说明及常用方法
package com.eduask.tzy; public class StringDemo { public static void main(String[] args) { // String对象的声明和操作 String S = "我是程序员";// (常用创建方式) String s1 = "abcd"; String s2 = "abcd"; System.out.println(s1 == s2);// true System.out.println(s1.equals(s2));// true // 结论:字符串常量池里面引用 String s = new String("我是程序员");// 不常用方式 String s3 = new String("abcd"); String s4 = new String("abcd"); System.out.println(s3 == s4); // false System.out.println(s3.equals(s4));// true // 结论:在内存空间新分配一个存储空间 // 1、String对象是不可变的 // 2、类中每一个看来会修改String值的方法,其实都是创建了新的String对象(包含修改后的字符串内容:如拼接) // 3、String的只读特性带来效率优化可能 // 4、字符串字面值储存于字符串池中,String对象优先指向该字符串池,避免发生重复的字符串事例 // 5、系统对String的非修改处理效率很高,远远超过另外两个字符串类StringBuffer和StringBuilder(频繁修改就用后面两个类) /* String常用方法 */ // ①charAt(int index) 返回指定索引处的 char 值。 String content = "Hello,My Friend,You are my best friend"; System.out.println(content.charAt(2));// l // ②compareTo(String anotherString) 按字典顺序比较两个字符串。 System.out.println(content.compareTo("hello"));// -32 // ③concat(String str) 将指定字符串连接到此字符串的结尾。 content = content.concat("I lied");//content = content+"I lied"; System.out.println(content);//Hello,My Friend,You are my best friendI lied //④endsWith(String suffix)测试此字符串是否以指定的后缀结束。 System.out.println(content.endsWith("lied"));//true //⑤startsWith(String suffix)测试此字符串是否以指定的前缀开始。 System.out.println(content.startsWith("Hello,"));//true //⑥contains(CharSequence s) 当且仅当此字符串包含指定的 char 值序列时,返回 true。 System.out.println(content.contains("My"));//true //⑦equals(Object anObject) 将此字符串与指定的对象比较。(案例在上面) //⑧equalsIgnoreCase(String anotherString) 将此 String 与另一个 String 比较,不考虑大小写。 //⑨indexOf(int ch)返回指定字符在此字符串中第一次出现处的索引。 // indexOf(String str, int fromIndex)返回指定子字符串在此字符串中第一次出现处的索引,从指定的索引开始。 // lastIndexOf(String str)返回指定子字符串在此字符串中最右边出现处的索引。 // lastIndexOf(String str, int fromIndex) 返回指定子字符串在此字符串中最后一次出现处的索引,从指定的索引开始反向搜索。 System.out.println(content.indexOf("o")); System.out.println(content.lastIndexOf("o")); System.out.println(content.indexOf("o",5));//17 //⑩length() 返回此字符串的长度。 System.out.println(content.length());//44 //⑩① replace(char oldChar, char newChar) 返回一个新的字符串,它是通过用 newChar 替换此字符串中出现的所有 oldChar 得到的。 System.out.println(content.replace('e', 'a'));//Hallo,My Friand,You ara my bast friandI liad //⑩②split(String regex) 根据给定正则表达式的匹配拆分此字符串。 String [] arr = content.split(" "); System.out.println(arr.length); for (String string : arr) { System.out.print(string+"*");//Hello,My*Friend,You*are*my*best*friendI*lied* } System.out.println(); //⑩③substring(int beginIndex) 返回一个新的字符串,它是此字符串的一个子字符串。 // substring(int beginIndex, int endIndex) 返回一个新字符串,它是此字符串的一个子字符串。 System.out.println(content.substring(5));//,My Friend,You are my best friendI lied System.out.println(content.substring(5, 10));//,My F //⑩④toLowerCase() 使用默认语言环境的规则将此 String 中的所有字符都转换为小写。 // toUpperCase() 使用默认语言环境的规则将此 String 中的所有字符都转换为大写。 System.out.println(content.toLowerCase());//hello,my friend,you are my best friendi lied System.out.println(content.toUpperCase());//HELLO,MY FRIEND,YOU ARE MY BEST FRIENDI LIED //⑩⑤trim() 返回字符串的副本,忽略前导空白和尾部空白。 System.out.println(" abc ");// abc (有前后空格) System.out.println(" abc ".trim());//abc(成功去掉前后空格) } }
String说明及常用方法
package com.eduask.tzy; public class Employee { public int age; public String name; public String toString() { return "我的名字叫" + name + ",今年:" + age + "岁"; } // 在指定字符串中查找相应的字符串出现次数 /* * src 朋友啊朋友,你是我的好朋友 dst 朋友 indexOf("朋友"); */ public int countContent(String src, String dst) { int count = 0;// 计数器 int index = 0;// 保存找到朋友的下标 index = src.indexOf(dst); // indexOf找到返回首次出现的下标,找不到就返回-1 while (index != -1) { count++;// 计数器加1 index += dst.length();// 指定从那个下标开始往后找 index = src.indexOf(dst, index); } return count; } public static void main(String[] args) { Employee emp = new Employee(); emp.name = "张三"; emp.age = 30; System.out.println(emp.toString()); String src = "朋友啊朋友,你是我的好朋友"; String dst = "朋友"; int count = emp.countContent(src, dst); System.out.println(dst + "出现的次数为:" + count + "次"); // 我的名字叫张三,今年:30岁 // 朋友初相的次数为:3次 } }
雇员类案例
封装: 将东西包装在一起,然后以新的完整形式呈现出来: 将方法和字段一起包装到一个单元中,单元以类的形式实现。 信息隐藏,隐藏对象的实现细节,不让外部直接访问到。 将数据和方法包装进类中,加上具体实现的隐藏,共同被 称作封装,其结果是一个同事带有特征和行为的数据类型。 “定义类,定义其属性、方法的过程成为封装类” 信息隐藏是oop最重要的功能之一,也是使用访问修饰符 的原因。 信息隐藏的原因包括: 对模块的任何实现细节所作的更改不会影响使用该模块 的代码。 防止用户意外修改数据。 使模块易于使用和维护。 访问修饰符** 作用: 用于控制被修饰变量、方法、类的可见范围. 总结: 在不同包下面能够访问的权限修饰符只有: pulbic 与protected,但是 protected 必须要有继承的关系才能够访问。 1、构造器创建的快捷键 1)右键Source,选择Generate Constructor using Fields,再根据需要勾选参数个数 注意:方法里面传的参数和构造器里面的参数是没有任何关系的。 1)我们定义的方法里面的参数是形式参数(形参),可以看作一个变量,它具体的值跟 调用此方法传入的参数有关,传入值是什么,此参数的值就是什么 2、包。 1)不同包下可以有相同名字的类,在包A下可以条用包B下的相同名字的类,使用包全称 例子: com.hygj.j37.House house = new com.hygj.j37.House(); 说明:是在j38里面调用j37里面相同名字的House类,如果我们需要使用另一个包里面全部类, 则可以通过通配符*来调用如:import com.hygj.j37.*;导入包使用关键字import 语法: package com.hygj.j38; //当前包 import com.hygj.j37.*; //导入包 3、访问修饰符 1)默认的(什么都不写) 只能在相同包的类才能调用,但是子类不能调用父类的属性。 2)public(公共的) 在同一个工程下,任意包下都可以使用。 3)private(私有的) 只能在当前类使用,超过当前类是不能使用的 1)要获取private的属性,则必须要提供公共get set方法,get方法是获取值 set方法是赋值。然后在其他的类里面进行调用get set方法即可访问 到私有的属性 2)get set 方法的快捷键是: Generate Getters and Setters 4)protected(受保护的) 只能在相同包的类才能调用,但是子类可以调用父类的属性。 4、非访问修饰符 1)static 1)使用了static静态关键字的方法或属性,则不需要用关键字new来创建对象调用方法和属性,只需要类名.方法名 或者类名.属性 2)局部变量是不能够用static修饰的,一般定义静态变量是在类上方 3)局部变量不能被声明为 static 变量。 4)静态方法不能使用类的非静态变量。 例子: public static void show(){ System.out.println("张三"); } 如果声明了静态方法或变量,值是放在方法区,因为方法区是一个数据共享区;所以不管什么变量访问它,都是同一份. 在静态方法中不能直接访问实例方法和实例变量. 在静态方法中不能使用 this 和 super 关键字. 静态方法不能被 abstract 修饰. 静态的成员变量可以使用类名或者是对象进行访问,非静态成员变量只能使用对象进行访问. 静态函数可以直接访问静态的成员,但是不能够直接访问非静态成员.,非静态函数可以访问静态和非静态成员. 当类被加载时,静态代码块只能被执行一次。类中不同的静态方法代码块按他们在类中出现的顺序被依次执行. 当多个修饰符连用时,修饰符的顺序可以颠倒,不过作为普遍遵守的编码规范,通常把访问控制修饰符放在首位, 其次是 static 或 abstact 修饰符,接着就是其他的修饰符 内部类: 一个类的内部,有另外一个类(可以有多个) 1)如果在内部类里加上了修饰符static,则我们可以直接通过 外层类.内层类 实例名 = new 外层类.内层类(); 例子: Person.Student student = new Person.Student(); 2)如果在类文件上面导入了内部类,例子如:import com.hygj.sta.Person.Student; 我们就可以直接使用内部类建立实例:Student st = new Student(); 3)如果内部类不是static的,那么我们必须先new一个外层的类的实例,然后再外层实例.new 内部类(); 例子: Person person = new Person(); Student student = person.new Student(); 说明:Person是外层类,Student是内部类 2)final(最终的) 1)被final修饰过的实例(对象),是不能够改变它的内存地址的,也就是说不能改变被final修饰过的引用。 2)如果是被final修饰的对象,则对象里面的属性的值是可以更改的,但是如果用final修饰的属性,则是不能 改变它的值的。 3)类中的 Final 方法可以被子类继承,但是不能被子类修改。 4)final 类不能被继承,没有类能够继承 final 类的任何特性。 final 变量必须被显式初始化,并且只能被赋值一次值 final 修饰基本类型变量的时候, 该变量不能重新赋值 final 修饰引用类型变量的时候, 该变量不能重新指向其他对象 final 修饰的方法为最终的方法, 该方法不能被重写 private 类型的方法都默认为是final方法,因而也不能被子类重写 final 修饰的类为最终的类, 不能被继承 3)abstract 修饰符 抽象类不能被实例化. 抽象类中可以没有抽象方法,但包含了抽象方法的类必须被定义为抽象方法. 如果子类没有实现父类中所有的抽象方法,子类也必须定义为抽象类. 抽象类不能被定义为 private、final、和 static 类型. 没有抽象的构造方法. 抽象方法没有方法体,如果一个方法没有方法体,那么该方法必须声明为抽象的方法. 非抽象类继承抽象类的时候,必须要把抽象类中的所有抽象方法实现. 4)注意:以下修饰符一起用是无意义的,会导致编译错误: abstract 与 private abstract 与 final abstract 与 static 修饰符文档 修饰符文档 package com.eduask.tzy; public class Demo { public static void main(String[] args) { Student st = new Student(); st.setName("小名"); st.setAge(15); System.out.println(st.getName()+st.getAge()); //年龄太小了 小名25 } } class Student { private String name; private int age; public String getName() { return name; } public void setName(String name) { this.name = name; } public int getAge() { return age; } public void setAge(int age) { if(age<25){ System.out.println("年龄太小了"); this.age =25; }else{ this.age = age; } } } 封装基础案例 package com.eduask.tzy; public class StaticDemo { public static void main(String[] args) { Account acc1 = new Account(); // acc1.number1++;//会让下面类变量值改变 // acc1.showNumber1();//2 Account acc2 = new Account(); // acc2.showNumber1();//2 Account.number1++; System.out.println(Account.number1); } } class Account{ public static int number1=1;//静态变量(类变量),它不属于任何对象 private int number2=2; public static int number3; public Account(){ System.out.println("我是无参构造"); } //static语句块:在类加载的时候就会执行,只会执行一次(和多少实例无关),用来对静态的变量赋值 static{ System.out.println("我是static语句块"); number3 = 100; } public static void showNumber1(){//1、静态方法中不能访问非静态的变量 2、不可以使用this System.out.println(number1); } public void showNumber2(){ System.out.println(number2); } public void showNumber(){//非静态的方法可以访问静态的内容和非静态的属性和方法 showNumber1(); System.out.println("非静态方法访问静态变量"+number1); } } static关键字 package com.abc.tzy; public class TestFinal { /* final可以用来修饰变量、方法、类。 final修饰的变量是一个常量。一旦赋值就不能被修改(常量一般都和static关键字配合使用) final修饰类代表此类不能被继承。 final修饰方法代表此方法不能被重写*/ public static void main(String[] args) { X x = new X(); x.show1(); C c = new C(); c.show2(); final X x2 = new X(); // x2 = new X();final用在引用变量上,代表引用变量只能引用一开始所引用的对象,不能改变其指向 x2.number2=5; x2.show2(); } //答案:1 2 5 } /*final*/ class X{//常量类不能被继承 public final int number1 = 1; public int number2 = 2; public void show1(){ // number1++;常量不可以被修改 System.out.println(number1); } //子类不能对父类中的常量方法进行重写 public /*final*/ void show2(){ System.out.println(number2); } } class C extends X{ public void show2(){//Cannot override the final method from X System.out.println(number2); } } final关键字 package com.abc.tzy; /* Object类常见方法: String toString() 1-返回该对象的字符串描述性信息。默认输出格式是:类名[字段值,字段值。。。]; 2-只要对象与一个字符串通过“+”连接,系统就会自动调用toString()以 获得对象的字符串描述; 3-常被改写:可以根据用户的需要对其进行重写。 boolean equals() 1-Object类原始功能是实现判断两个对象是否具有相同的引用;要求判断两个对象状态的相等性; 2-在jdk标准库中提供了一些类,比如String,Date,包装类,File类。他们都对equals方法进行了重写。 3-常被改写:可以根据用户的需要对其进行重写. */ public class TestObject { public static void main(String[] args) { Student st = new Student("张三",50); System.out.println(st); System.out.println(st.toString()); Student st1 = new Student("张三",50); System.out.println(st1.equals(st)); } } //不重写 com.abc.tzy.Student@659e0bfd com.abc.tzy.Student@659e0bfd false //重写后姓名张三, 年龄50岁 姓名张三, 年龄50岁 true class Student /*extends Object*/{ //不加也是继承Object private String name; private int age; public Student(String name, int age) { super(); this.name = name; this.age = age; } @Override public String toString() { return "姓名" + name + ", 年龄" + age + "岁"; } /*public boolean equals(Object obj){ //自己跟自己比 if(this==obj){ return true ; } if(obj==null){ return false; } //类型 if(this.getClass()!=obj.getClass()){ return false; } Student stu = (Student)obj; if(this.age!=stu.age){ return false; } if(this.name==null&&stu.name!=null){ return false; }else if(!this.name.equals(stu.name)){ return false; } return true; } */ @Override public int hashCode() { final int prime = 31; int result = 1; result = prime * result + age; result = prime * result + ((name == null) ? 0 : name.hashCode()); return result; } @Override public boolean equals(Object obj) { if (this == obj) return true; if (obj == null) return false; if (getClass() != obj.getClass()) return false; Student other = (Student) obj; if (age != other.age) return false; if (name == null) { if (other.name != null) return false; } else if (!name.equals(other.name)) return false; return true; } } Object类 |
方法重载: 多数程序设计语言要求为每个方法(函数)提供一个独一无二的方法名,不存在方法重载的概念。 在Java中规定方法签名是解析方法的规则而不是方法名,为方法重载开创了条件。 注:方法签名——》方法名+参数列表 方法重载使得在一个类中,方法名相同而参数列表不同的方法可同时存在,代表相似的行为或功能。 重载over load概念:在同一类中,同名不同参的方法称为重载方法。 注意:仅有返回类型不同的方法不能称为重载,即方法重载必须方法签名不同。******* package com.eduask.tzy; public class OverloadDemo { public static void main(String[] args) { Printer p = new Printer(1000); System.out.println(p.toString()); Printer p1 = new Printer("戴尔",2000); System.out.println(p1.toString()); p.print("hello"); p.print(11); p.print("hello", 22); p.print( 22,"hello"); } } class Printer{ private String brand = "惠普"; private double price; public Printer(double price){ this.price = price; } public Printer(String brand,double price){ this.brand = brand; this.price = price; } public void print(String content){ System.out.println("字符串:"+content); } public void print(int content){ System.out.println("整形:"+content); } public void print(String content,int content1){ System.out.println("字符串:"+content+"整形"+content1); } @Override public String toString() { return "Printer [brand=" + brand + ", price=" + price + "]"; } // public int print(int content){ // System.out.println("整形:"+content); // }这样不是重载,程序无法分辨是哪个方法 public int print(int content,String content1){//重载成功 System.out.println(content+"--"+content1); return 1; } } 重载案例 方法重写:(override) 方法的重写是指类可以根据需要对从父类继承来的方法进行改写,是多态机制的前奏。 重写注意: 重写方法必须和被重写方法具有相同的方法名称、参数列表和返回值。 重写方法不能使用比被重写方法更严格的访问权限 父类中的私有方法不能被重写。 在子类重写的方法中继续调用父类被重写的方法,可以通过调用super.函数名获取。 |
继承的概念和实现: 继承背后的思想就是基于已存在的类来构建新类。 当从已存在的类继承时,就重用了它的方法和属性,还可以添加新的方法和属性来定制新类以对应需求。 约定:从其他类导出的类叫子类,被导出的类叫父类 在Java中,除了Object类之外,所有的类都是子类,都有唯一的父类。 继承在oop中不可或缺 创建一个类时,总是在继承 类之间的关系: is-a 继承体现 Has-a 组合体现 Like-a 实现接口体现 继承的意义: 代码重用 体现不同抽象层次 父子类关系: 父类更抽象,更一般; 子类更具体,更特殊; extends关键字: 在Java中,用extends关键字来表示一个类继承了另一个类
package com.abc.tzy; public class TeacherDemo { public static void main(String[] args) { B b = new B(); b.showB(); } } /*A的构造方法 B的构造方法 子类B A 父类B */ class A{ public A(){ System.out.println("A的构造方法"); } public void showA(){ System.out.println("A"); } public void showB(){ System.out.println("父类B"); } } class B extends A{ public B(){ super();//调用父类的构造方法,可以省略,编译时会自动加上。 System.out.println("B的构造方法"); } public void showB(){ System.out.println("子类B"); super.showA(); super.showB(); } } 继承案例1 package com.abc.tzy; public class TeacherDemo1 { public static void main(String[] args) { JavaTeacher jt = new JavaTeacher("张三","666学校"); DBTeacher dt = new DBTeacher("李四", "999学校"); jt.teaching(); dt.teaching(); } } /* 授课前准备 Java老师打开Eclipse 狂写Java代码 授课前准备 DB老师打开Mysql 狂写sql代码 */ class Teacher{ private String name; private String school; //没有无参构造了哦 public Teacher(String name, String school) { super(); this.name = name; this.school = school; } public void teaching(){ System.out.println("授课前准备"); } } class JavaTeacher extends Teacher{ public JavaTeacher(String name, String school) { super(name, school); } public void teaching(){ super.teaching(); System.out.println("Java老师打开Eclipse"); System.out.println("狂写Java代码"); } } class DBTeacher extends Teacher{ public DBTeacher(String name, String school) { super(name, school); } public void teaching(){ super.teaching(); System.out.println("DB老师打开Mysql"); System.out.println("狂写sql代码"); } } 继承案例2
|
多态: 多态性是指同一操作作用于某一对象,可以有不同的解释,产生不同的执行结果。 多态存在的三个必要条件: 需要存在继承和实现关系; 同样的方法调用而执行不同操作。运行不同代码。(重写操作) 在运行时父类或者接口的引用变量可以引用其子类的对象;如:Animal a =new Dog(); 多态的作用: 多态通过分离做什么和怎么做,从另一个角度将接口和实现进行分离; “多态”则消除了类型之间的耦合关系; 多多态的存在提高了程序的扩展性和后期的可维护性。 package com.abc.tzy; public class AnimalDemo { public static void main(String[] args) { //父类的引用变量可以引用其子类的对象 Animal an1 = new SDog("旺财"); an1.eat(); Animal an2 = new SCat("招财"); an2.eat(); } } class Animal{ private String name; public Animal(String name){ this.name= name; } //这是一个通用方法,通用的方法实现没有太大的意义,只是告诉其子类去实现它 public void eat(){ System.out.println("能吃东西"); } } class SDog extends Animal{ public SDog(String name) { super(name); } public void eat(){ System.out.println("啃骨头"); } } class SCat extends Animal{ public SCat(String name) { super(name); } public void eat(){ System.out.println("吃鱼"); } } 多态案例 package com.abc.tzy; /*由子类转型成父类,在继承图上是向上移动的,一般称为向上转型 向上转型是从一个较专用类型向较通用类型转换,所以总是安全的,也就是说,子类是父类的一个超集 向上转型过程中,类接口中唯一开能发生的事情是丢失方法,而不是获取方法 与之相反的操作是向下转型,不安全(可能需要instanceof操作符协助) Lsp(liskov替换原则):子类型必须能够替换掉它们的基类型 安全的上转型和LSP的实施,充分体现继承的“is-a”关系*/ public class AnimalDemo { public static void main(String[] args) { //父类的引用变量可以引用其子类的对象 Animal an1 =/*(Animal)*/ new SDog("旺财"); //向上转型首先是安全的,可能会导致子类方法的丢失。 //父类的引用变量只能调用父类中有的方法或子类重写父类的方法 an1.eat(); // an1.sleep();//该方法丢失 Animal an2 = new SCat("招财"); an2.eat(); //向下转型是不安全的 //SCat cat =(SCat)an1;//java.lang.ClassCastException //instanceof运算符用来在运行时通过返回一个布尔值来指出对象是否是特定类或者是它的子类的一个实例 if(an1 instanceof SCat){ SCat cat =(SCat)an1; System.out.println("转换成了猫"); cat.eat(); } if(an1 instanceof SDog){ SDog dog =(SDog)an1; System.out.println("转换成了狗"); dog.sleep(); } } } //答案:啃骨头 吃鱼 转换成了狗 狗睡觉 class Animal{ private String name; public Animal(String name){ this.name= name; } //这是一个通用方法,通用的方法实现没有太大的意义,只是告诉其子类去实现它 public void eat(){ System.out.println("能吃东西"); } } class SDog extends Animal{ public SDog(String name) { super(name); } public void eat(){ System.out.println("啃骨头"); } public void sleep(){ System.out.println("狗睡觉"); } } class SCat extends Animal{ public SCat(String name) { super(name); } public void eat(){ System.out.println("吃鱼"); } } 上下转型及instanceof运算符 静态绑定和动态绑定的概念: 在程序执行前方法已经被绑定,针对java简单的可以理解为程序编译期的绑定(静态绑定)java当中的方法是final,static,private和构造方法都是前期绑定的。 运行时,根据变量实际引用的对象类型决定调用哪个方法(动态绑定) 静态绑定在编译期进行 Person.sayHi(); 动态绑定在运行期进行 Person p = new Teacher(); p.sayHi(); 多态的概念基于对象引用的动态绑定特性 多态的应用: 简单来说,多态是具有表现多种形为能力的特征。 同一个实现接口,使用不同的实例而执行不同的操作 package com.abc.tzy; public class PrinterDemo { public static void main(String[] args) { // ColorPrinter cp = new ColorPrinter("惠普"); // BlackPrinter bp = new BlackPrinter("戴尔"); D3Printer d3 = new D3Printer("王牌"); School sc = new School(); // sc.setPrinter(cp); // sc.setPrinter(bp); sc.setPrinter(d3); sc.print("Hello,java"); } } class Printer{ private String brand; public Printer(String brand){ this.brand=brand; } public String getbrand(){ return brand; } //打印的方法,应该由其子类来具体实现 public void print(String content){ } } //开闭原则:对修改是封闭的,对扩展是开放的。(现在下面代码在加一种打印机就会很麻烦) //多态解决这个问题,父类的引用变量可以引用其子类的对象。 class School{ /*private Printer cp =null; private Printer bp =null;*/ // 这样就写死了没有扩展性,和维护性 private Printer p = null;//我们学校有打印机 //安装彩色打印机 /*public void setPrinter(ColorPrinter cp){ this.cp=cp; } //安装黑白打印机(重载) public void setPrinter(BlackPrinter bp){ this.bp=bp; } public void print(String content){ if(cp!=null){cp.print(content);}// 注意防止java.lang.NullPointerException if(bp!=null){bp.print(content);} }*/ //拿父类的引用变量作为参数,好处就是可以接收任何其子类的对象 public void setPrinter(Printer p){ this.p=p; } public void print(String content){ p.print(content); } } class ColorPrinter extends Printer{ public ColorPrinter(String brand){ super(brand); } //对父类的方法进行重写 public void print(String content){ System.out.println(getbrand()+"彩色打印"+content); } } class BlackPrinter extends Printer{ public BlackPrinter(String brand){ super(brand); } //对父类的方法进行重写 public void print(String content){ System.out.println(getbrand()+"黑白打印"+content); } } class D3Printer extends Printer{ public D3Printer(String brand){ super(brand); } //对父类的方法进行重写 public void print(String content){ System.out.println(getbrand()+"3D打印"+content); } } 开闭原则,多态应用,可扩展性和维护性 |
抽象类
抽象的定义:
抽象是把多个事物的共性的内容抽取出来,本质就是把我们关注的内容抽取出来。(比如:宝马、奔驰都属于汽车,汽车是抽象出来的概念)
抽象类:
Java中可以定义没有方法体的方法,该方法由其子类来具体的实现。
该没有方法体的方法我们称之为抽象方法,含有抽象方法的类我们称之为抽象类。
抽象方法特点:
只有方法头没有方法体的方法称之为抽象方法;
抽象方法用abstract来修饰;
抽象方法代表一种不确定的操作或行为;
抽象方法不能被调用。
抽象类特点:
定义中含有抽象方法的类叫做抽象类
抽象类用abstract来修饰
抽象类代表一种抽象的对象类型
抽象类不能实例化
抽象类中可以有具体方法,可以没有抽象方法
package com.abc.tzy; public class EmployeeDemo { public static void main(String[] args) { Employee t = new Java_Teacher(1,"张三",2000);//可以使用多态 t.work(); Leader l = new Leader(2, "李四", 5000, 1000); l.work(); Employee e = new Employee(3, "王伍", 2000) { @Override public void work() { System.out.println("抽象类不能实例化,可以通过重写方法匿名类实现"); } }; e.work(); } } //答案:上Java课 //培训新员工 //安排课程 //抽象类不能实例化,可以通过重写方法匿名类实现 //抽象类 abstract class Employee{ private int number; private String name; private double salary; public Employee(int number, String name, double salary) { super(); this.number = number; this.name = name; this.salary = salary; } //抽象方法声明 public abstract void work(); } //一但一个类去继承了抽象类,那么这个类要么去实现抽象类中抽象方法,要么继续抽象下去 class Java_Teacher extends Employee{ public Java_Teacher(int number, String name, double salary) { super(number, name, salary); } //抽象方法的实现 @Override public void work() { System.out.println("上Java课"); } } //领导 class Leader extends Employee{ private double allowance;//津贴 public Leader(int number, String name, double salary,double allowance) { super(number, name, salary); this.allowance = allowance; } //抽象方法的实现 @Override public void work() { System.out.println("培训新员工"); System.out.println("安排课程"); } }
抽象类
接口
接口语法:
interface 接口名{
//静态常量、抽象方法
}
接口的特点:
接口中只能存放静态常量和抽象方法。
Java接口是对功能的扩展. 如: 一个人类 那实例里有些人不抽烟,有的要抽烟,所以就把抽烟 放到接口里.
通过实现接口,java类可以实现多实现
一个类可以同时继承(extends)一个父类并且实现(implements)多个接口
接口与接口之间可以通过使用extends来产生继承关系
接口(interface)与抽象类(abstract)的区别
抽象类和具体实现类之间是一种继承关系,也就是说如果采用抽象类方式,则父类和子类在概念上应该是相同的。
如:人》张三》喝奶
接口和实现类在概念上不要求相同,接口只是抽取相互之间没有关系的类的共同特征,而不去关注之间的关系,它可以使没有层次关系的类具有相同的行为。
如:狗》喝奶 张三》喝奶
抽象类是对一组具有相同属性和行为的逻辑上有关系的事物的一种抽象,而接口则是对一组具有相同属性和行为的逻辑上不相关的事物的一种抽象。
对于接口和抽象类的选择,反映出设计人员看待问题的不同角度。抽象类用于一组相关的事物,表示的是“is-a”的关系;而接口用于一组不相关的事物,表示“like-a”的关系。
package com.abc.tzy; public class InterfaceDemo { public static void main(String[] args) { Person p = new Person(); Child c =new Child(); Dog d = new Dog(); Fool f = new Fool(); p.feed(c); p.feed(d); p.feed(f); } } class Person{ /*public void feed(Child c){ c.eat(); } public void feed(Dog d){ d.eat(); }*/ public void feed(IAbility iability){ iability.eat(); } } interface IAbility{ // //接口中只能放共有的静态常量,和抽象方法(声明) // /*public static final*/ int number = 1; // /*public abstract*/ void show(); // 如果上面需要在喂一个花 喝水 那么要具备这个功能 需要修改代码,扩展性差 /*public abstract*/ void eat(); } class Child implements IAbility{ public void eat(){ System.out.println("小孩吃米饭"); } } class Dog implements IAbility{ @Override public void eat(){ System.out.println("狗吃骨头"); } } class Fool implements IAbility{ @Override public void eat(){ System.out.println("花喝水"); } }
接口案例1
面向接口编程: 开发系统时,主体构架使用接口,接口构成系统的骨架。 这样就可以通过更换接口的实现类来更换系统的实现。 示例: 需求:王牌公司内部安装了彩色打印机或黑白打印机,通过其 所安装的打印机可以用来打印教员的信息,也可以用来打印其 自身的信息. package com.abc.tzy; public class PrinterDemo { public static void main(String[] args) { ColorPrinter cp = new ColorPrinter("惠普"); BlackPrinter bp = new BlackPrinter("戴尔"); TTeacher tt = new TTeacher("张三老师", 20); School sc = new School(); sc.setPrinter(bp); sc.print(tt); sc.setPrinter(cp); sc.print(sc); //戴尔黑白打印你好我的名字叫:张三老师,今年:20岁. //惠普彩色打印你好我是王牌有限公司 } } interface IInfo{ public abstract String detail(); } abstract class Printer{ private String brand; public Printer(String brand){ this.brand=brand; } public String getbrand(){ return brand; } //打印的方法,应该由其子类来具体实现 public abstract void print(String content); } //开闭原则:对修改是封闭的,对扩展是开放的。(现在下面代码在加一种打印机就会很麻烦) //多态解决这个问题,父类的引用变量可以引用其子类的对象。 class School implements IInfo{ /*private Printer cp =null; private Printer bp =null;*/ // 这样就写死了没有扩展性,和维护性 private Printer p = null;//我们学校有打印机 //安装彩色打印机 /*public void setPrinter(ColorPrinter cp){ this.cp=cp; } //安装黑白打印机(重载) public void setPrinter(BlackPrinter bp){ this.bp=bp; } public void print(String content){ if(cp!=null){cp.print(content);}// 注意防止java.lang.NullPointerException if(bp!=null){bp.print(content);} }*/ //拿父类的引用变量作为参数,好处就是可以接收任何其子类的对象 //越抽象的东西越稳定 public void setPrinter(Printer p){ this.p=p; } //******多态.程序设计的时候主体框架使用接口或抽象类,使程序有很好的可扩展性。***** // public void print(String content){ // p.print(content); // } public void print(IInfo info){ p.print(info.detail()); } @Override public String detail() { return "你好我是王牌有限公司"; } } class ColorPrinter extends Printer{ public ColorPrinter(String brand){ super(brand); } //对父类的方法进行重写 public void print(String content){ System.out.println(getbrand()+"彩色打印"+content); } } class BlackPrinter extends Printer{ public BlackPrinter(String brand){ super(brand); } //对父类的方法进行重写 public void print(String content){ System.out.println(getbrand()+"黑白打印"+content); } } class TTeacher implements IInfo{ private String name; private int age; public TTeacher(String name,int age){ super(); this.name = name; this.age = age; } @Override public String detail() { return "你好我的名字叫:"+name+",今年:"+age+"岁."; } } 示例代码 |
实现士兵作战程序: 案例介绍: 编写一个Soldier类,描述具有普遍行为和属性的一个士兵对象。 编写陆军士兵、海军士兵、军官类来拓展Soldier类。 案例设计: 建模一个Soldier类。 设计Soldier类的相关通用属性和方法。 建模一个陆军士兵、海军士兵。军官类来继承Soldier类,增加 各自的特有属性和方法,并重写相应的方法。 package com.abc.tzy; public class SoldierDemo { public static void main(String[] args) { Officer s1 = new Officer("军官tzy"); s1.callToAttack(); System.out.println("**********"); s1.callToAttack(s1.getSoldier()[0]);//可以只传s1让自己行动 } } abstract class Soldier{ private String name; public Soldier(String name){ this.name=name; } public String getName(){ return name; } public void start(){ System.out.println("准备攻击。。"); } public void end(){ System.out.println("攻击完成。。"); } public abstract void attack(); public void action(){ start(); attack(); end(); } } class LandSoldier extends Soldier{ public LandSoldier(String name) { super(name); } @Override public void attack() { System.out.println(getName()+"步枪凸凸凸"); } } class OceanSoldier extends Soldier{ public OceanSoldier(String name) { super(name); } @Override public void attack() { System.out.println(getName()+"鱼雷凸凸凸"); } } class Officer extends Soldier{ private Soldier [] soldiers = new Soldier[2];//军官持有2个士兵 public Officer(String name) { super(name); soldiers[0]=new LandSoldier("张三"); soldiers[1]=new OceanSoldier("李四"); } public Soldier[] getSoldier(){ return soldiers; } @Override public void attack() { System.out.println(getName()+"手枪嘟嘟嘟"); } //法号司令(让所有士兵一起打包括自己) public void callToAttack(){ for (int i = 0; i < soldiers.length; i++) { soldiers[i].action();//让每个士兵调用自身行动方法 } this.action();//自己也行动 } //让一个士兵行动 public void callToAttack(Soldier soldier){ soldier.action(); } } 士兵攻击案例 |
javaSE基础的更多相关文章
- javaSE基础07
javaSE基础07 一.static静态修饰符 用了static修饰的变量就会变成共享的属性,只会初始化一次,在内存中只存在一个,并且每个对象都可以访问,存放在方法区(数据共享区) 1.1 stat ...
- javaSE基础06
javaSE基础06 一.匿名对象 没有名字的对象,叫做匿名对象. 1.2匿名对象的使用注意点: 1.我们一般不会用匿名对象给属性赋值的,无法获取属性值(现阶段只能设置和拿到一个属性值.只能调用一次方 ...
- javaSE基础05
javaSE基础05:面向对象 一.数组 数组的内存管理 : 一块连续的空间来存储元素. Int [ ] arr = new int[ ]; 创建一个int类型的数组,arr只是一个变量,只是数组的一 ...
- javaSE基础04
javaSE基础04 一.三木运算符 <表达式1> ? <表达式2> : <表达式3> "?"运算符的含义是: 先求表达式1的值, 如果为真, ...
- javaSE基础03
javaSE基础03 生活中常见的进制:十进制(0-9).星期(七进制(0-6)).时间(十二进制(0-11)).二十四进制(0-23) 进制之间的转换: 十进制转为二进制: 将十进制除以2,直到商为 ...
- javaSE基础02
javaSE基础02 一.javac命令和java命令做什么事情? javac:负责编译,当执行javac时,会启动java的编译程序,对指定扩展名的.java文件进行编译,生成了jvm可以识别的字节 ...
- JavaSE基础01
JavaSE基础篇01 ------从今天开始,我就学习正式java了,O(∩_∩)O哈哈~,请大家多指教哦 一.Windows常见的dos命令 操作dos命令: win7 --->开始 --- ...
- javase基础复习攻略《十》
按照计划本篇为大家总结JAVA的网络编程,什么叫网络编程呢?网络编程!=网站编程,对于这一点大家一定要注意,很多小朋友都曾经这么认为.既然谈到网络编程,咱们先了解一下网络的基础知识,什么是计算机网络? ...
- javase基础复习攻略《二》
今天就开始的真正走进JAVASE的世界,本篇介绍的是:JAVASE基础语法,大家如果有C语言的基础,对于本节内容一定感觉非常轻松,编程语言之间的都是相通的,只不过C语言属于面向过程编程,而JAVA语言 ...
- 基础1 JavaSe基础
JavaSe基础 1. 九种基本数据类型的大小,以及他们的封装类 boolean 无明确指定 Boolean char 16bits Character byte 8bits Byte short 1 ...
随机推荐
- Glide 这样用,更省内存!!!
一.前言 Glide 是 Google 官方推荐的一款图片加载库,使用起来也非常的简单便利,Glide 它帮我们完成了很多很重要,但是却通用的功能,例如:图片的加载压缩.展示.加载图片的内存管理等等. ...
- Java字符串的匹配问题,String类的matches方法与Matcher类的matches方法的使用比较,Matcher类的matches()、find()和lookingAt()方法的使用比较
参考网上相关blog,对Java字符串的匹配问题进行了简单的比较和总结,主要对String类的matches方法与Matcher类的matches方法进行了比较. 对Matcher类的matches( ...
- An Introduction to Variational Methods (5.3)
从之前的文章中,我们已经得到了所有需要求解的参数的优化分布的形式,分别为: 但是,我们从这些分布的表达式中(参见之前的文章),可以发现这些式子并不能够直接求解.这是因为各个参数之间相互耦合,从而导 ...
- django ajax练习
这几天遇到了django ajax请求出错的问题,总结一下 前端js:我这里创建的是一个字典格式的数据,前端js收到字典之后也是要用字典的形式去解包后台传送过来的数据,比如我下面的写法:data['s ...
- 前端基础之JavaScript
什么是JavaScript? JavaScript,也称ECMAScript,是一种基于对象和事件驱动并具有相对安全性并广泛用于客户端网页开发的脚本语言,同时也是一种广泛用于客户端Web开发的脚本语言 ...
- centos crontab(定时任务) 使用
一.介绍 crontab命令的功能是在一定的时间间隔调度一些命令的执行.当安装完成操作系统之后,默认便会启动此任务调度命令.crond命令每分锺会定期检查是否有要执行的工作,如果有要执行的工作便会 ...
- javascript正则表达式入门
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/ ...
- 百度SMS SDK for .Net
SMS 服务用于向指定的手机号码发送短信. 百度SMS提供了C, JAVA, Python的官方SDK,本项目依据API封装了面向.net的库,目前已经实现了基本的短信发送功能. 项目Github开源 ...
- Android进程间通信
http://www.cnblogs.com/manuosex/p/3588634.html 一.Linux系统进程间通信有哪些方式? 1.socket: 2.name pipe命名管道: 3.mes ...
- JAVA常用API(Date、DateFormat、Calendar、System、Math、基本数据类型包装类)
注:本文所有内容均属个人见解,如有错误望各位大佬好心指点批评,不胜感激 本章重点单词: parse:解析 format:格式化 pattern:模式 amount:数量 filed :领域 1.Dat ...