目录
1 Java语言概述
1.软件 : 系统软件 vs 应用软件
2.人与计算机做交互:使用计算机语言。
图形化界面 vs 命令行方式 dir md:创建文件夹 rd:删除目录 cd cd.. cd/:回退到根目录 del:删除文件 exit:退出dos命令行
3.语言的分类:第一代:机器语言 第二代:汇编语言 第三代:高级语言(面向过程 --- 面向对象)4.java语言的特性:①面向对象性 ②健壮性 ③跨平台性(write once ,run anywhere)---JVM(java虚拟机)
5.安装JDK及配置path环境变量
1)傻瓜式安装JDK。
2)path:window操作系统在执行命令时所要搜寻的路径。
我们需要将jdk中bin目录所在的路径:D:\Java\jdk1.7.0_07\bin 保存在path环境变量下。
3)测试:在命令行窗口,任意的文件目录下,执行javac.exe 或者java.exe都可以调用成功。
>河床好比操作底层,jdk好比是河水,java应用程序好比是船。
6.如何编写并运行第一个java程序
【过程】编写----编译----运行
1)编写:每一个java文件都是.java结尾的,称为源文件【HelloWorld.java】。java程序就存在于源文件中
public class HelloWorld{ //程序的主方法,是程序的入口 public static void main(String args[]){ //要执行的代码 System.out.println("HelloWorld"); } }
注意点:
Java源文件以“java”为扩展名。源文件的基本组成部分是类(class),如本类中的HelloWorld类。
一个源文件中最多只能有一个public类。其它类的个数不限,如果源文件包含一个public类,则文件名必须按该类名命名。
Java应用程序的执行入口是main()方法。它有固定的书写格式:public static void main(String[] args) {...}
Java语言严格区分大小写。
Java方法由一条条语句构成,每个语句以“;”结束。
大括号都是成对出现的,缺一不可。2)编译: 在源文件所在的目录下,执行javac.exe 源文件名.java;生成诸多个.class结尾的字节码文件
3)运行:生成的字节码文件通过java.exe解释执行javac hello.java
java hello7.会调试程序中出现的问题
8.注释: ①单行注释 // ②多行注释 /* */ (多行注释不能够嵌套)
③文档注释 /** */ javadoc -d 文件目录名 -author -version 源文件名.java;9.JDK提供的关于旗下所有的包、类的文档:API
2 基本语法
2.1 关键字 & 标识符
关键字:被Java语言赋予了特殊含义,用做专门用途的字符串(单词)
保留字:
标识符:凡是自己可以起名字的地方都叫标识符
命名的规则:(一定要遵守,不遵守就会报编译的错误)
由26个英文字母大小写,0-9 ,_或 $ 组成
数字不可以开头。
不可以使用关键字和保留字,但能包含关键字和保留字。
Java中严格区分大小写,长度无限制。
标识符不能包含空格。Java中的名称命名规范:(不遵守,也不会出现编译的错误)
包名:多单词组成时所有字母都小写:xxxyyyzzz
类名、接口名:多单词组成时,所有单词的首字母大写:XxxYyyZzz
变量名、方法名:多单词组成时,第一个单词首字母小写,第二个单词开始每个单词首字母大写:xxxYyyZzz
常量名:所有字母都大写。多单词时每个单词用下划线连接:XXX_YYY_ZZZ
2.2变量
1.java中变量按照数据类型来分类:基本数据类型 vs 引用数据类型(数组 类 接口)
>基本数据类型:
整型:byte(8 bit) short int(默认类型) long(+L)
浮点型:float(+F) double (默认类型)
字符型:char(‘ ’)
布尔类型: boolean(只能取值为true 或false,不能取null)补充:按照在类中存在的位置的不同:成员变量 vs 局部变量
2.进制(了解)
十进制 二进制 八进制 十六进制二进制:计算机底层都是用二进制来存储、运算。
>二进制 与十进制之间的转换。
>二进制在底层存储:正数、负数都是以补码的形式存储的。(原码、反码、补码)
>四种进制间的转换3.变量的运算:
①自动类型转换:容量小的数据类型自动转换为容量大的数据类型。
short s = 12;
int i = s + 2;
注意:byte short char之间做运算,结果为int型!
②强制类型转换:是①的逆过程。使用“()”实现强转。long l1 = 1234L;
int m1 = (int)l1;
2.3运算符
运算符是一种特殊的符号,用以表示数据的运算、赋值和比较等。
算术运算符:
+ - + - * / % ++ -- +
注意:1) /: int i = 12; i = i / 5;
2) %:最后的符号只跟被模数相同
3)前++:先+1,后运算 后++:先运算,后+1
4)+:String字符串与其他数据类型只能做连接运算,且结果为String类型。sysout('*' + '\t' + '*'); vs sysout("*" + '\t' + '*');
赋值运算符:
= += -= *= /= %=
int i= 12;
i = i * 5;
i *= 5;//与上一行代码同样的意思
【特别地】
short s = 10;
s = s + 5;//报编译的异常
s = (short)(s + 5);
s += 5;//s = s + 5,但是结果不会改变s的数据类型。
比较运算符(关系运算符)
== > < >= <= instanceof【注意】区分== 与 = 区别。
进行比较运算操作以后,返回一个boolean类型的值
4>=3 表达的是4 > 3或者 4 = 3.结果是true。if(i > 1 && i < 10){ }
不能写为:if(1 < i < 10){}逻辑运算符(运算符的两端是boolean值)
& &&短路与 | || ^异或 !
【注意】区分 & 与 && 的区别,以及 | 与 || 的区别
我们使用的时候,选择&& , ||位运算符(两端是数值类型的数据)
<< >> >>> & | ^ ~(取反+1)
【例子】1.如何交换m = 12和n = 5的值
2.将60转换为十六进制输出。三元运算符
(条件表达式)? 表达式1 : 表达式2;
1)既然是运算符,一定会返回一个结果,并且结果的数据类型与表达式1,2的类型一致
2)表达式1与表达式2 的数据类型一致。
3)使用三元运算符的,一定可以转换为if-else。反之不一定成立。
例子:获取两个数的较大值;获取三个数的最大值。
2.4 流程控制
1.顺序结构
>程序从上往下的顺序执行2.分支结构:
if-else
switch-case3.循环结构:
while(){}
do{}while()
for(;;){}
2.4.1 分支结构
1.条件判断:
①if(条件表达式){ }②if(条件表达式){
//执行的语句1;
}else{
//执行的语句2;
}③if(条件表达式1){
//执行的语句1;
}else if(条件表达式2){
//执行的语句2;
}else if( 条件表达式3){
//执行的语句3;
}...
}else{
//执行的语句;
}【注意】
1.一旦满足某个条件表达式,则进入其执行语句块执行,执行完毕,跳出当前的条件判断结构,不会执行其以下的条件结构语句。
2.如果诸多个条件表达式之间为“互斥”关系,多个结构可以上下调换顺序
如果诸多个条件表达式之间为“包含”关系,要求条件表达式范围小的写在范围大的上面。2.选择结构
switch(变量){
case 值1:
//break;
case 值2:
//break;
...
default:
break;
}【注意】
1.变量可以为如下的数据类型:byte short int char 枚举 String
2.case后只能填写变量的值,不能写范围。
3.default是可以省略的。并且其位置也是灵活的,但是通常将其放在case语句之后。
4.一旦满足某个case语句,则进入执行其操作。直至遇到break或者程序终止。
5.若要判断的语句的条件满足switch变量的数据类型,且值不多的情况下,建议选择switch-case .
除此之外,选择if-else.
2.4.2 循环结构
1.格式:
①初始化条件
②循环条件
③迭代部分
④循环体
for(①;②;③){
④
}①
while(②){
④
③
}①
do{
④
③
}while(②);注:1.不同的循环结构之间可以相互转换
2.while和do-while的区别:do-while程序至少会执行一次2.嵌套循环:循环结构还可以声明循环。让内层循环结构整体充当外层循环的循环体。
若外层循环执行m次,内层循环执行n次,整个程序执行m*n次。【题目】
******
******
******
for(int i = 0;i < 3;i++){
for(int j = 0;j < 6;j++){
System.out.print("*");
}
System.out.println();
}
说明:外层循环控制行数,内层循环控制列数
【例题】1.九九乘法表 2.输出100内的质数。(两种)
3.无限循环结构
for(;;){
...
if( ){
break;
}
...
}
或者
while(true){
...
if( ){
break;
}
...
}
往往我们在无限循环结构内部提供循环的终止条件,使用break关键字。否则,此循环将无限制的执行下去,形成死循环!
死循环是我们要避免的。
2.4.3 break &continue
break:
>使用switch-case结构或者循环结构中
>在循环结构中,一旦执行到break,就跳出当前循环。continue:使用在循环结构中
>一旦执行到continue,就跳出当次循环。
for(int i = 1;i <= 10;i++){
if(i % 4 == 0){
//break; //123
continue; //123567910
}System.out.print(i);
}
在嵌套循环中,使用带标签的break和continue。
label:for(int i = 1;i < 5;i++){
for(int j = 1;j <= 10;j++){
if(j % 4 == 0){
//break;
//continue;
//break label;
continue label;
}
System.out.print(j);
}
System.out.println();
}
2.5 数组
数组:相同数据类型的数据的组合。
如: int score1 = 72;
int score2 = 90;
int score3 = 59;使用数组:
1.数组的初始化
int[] scores1 = new int[]{72,90,59};//静态初始化:在声明并初始化数组与给数组相应的元素赋值操作同时进行。
int scores2[] = new int[3];//动态初始化:在声明并初始化数组与给数组相应的元素赋值操作分开进行。
scores2[0] = 72;
scores2[1] = 90;
scores2[2] = 59;
//声明数组的错误写法:
1)String[] names = new String[5]{"AA","BB","CC"};
2)int i[10];
3)int i = new int[];
注:不管是动态还是静态初始化数组,一定在创建的时候,就指明了数组的长度!
2.如何引用数组元素:通过数组的下角标的方式。下角标从0开始,到n-1结束。其中n为数组的长度。
3.数组的长度:通过数组的属性length来调用。
System.out.println(scores2.length);//3
4.如何遍历数组
for(int i = 0;i < scores1.length;i++){
System.out.println(scores1[i]);
}
5.关于数组元素的默认初始化值
1)byte short int long 而言:0
2)float double 而言:0.0
3)char而言:空格
4)boolean而言:false
5)引用类型变量而言:null6.数组的内存结构
对于数组来讲:
2.5.1 二维数组
1.声明并初始化
//一维:
int[] i = new int[12];
i[0] = 12;int[] j = new int[]{12,3};
//二维:
1)String[][] str = new String[4][3]; //4行3列2)String[][] str1 = new String[4][];
str1[0] = new String[3];
...
str1[3] = new String[5];
3)
int[][] arr = new int[][]{{1,2,3},{4,5},{6}};2.如何引用二维数组的元素:arr[1][0] = 12;
3.二维数组的长度:arr.length;//3
arr[1].length;//24.遍历二维数组
for(int i = 0;i < arr.length;i++){
for(int j = 0;j < arr[i].length;j++){
System.out.print(arr[i][j] + "\t");
}
System.out.println();
}
5.二维数组的结构:
2.5.2 数组常见异常
//1.数组下标越界的异常:java.lang.ArrayIndexOutOfBoundsException
int[] i = new int[10];
// i[0] = 90;
// i[10] = 99;
// for(int m = 0;m <= i.length;m++){
// System.out.println(i[m]);
// }
//2.空指针的异常:NullPointerException
//第一种:
// boolean[] b = new boolean[3];
// b = null;
// System.out.println(b[0]);
//第二种:
// String[] str = new String[4];
// //str[3] = new String("AA");//str[3] = "AA";
// System.out.println(str[3].toString());
//第三种:
int[][] j = new int[3][];
j[2][0] = 12;
2.5.3 数组的常用的算法问题
1.求数组元素的最大值、最小值、和、平均数
2.数组的复制和反转
情况1:
情况2:(如何实现复制)
数组的反转:
// 数组元素的反转
// for(int i = 0;i < arr.length/2;i++){
// int temp = arr[i];
// arr[i] = arr[arr.length-1 - i];
// arr[arr.length - 1 - i] = temp;
// }
for (int x = 0, y = arr.length - 1; x < y; x++, y--) {
int temp = arr[x];
arr[x] = arr[y];
arr[y] = temp;
}拓展:String str = "abcdefg";
数组的排序:
插入排序
直接插入排序、折半插入排序、Shell排序交换排序
冒泡排序、快速排序(或分区交换排序)选择排序
简单选择排序、堆排序归并排序
基数排序
// 使用冒泡排序使数组元素从小到大排列
// for (int i = 0; i < arr.length - 1; i++) {
// for (int j = 0; j < arr.length - 1 - i; j++) {
// if (arr[j] > arr[j + 1]) {
// int temp = arr[j];
// arr[j] = arr[j + 1];
// arr[j + 1] = temp;
// }
// }
// }
// //使用直接选择排序使数组元素从小到大排列
// for(int i = 0; i < arr.length - 1; i++){
// int t = i;//默认i处是最小的
// for(int j = i;j < arr.length;j++){
// //一旦在i后发现存在比其小的元素,就记录那个元素的下角标
// if(arr[t] > arr[j]){
// t = j;
// }
// }
// if(t != i){
// int temp = arr[t];
// arr[t] = arr[i];
// arr[i] = temp;
// }
// }还可以调用:Arrays工具类:Arrays.sort(arr);
3 面向对象(一)
3.1 类及对象
1.关于于类的设计
2.类的组成成分:
1) 属性(成员变量,Field)
2)方法(成员方法,函数,Method)2.1属性:
* 成员变量 vs 局部变量
* 相同点:1.遵循变量声明的格式: 数据类型 变量名 = 初始化值
* 2.都有作用域
* 不同点:1.声明的位置的不同 :成员变量:声明在类里,方法外
* 局部变量:声明在方法内,方法的形参部分,代码块内
* 2.成员变量的修饰符有四个:public private protected 缺省
* 局部变量没有修饰符,与所在的方法修饰符相同。
* 3.初始化值:一定会有初始化值。
* 成员变量:如果在声明的时候,不显式的赋值,那么不同数据类型会有不同的默认初始化值。
* byte short int long ==>0
* float double ==>0.0
* char ==>空格
* boolean ==>false
* 引用类型变量==>null
* 局部变量:一定要显式的赋值。(局部变量没有默认初始化值)
* 4.二者在内存中存放的位置不同:成员变量存在于堆空间中;局部变量:栈空间中
*
* 总结:关于变量的分类:1)按照数据类型的不同:基本数据类型(8种) & 引用数据类型
* 2)按照声明的位置的不同:成员变量 & 局部变量2.2 方法:提供某种功能的实现
* 1)实例:public void eat(){//方法体}
* public String getName(){}
* public void setName(String n){}
* 格式:权限修饰符 返回值类型(void:无返回值/具体的返回值) 方法名(形参){}
*
* 2)关于返回值类型:void:表明此方法不需要返回值
* 有返回值的方法:在方法的最后一定有return + 返回值类型对应的变量
* 记忆:void 与return不可以同时出现一个方法内。像一对“冤家”。
*
* 3)方法内可以调用本类的其他方法或属性,但是不能在方法内再定义方法!
3.面向对象编程的思想的落地法则一:
1)设计并创建类及类的成分
2)实例化类的对象
3)通过“对象.属性”或"对象.方法"的形式完成某项功能4.类的初始化的内存解析
4.1 内存划分的结构:
栈(stack):局部变量 、对象的引用名、数组的引用名
堆(heap):new 出来的“东西”(如:对象的实体,数组的实体),含成员变量
方法区:含字符串常量
静态域:声明为static的变量4.2 理解的基础上,学会基本的创建的类的对象在内存中的运行。
3.2 方法的重载
* 方法的重载(overload)
* 要求:1.同一个类中 2.方法名必须相同 3.方法的参数列表不同(①参数的个数不同②参数类型不同)
* 补充:方法的重载与方法的返回值类型没有关系!//如下的四个方法构成重载
//定义两个int型变量的和
public int getSum(int i,int j){
return i + j;
}
//定义三个int型变量的和
public int getSum(int i,int j,int k){
return i + j + k;
}
//定义两个double型数据的和
public double getSum(double d1,double d2){
return d1 + d2;
}//定义三个double型数组的和
public void getSum(double d1,double d2,double d3){
System.out.println(d1 + d2 + d3);
}
//不能与如上的几个方法构成重载
// public int getSum1(int i,int j,int k){
// return i + j + k;
// }
// public void getSum(int i,int j,int k){
// System.out.println(i + j + k);
// }
//以下的两个方法构成重载。
public void method1(int i,String str){
}
public void method1(String str1,int j){
}
3.3 可变个数的形参的方法
* 可变个数的形参的方法:
* 1.格式:对于方法的形参: 数据类型 ... 形参名
* 2.可变个数的形参的方法与同名的方法之间构成重载
* 3.可变个数的形参在调用时,个数从0开始,到无穷多个都可以。
* 4.使用可变多个形参的方法与方法的形参使用数组是一致的。
* 5.若方法中存在可变个数的形参,那么一定要声明在方法形参的最后。
* 6.在一个方法中,最多声明一个可变个数的形参。
//如下四个方法构成重载
//在类中一旦定义了重载的可变个数的形参的方法以后,如下的两个方法可以省略
// public void sayHello(){
// System.out.println("hello world!");
// }
// public void sayHello(String str1){
// System.out.println("hello " + str1);
// }
//可变个数的形参的方法
public void sayHello(String ... args){
for(int i = 0;i < args.length;i++){
System.out.println(args[i] + "$");
}
//System.out.println("=====");
}
public void sayHello(int i,String ... args){
//public void sayHello(String ... args,int i){
System.out.println(i);
for(int j = 0;j < args.length;j++){
System.out.println(args[j] + "$");
}
}
public void sayHello1(String[] args){
for(int i = 0;i < args.length;i++){
System.out.println(args[i]);
}
}
3.4 java的值传递机制
重点、难点
* 方法的参数传递(重点、难点)
* 1.形参:方法声明时,方法小括号内的参数
* 实参:调用方法时,实际传入的参数的值
*
* 2.规则:java中的参数传递机制:值传递机制
* 1)形参是基本数据类型的:将实参的值传递给形参的基本数据类型的变量
* 2)形参是引用数据类型的:将实参的引用类型变量的值(对应的堆空间的对象实体的首地址值)传递给形参的引用类型变量。
【典型例题1】public static void main(String[] args) {
TestArgsTransfer tt = new TestArgsTransfer();
int i = 10;
int j = 5;
System.out.println("i:" + i + " j:" + j);//i : 10 j : 5
// //交换变量i与j的值
// int temp = i;
// i = j;
// j = temp;
tt.swap(i, j);//将i的值传递给m,j的值传递给n
System.out.println("i:" + i + " j:" + j);//i : 10 j : 5
}
//定义一个方法,交换两个变量的值
public void swap(int m,int n){
int temp = m;
m = n;
n = temp;
System.out.println("m:" + m + " n:" + n);}
使用swap方法以后:
【典型例题2】
public class TestArgsTransfer1 {
public static void main(String[] args) {
TestArgsTransfer1 tt = new TestArgsTransfer1();
DataSwap ds = new DataSwap();
System.out.println("ds.i:" + ds.i + " ds.j:" + ds.j);
tt.swap(ds);
System.out.println(ds);
System.out.println("ds.i:" + ds.i + " ds.j:" + ds.j);
}
//交换元素的值
public void swap(DataSwap d){
int temp = d.i;
d.i = d.j;
d.j = temp;
System.out.println(d);//打印引用变量d的值
}
}class DataSwap{
int i = 10;
int j = 5;
}
3.5 面向对象的特征一:封装性
* 一、面向对象的特征一:封装与隐藏
* 问题:当创建了类的对象以后,如果直接通过"对象.属性"的方式对相应的对象属性赋值的话,可能会出现不满足实际
* 情况的意外,我们考虑不让对象来直接作用属性,而是通过"对象.方法"的形式,来控制对象对属性的访问。实际
* 情况中,对属性的要求就可以通过方法来体现。
*
二、面向对象思想的落地法则二:
(封装性的思想)①将类的属性私有化,②提供公共的方法(setter & getter)来实现调用。三、四种权限修饰符
1.权限从大到小为:public protected 缺省 private
2.四种权限都可以用来修饰属性、方法、构造器
3.修饰类的话:public 缺省
3.6 构造器
* 一、类的第三个成员:构造器(constructor 构造方法) construction CCB ICBC oop
* constructor:建造者
* 构造器的作用:①创建对象 ②给创建的对象的属性赋值
*
* 1.设计类时,若不显式声明类的构造器的话,程序会默认提供一个空参的构造器.
* 2.一旦显式的定义类的构造器,那么默认的构造器就不再提供。
* 3.如何声明类的构造器。格式:权限修饰符 类名(形参){ }
* 4.类的多个构造器之间构成重载
* 二、类对象的属性赋值的先后顺序:①属性的默认初始化 ②属性的显式初始化③通过构造器给属性初始化
* ④通过"对象.方法"的方式给属性赋值
3.7 this关键字
this:
1.使用在类中,可以用来修饰属性、方法、构造器
2.表示当前对象或者是当前正在创建的对象
3.当形参与成员变量重名时,如果在方法内部需要使用成员变量,必须添加this来表明该变量时类成员
4.在任意方法内,如果使用当前类的成员变量或成员方法可以在其前面添加this,增强程序的阅读性
5.在构造器中使用“this(形参列表)”显式的调用本类中重载的其它的构造器
>5.1 要求“this(形参列表)”要声明在构造器的首行!
>5.2 类中若存在n个构造器,那么最多有n-1构造器中使用了this。public class TestPerson {
public static void main(String[] args) {
Person p1 = new Person();
System.out.println(p1.getName() + ":" + p1.getAge());
Person p2 = new Person("BB",23);
int temp = p2.compare(p1);
System.out.println(temp);
}
}
class Person{
private String name;
private int age;
public Person(){
this.name = "AA";
this.age = 1;
}
public Person(String name){
this();
this.name = name;
}
public Person(String name,int age){
this(name);
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public void eat(){
System.out.println("eating");
}
public void sleep(){
System.out.println("sleeping");
this.eat();
}
//比较当前对象与形参的对象的age谁大。
public int compare(Person p){
if(this.age > p.age)
return 1;
else if(this.age < p.age)
return -1;
else
return 0;
}
}
3.8 package & import
/*
* package:声明源文件所在的包,写在程序的第一行。
* 每“.”一次,表示一层文件目录。
* 包名都要小写。
*
* import:
* 1)显式导入指定包下的类或接口
* 2)写在包的声明和源文件之间
* 3)如果需要引入多个类或接口,那么就并列写出
* 4)如果导入的类是java.lang包下的,如:System String Math等,就不需要显式的声明。
* 5)理解.*的概念。比如java.util.*;
* 6)如何处理同名类的导入。如:在util包和sql包下同时存在Date类。
* 7)import static 表示导入指定类的static的属性或方法
* 8)导入java.lang.*只能导入lang包下的所有类或接口,不能导入lang的子包下的类或接口
*/
//import java.util.Scanner;
//import java.util.Date;
//import java.util.List;
//import java.util.ArrayList;
import java.lang.reflect.Field;
import java.util.*;
import static java.lang.System.*;
public class TestPackageImport {
public static void main(String[] args) {
out.println("helloworld");
Scanner s = new Scanner(System.in);
s.next();
Date d = new Date();
List list = new ArrayList();
java.sql.Date d1 = new java.sql.Date(522535114234L);
Field f = null;
}
}
4 面向对象(二)
4.1 面向对象的特征二:继承性
1.为什么要有继承性:
2.通过"class A extends B"类实现类的继承。
* 子类:A 父类(或基类 SuperClass):B
*
* 3.子类继承父类以后,父类中声明的属性、方法,子类就可以获取到。
* 明确:当父类中有私有的属性或方法时,子类同样可以获取得到,只是由于封装性的设计,使得子类不可以直接
* 调用罢了。
* 子类除了通过继承,获取父类的结构之外,还可以定义自己的特有的成分。
*
* extends:子类是对父类功能的“扩展”,明确子类不是父类的子集。
*
* 4.java中类的继承性只支持单继承:一个类只能继承一个父类。反之,一个父类可以有多个子类。
* 5.子父类是相对的概念。
4.1.1 方法的重写
1.方法的重写(override orverwrite) vs 重载(overload)
【面试题】方法的重载与重写的区别?
重载:“两同一不同”:同一个类,同一个方法名,不同的参数列表。 注:方法的重载与方法的返回值无关!
>构造器是可以重载的
重写:(前提:在继承的基础之上,子类在获取了父类的结构以后,可以对父类中同名的方法进行“重构”)
方法的返回值,方法名,形参列表形同;权限修饰符不小于父类的同名方法;子类方法的异常类型不大于父类的;
两个方法要同为static或同为非static。
public void method1(String[] str,int age) throws Exception{}
class Cirlce{
//求圆的面积
public double findArea(){
}}
class Cylinder extends Circle{
//求圆柱的表面积
public double findArea(){
}
}
4.2 关键字super
1.super,相较于关键字this,可以修饰属性、方法、构造器
2.super修饰属性、方法:在子类的方法、构造器中,通过super.属性或者super.方法的形式,显式的调用父类的指定
属性或方法。尤其是,当子类与父类有同名的属性、或方法时,调用父类中的结构的话,一定要用“super.”3.通过“super(形参列表)”,显式的在子类的构造器中,调用父类指定的构造器!
>任何一个类(除Object类)的构造器的首行,要么显式的调用本类中重载的其它的构造器“this(形参列表)”或显式的调用父类中
指定的构造器“super(形参列表)”,要么默认的调用父类空参的构造器"super()"
>建议在设计类时,提供一个空参的构造器!
4.3 子类对象实例化的全过程
//子类对象实例化的全过程
public class TestDog {
public static void main(String[] args) {
Dog d = new Dog();
d.setAge(10);
d.setName("小明");
d.setHostName("花花");System.out.println("name:" + d.getName() + " age:" + d.getAge()
+ "hostName:" + d.getHostName());
System.out.println(d.toString());
}
}// 生物
class Creator {
private int age;public int getAge() {
return age;
}public void setAge(int age) {
this.age = age;
}public Creator() {
super();
System.out.println("this is Creator's constructor");
}}
// 动物类
class Animal extends Creator {
private String name;public String getName() {
return name;
}public void setName(String name) {
this.name = name;
}public Animal() {
super();
System.out.println("this is Animal's constructor");
}}
// 狗
class Dog extends Animal {
private String hostName;public String getHostName() {
return hostName;
}public void setHostName(String hostName) {
this.hostName = hostName;
}public Dog() {
super();
System.out.println("this is Dog's constructor");
}}
4.4 面向对象特征三:多态性
1.多态性的表现:①方法的重载与重写 ②子类对象的多态性
2.使用的前提:①要有继承关系 ②要有方法的重写
3.格式:Person p = new Man();//向上转型
// 虚拟方法调用:通过父类的引用指向子类的对象实体,当调用方法时,实际执行的是子类重写父类的方法
p1.eat();
p1.walk();
// p1.entertainment();
4.>编译时,认为p是Person类型的,故只能执行Person里才有的结构,即Man里特有的结构不能够调用
>子类对象的多态性,并不使用于属性。5.关于向下转型:
①向下转型,使用强转符:()
②为了保证不报ClassCastException,最好在向下转型前,进行判断: instanceof
// 若a是A类的实例,那么a也一定是A类的父类的实例。
if (p1 instanceof Woman) {
System.out.println("hello!");
Woman w1 = (Woman) p1;
w1.shopping();
}if (p1 instanceof Man) {
Man m1 = (Man) p1;
m1.entertainment();
}
4.5 Object类
1.java.lang.Object 类,是所有类的根父类!
2.Object类仅有一个空参的构造器 public Object(){ }
3.关于方法:
① equals(Object obj)public boolean equals(Object obj) {
return (this == obj);
}// ==
// 1.基本数据类型:根据基本数据类型的值判断是否相等。相等返回true,反之返回false
// 注:两端数据类型可以不同,在不同的情况下,也可以返回true。
// 2.引用数据类型:比较引用类型变量的地址值是否相等。//equals():
>①只能处理引用类型变量②在Object类,发现equals()仍然比较的两个引用变量的地址值是否相等
>像String 包装类 File类 Date类这些重写Object类的equals()方法,比较是两个对象的
//"实体内容"是否完全相同。
>若我们自定义一个类,希望比较两个对象的属性值都相同的情况下返回true的话,就需要重写Object类的
equals(Object obj)方法② toString()方法
当我们输出一个对象的引用时,会调用toString()方法。
1.public String toString() {
return getClass().getName() + "@" + Integer.toHexString(hashCode());
}
当我们没有重写Object类的toString()方法时,打印的就是对象所在的类,以及对象实体在堆空间的位置
2.一般我们需要重写Object类的toString()方法,将此对象的各个属性值返回。
3.像String类、Date、File类、包装类都重写了toString()方法。
4.6 包装类
基本数据类型由于不是类,不能够使用java类库里提供的大量的方法。所有在设计上,
我们让每一个基本数据类型都对应一个类,同时数据存储的范围还不变。此时相当于
基本数据类型就具有了类的特点。这些类即为包装类(wrapper 或封装类)
我们需要掌握的:
基本数据类型、包装类、String类之间的转换!
简易版:
1.基本数据类型与对应的包装类有自动装箱、自动拆箱
如:int i = 10;
Integer i1 = i;//自动装箱
int j = i1;//自动拆箱
2.基本数据类型、包装类---->String类:调用String类的重载的valueOf(Xxx xx);
String类---->基本数据类型、包装类:调用相应的包装的parseXxx(String str);
注意:String str = "123";
int i = (int)str;是错误的转法。
5 面向对象(三)
5.1 static关键字
1.static:静态的,可以用来修饰属性、方法、*代码块(或初始化块)、*内部类
2.
static修饰属性(类变量):
* 1.由类创建的所有的对象,都共用这一个属性
* 2.当其中一个对象对此属性进行修改,会导致其他对象对此属性的一个调用。vs 实例变量(非static修饰的属性,各个对象各自拥有一套副本)
* 3.类变量随着类的加载而加载的,而且独一份
* 4.静态的变量可以直接通过“类.类变量”的形式来调用
* 5.类变量的加载是要早于对象。所以当有对象以后,可以“对象.类变量”使用。但是"类.实例变量"是不行的。
* 6.类变量存在于静态域中。
*
* static修饰方法(类方法):
* 1.随着类的加载而加载,在内存中也是独一份
* 2.可以直接通过“类.类方法”的方式调用
* 3.内部可以调用静态的属性或静态的方法,而不能调用非静态的属性或方法。反之,非静态的方法是可以调用静态的属性或静态的方法
* >静态的方法内是不可以有this或super关键字的!
* 注:静态的结构(static的属性、方法、代码块、内部类)的生命周期要早于非静态的结构,同时被回收也要晚于非静态的结构
public class TestCircle {
public static void main(String[] args) {
Circle c1 = new Circle();
Circle c2 = new Circle(2.3);
System.out.println(c1);
System.out.println(c2);
System.out.println(Circle.getTotal());
}
}class Circle{
private double radius;
private static String info = "我是一个圆";
private int id;//编号
private static int init = 1001;//控制每个对象的id
private static int total = 0;//记录创建了多少个对象
public Circle(){
this.id = init++;
total++;
}
public Circle(double radius){
this.radius = radius;
this.id = init++;
total++;
}
public double getRadius() {
return radius;
}
public void setRadius(double radius) {
this.radius = radius;
}
public static String getInfo() {
return info;
}
public static void setInfo(String info) {
Circle.info = info;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public static int getTotal() {
return total;
}
public static void setTotal(int total) {
Circle.total = total;
}
@Override
public String toString() {
return "Circle [radius=" + radius + ", id=" + id + "]";
}
public static void show(){
System.out.println(Circle.info);
}
public void desc(){
System.out.println(this.info);
}}
5.1.1 单例模式
23种设计模式
单例模式:
解决的问题:如何只让设计的类只能创建一个对象
如何实现:饿汉式 & 懒汉式
//饿汉式1
class Bank{
//1.私有化构造器
private Bank(){}
//2.创建类的对象,同时设置为private的,通过公共的来调用,体现封装性
//4.要求此对象也为static的
private static Bank instance = new Bank();
//3.此公共的方法,必须为static
public static Bank getInstance(){
return instance;
}
}//饿汉式2
class Bank{
//1.私有化构造器
private Bank(){}
//2.创建类的对象,同时设置为private的,通过公共的来调用,体现封装性
//4.要求此对象也为static的
private static Bank instance = null;
static{
instance = new Bank();
}
//3.此公共的方法,必须为static
public static Bank getInstance(){
return instance;
}
}//懒汉式
class Bank{
private Bank(){}
private static Bank instance = null;
public static Bank getInstance(){
if(instance == null){//可能存在线程安全问题的!
instance = new Bank();
}
return instance;
}
}
5.2 main()方法
public static void main(String[] args){
//方法体
}//1.main()是一个方法,是主方法,为程序的入口
//2.权限修饰符:public protected 缺省 private ---面向对象的封装性
//3.对于方法来讲:static final abstract
//4.方法的返回值:void / 具体的返回值类型(基本的数据类型 & 引用数据类型),方法内部一定要有return
//5.方法名:命名的规则:xxxYyyZzz。给方法命名时,要见名之意
//6.形参列表:同一个方法名不同的形参列表的诸多个方法间构成重载。 形参 & 实参---方法的参数传递机制:值传递
//7.方法体:方法定义的是一种功能,具体的实现由方法体操作。
5.3 代码块
代码块:是类的第4个成员
作用:用来初始化类的属性
分类:只能用static来修饰。* 静态代码块:
* 1.里面可以有输出语句
* 2.随着类的加载而加载,而且只被加载一次
* 3.多个静态代码块之间按照顺序结构执行
* 4.静态代码块的执行要早于非静态代码块的执行。
* 5.静态的代码块中只能执行静态的结构(类属性,类方法)
*
* 非静态代码块:
* 1.可以对类的属性(静态的 & 非静态的)进行初始化操作,同时也可以调用本类声明的方法(静态的 & 非静态的)
* 2.里面可以有输出语句
* 3.一个类中可以有多个非静态的代码块,多个代码块之间按照顺序结构执行
* 4.每创建一个类的对象,非静态代码块就加载一次。
* 5.非静态代码块的执行要早于构造器
*
* 关于属性赋值的操作:
①默认的初始化
②显式的初始化或代码块初始化(此处两个结构按照顺序执行)
③构造器中;
—————————以上是对象的属性初始化的过程—————————————
④通过方法对对象的相应属性进行修改
5.4 final关键字
/*
* final:最终的 ,可以用来修饰类、属性、方法
*
* 1.final修饰类:这个类就不能被继承。如:String类、StringBuffer类、System类
*
* 2.final修饰方法:不能被重写。如:Object类的getClass()
*
* 3.final修饰属性:此属性就是一个常量,一旦初始化后,不可再被赋值。习惯上,常量用大写字符表示。
* 此常量在哪里赋值:①此常量不能使用默认初始化 ②可以显式的赋值、代码块、构造器。
*
* 变量用static final修饰:全局常量。比如:Math 类的PI
*
* >与finally finalize()区分开
*
*/class D{
final int I = 12;
final double PI;
final String NAME;public void m1(){
System.out.println(I);
// I = 10;}
{
PI = 3.14;
}
public D(){
NAME = "DD";
}
public D(String name){
this();
//NAME = name;
}
}
5.5 抽象:abstract
重点!
abstract:抽象的,可以用来修饰类、方法
* 1.abstract修饰类:抽象类
* 1)不可被实例化
* 2)抽象类有构造器 (凡是类都有构造器)
* 3)抽象方法所在的类,一定是抽象类。
* 4)抽象类中可以没有抽象方法。
* >当我们设计一个类,不需要创建此类的实例时候,就可以考虑将其设置为抽象的,由其子类实现这个类的抽象方法以后,就行实例化
*
* 2.abstract修饰方法:抽象方法
* 1)格式:没有方法体,包括{}.如:public abstract void eat();
* 2)抽象方法只保留方法的功能,而具体的执行,交给继承抽象类的子类,由子类重写此抽象方法。
* 3)若子类继承抽象类,并重写了所有的抽象方法,则此类是一个"实体类",即可以实例化
* 4)若子类继承抽象类,没有重写所有的抽象方法,意味着此类中仍有抽象方法,则此类必须声明为抽象的!
5.5.1 模板方法的设计模式
//模板方法设计模式
public class TestTemplate {
public static void main(String[] args) {
new SubTemplate().spendTime();
}
}abstract class Template {
public abstract void code();
public void spendTime() {
long start = System.currentTimeMillis();this.code();
long end = System.currentTimeMillis();
System.out.println("花费的时间为:" + (end - start));
}
}class SubTemplate extends Template {
public void code() {
boolean flag = false;
for(int i = 2;i <= 10000;i++){
for(int j = 2;j <= Math.sqrt(i);j++){
if(i % j == 0){
flag = true;
break;
}
}
if(!flag){
System.out.println(i);
}
flag = false;
}
}
}
5.6 接口interface
* 接口(interface) 是与类并行的一个概念
* 1.接口可以看做是一个特殊的抽象类。是常量与抽象方法的一个集合,不能包含变量、一般的方法。
* 2.接口是没有构造器的。
* 3.接口定义的就是一种功能。此功能可以被类所实现(implements)。
* 比如:class CC extends DD implements AA
* 4.实现接口的类,必须要重写其中的所有的抽象方法,方可实例化。若没有重写所有的抽象方法,则此类仍为一个抽象类
* 5.类可以实现多个接口。----java 中的类的继承是单继承的
* 6.接口与接口之间也是继承的关系,而且可以实现多继承
* >5,6描述的是java中的继承的特点。
* 7.接口与具体的实现类之间也存在多态性* 8.面向接口编程的思想:
5.6.1 工厂方法的设计模式
//接口的应用:工厂方法的设计模式
public class TestFactoryMethod {
public static void main(String[] args) {
IWorkFactory i = new StudentWorkFactory();
i.getWork().doWork();
IWorkFactory i1 = new TeacherWorkFactory();
i1.getWork().doWork();
}
}interface IWorkFactory{
Work getWork();
}
class StudentWorkFactory implements IWorkFactory{@Override
public Work getWork() {
return new StudentWork();
}
}
class TeacherWorkFactory implements IWorkFactory{@Override
public Work getWork() {
return new TeacherWork();
}
}interface Work{
void doWork();
}class StudentWork implements Work{
@Override
public void doWork() {
System.out.println("学生写作业");
}
}
class TeacherWork implements Work{@Override
public void doWork() {
System.out.println("老师批改作业");
}
}
5.6.2 代理模式
//接口的应用:代理模式(静态代理)
public class TestProxy {
public static void main(String[] args) {
Object obj = new ProxyObject();
obj.action();
}
}interface Object{
void action();
}
//代理类
class ProxyObject implements Object{
Object obj;
public ProxyObject(){
System.out.println("代理类创建成功");
obj = new ObjctImpl();
}
public void action(){
System.out.println("代理类开始执行");
obj.action();
System.out.println("代理类执行结束");
}
}
//被代理类
class ObjctImpl implements Object{@Override
public void action() {
System.out.println("=====被代理类开始执行======");
System.out.println("=====具体的操作======");
System.out.println("=====被代理类执行完毕======");
}
}
5.7 内部类
* 类的第5个成员:内部类
* 1.相当于说,我们可以在类的内部再定义类。外面的类:外部类。里面定义的类:内部类
* 2.内部类的分类:成员内部类(声明在类内部且方法外的) vs 局部内部类(声明在类的方法里)
* 3.成员内部类:
* 3.1是外部类的一个成员:①可以有修饰符(4个)②static final ③可以调用外部类的属性、方法
*
* 3.2具体类的特点:①abstract ②还可以在其内部定义属性、方法、构造器
*
* 4.局部内部类:
*
* 5.关于内部类,大家掌握三点:
* ①如何创建成员内部类的对象(如:创建Bird类和Dog类的对象)
* ②如何区分调用外部类、内部类的变量(尤其是变量重名时)
* ③局部内部类的使用 (见TestInnerClass1.java)
总结
面向对象的三条主线:
1.类及类的成分
2.面向对象的三大特性
3.其他的关键字:this super import package abstract static final interface等1.java程序是关注于类的设计。类从代码的角度:并列关系! 从执行、设计的角度:关联关系、继承关系、聚合关系
class A{}
class B{
A a = new A();
}
2.类的成分:属性 方法 构造器 代码块 内部类
2.1 属性:①变量的分类:成员变量(属性 Field) vs 局部变量(方法的形参、方法内部、代码块内部)
基本数据类型(8种,不同的数据类型对应不同的默认初始化值) vs 引用数据类型(数组、类、接口 默认初始化值为null)
②属性的声明格式:修饰符 数据类型 变量名 = 初始化值;//java是强数据类型的语言
③对属性的赋值的操作:1.默认初始化 2.显式的初始化 3.代码块的初始化 4.构造器的初始化;5.调用方法、属性进行赋值
2.2 方法 ①格式:修饰符 (其它的关键字:static/final/abstract)返回值类型 方法名(形参列表){ //方法体 }
②方法的重载(overload) vs 方法的重写(override overwrite)
③ 方法的参数传递机制:值传递(难点)
2.3构造器 ①构造器的作用:1.创建类的对象 2.初始化对象的成员变量
②构造器也是可以重载的。
2.4 代码块 主要作用:用来初始化类的成员变量
分类:静态的代码块 vs 非静态的代码块
2.5 内部类 ①分类:成员内部类(static的成员 vs 非static的成员) vs 局部内部类(方法内部声明的类)
②掌握 :①如何创建成员内部类的对象(如:创建Bird类和Dog类的对象)
②如何区分调用外部类、内部类的变量(尤其是变量重名时)
③局部内部类的使用 (见TestInnerClass1.java)
3. 类的初始化(创建类的对象)
3.1 如何创建类的对象。如: Person p = new Person(); Date d = new Date();
3.2 内存解析:
①栈:局部变量、对象的引用名、数组的引用名
堆:new 出来的“东西”
方法区:(字符串常量池)
静态域:存放类中静态的变量
②如何理解创建的对象在内存中加载的过程(理解)
3.3 子类对象实例化的全过程: SubClass sc = new SubClass();
4.面向对象的三大特性:
4.1 封装性:
① 通过私有化类的成员变量,通过公共的getter和setter方法来调用和修改
② 还可以对类的其他结构进行“封装”
③ 权限修饰符:public protected 缺省 private
4.2 继承性:
通过让一个类A继承另一个类B,就可以获取类B中的结构(主要的:属性、方法、构造器)。子类:类A 父类:类B
>java中的类的继承性:单继承的。
4.3 多态性:
①体现:方法的重载与重写 ; 子类对象的多态性 Person p = new Student();
②子类对象多态性的使用:虚拟方法调用。
③向上转型 向下转型 Student s = (Student)p; //建议在向下转型之前: if ( p instanceof Student)避免出现ClassCastException的异常5.其它关键字:
5.1 this:修饰属性、方法、构造器 。表示:当前对象或当前正在创建的对象
5.2 super:修饰属性、方法、构造器。显式的调用父类的相应的结构,尤其是子父类有重名的方法、属性
5.3 static : 修饰属性、方法、代码块、内部类。随着类的加载而加载!
5.4 final:修饰类、属性、方法。表示“最终的”
5.5 abstract : 修饰类、方法
5.6 interface:表示是一个接口,(接口是与类并列的一个结构)。类与接口之间同时“implements”发生关系。
5.7 package import 。。。
>abstract不能修饰属性、构造器、不能与final static private共用。