输入方法
Scanner sc = new Scanner(System.in);
int r = sc.nextInt();
多个数据类型级别 由小转大
byte,short,char -->int -->long -->float -->double
两个数交换的四种方式
1.中间变量法: 利用中间变量temp,将两个数交换
2.数学运算法: 先将两变量a和b的和赋给其中一个变量(如a),
另一个变量b则等于和减去第一个变量(也就是 b = a - b),这样变量a也就等于a-b.
a = a + b;
b = a - b;
a = a - b;
3.异或法 : a = a ^ b;//^异或运算
b = a ^ b;//
a = a ^ b;
4.一行代码搞定法(推荐使用):int x = a + b
b = a
a = x - a
a?b:c :a成立输出b反之输出c 相当于if else
运算符优先级:赋值(=)<三目(?)<逻辑(& ^ | && ||)<关系(> <)<算数(+ - * /)<单目(!) 从左往右
随机数 :Math.random() [0.0-1.0]
switch(){
case * : ;break;
......
default: ;break;
}
switch 和 if 区别
表达式是等值判断的话 if,switch都可以
如果表达式是区间判断的情况 if最好
switch应用场合: 就是等值判断,等值的情况比较少的情况下
while(布尔表达式(true/false)){
循环体;
}
do{
循环体;
}while(布尔表达式);
while 和 do-while 的区别:
while: 先判断,再执行
do-while:先执行,再判断,至少被执行一次,从第二次开始才进行判断
do-while ,while,for 效率一样高 没有提高效率,只是减少工作量而已
break :停止最近的循环
break 标签 outer*: //定义标签位置
循环体
break outer*;//根据标签结束循环
continue :停止本次循环,继续下一次循环
结束本次离他最近的循环,继续下一次循环
continue 标签 outer*: //定义标签位置
循环体
continue outer*;//根据标签结束循环
return :遇到return结束当前正在执行的方法
作用:跟循环无关,就是程序中遇到return,那么return所在的那个方法就停止了
/*输出1-100中被5整除的数,每行输出6个*/
int count = 0; //引入一个计数器 初始值为0
for(int i=1;i<100;i++){
if (i%5==0){
System.out.print(i+"\t");
count++; //每在控制台输出一个数,count就+1
if (count%6==0){
System.out.println();//换行
}
}
}
int count=0;
boolean flag=true;//引入一个布尔类型的变量
Scanner sc =new Scanner(System.in);
for (int i=1;i<11;i++){
System.out.println("请录入第"+i+"个数");
int num = sc.nextInt();
if (num>0){
count++;
}
if (num==666){
flag=false;//当遇到666时候,系统被迫退出
break;
}
}
System.out.println("录入的正数有"+count+"个 系统退出状态是"+flag+"");
实心菱形
int size=10;
int startNum = size/2+1;
int endNum = size/2+1;
boolean flag = true;
for (int j=1;j<=size;j++) {
for (int i = 1; i <= size; i++) {
if (i >= startNum && i <= endNum) {
System.out.print("*");
} else {
System.out.print(" ");
}
}
System.out.println();
if (endNum==size){
flag=false;
}
if (flag){
startNum--;
endNum++;
}
else {
startNum++;
endNum--;
}
}
二重循环: 二元一次方程组的问题
三重循环: 三元一次方程组的问题(百钱买白鸡)
方法必须是先创建才可以使用,该过程称为方法定义
方法创建后并不是直接运行的,需要手动在代码中调用后才可以执行,该过程称为方法调用
方法的定义需要注意什么?
1)形参列表要怎么写:定义几个参数,分别是什么类型的。 不确定因素我们会当做方法的形参
2)方法到底是否需要返回值,如果需要的话,返回值的类型是什么
方法的调用需要注意什么?
1)实际参数要怎么传入:传入几个参数,传入什么类型的
2)方法是否有返回值需要接受
System.out.println(add(10,20));
System.out.println(add(12,13,14));
}
public static int add(int num1,int num2){
return num1+num2;
}
public static int add(int num1,int num2,int num3){
return num1+num2+num3;
方法的重载是指一个类中可以定义多个方法名相同,但参数不同的方法。
调用时,会根据不同的参数自动匹配对应的方法
注意本质:重载的方法,实际是完全不同的方法,只是名称相同而已
1.在同一个类中,方法名相同,形参列表不同的多个方法,构成了方法的重载。
2.方法的重载只跟,方法名和形参列表有关,与修饰符,返回值类型无关。
3.注意:形参列表不同指的是什么?
1)个数不同
2)顺序不同
3)类型不同
4.1)add(int a) 和 add(int b) -->不构成方法重载 相当于方法的重复定义
2) public static int add(int a) 和 public static void add(int b) -->不构成方法重载
int arr[];
arr = new int[4] //给数组开辟一个长度为4的空间
增强for循环
对数组arr进行遍历,遍历出来每个元素都用int类型的num接受
for(int num:arr){
//每次都将num在控制台输出
System.out.println(sum);
}
优点:代码简单
缺点:不能涉及索引相关的操作
数组初始化方式总共有三种 : 静态初始化 动态初始化 默认初始化
静态初始化: int arr[] = {1,2,3};
int arr[] =new int[]{1,2,3};
注意:
1.new int[3]{1,2,3}; -->错误
2.int arr[];
arr = {1,2,3}; --<错误
动态初始化: int arr[] = new int[3];
arr[0]=1;
arr[1]=2;
arr[2]=3;
默认初始化: int arr[] = new int[3]; -->数组有默认初始化值
求给定数组中最大的数
int i=0;
int arr[] = new int[]{1,2,3,6,4,8,9};
for ( i=0;i<6;i++){
if (arr[i]<arr[i+1]){
arr[i]=arr[i+1];
}
}
System.out.println(arr[i]);
数组出现重复数,返回其索引
int arr[] = {12, 34, 56, 7, 3, 56};
int index[] = new int[arr.length];
int j = 0;
for (int i = 0; i < arr.length; i++) {
if (3 == arr[i]) {
index[j] = i;
j++;
}
}
for (int i=0;i<j;i++) {
System.out.println(index[i]);
if (i == j - 1){
break;
}
}
数组添加
int arr[] = {12, 34, 56, 7, 3, 56};
System.out.println("增加前数组:");
for (int i=0;i<arr.length;i++){
if (i!=arr.length-1){
System.out.print(arr[i]+",");
}
else {
System.out.println(arr[i]);
}
}
System.out.println("增加后数组:");
int index = 2;
for(int i=arr.length-1;i>=index+1;i--){
arr[i] = arr[i-1];
}
arr[index] = 999;
for (int i=0;i<arr.length;i++){
if (i!=arr.length-1){
System.out.print(arr[i]+",");
}
else {
System.out.println(arr[i]);
}
}
数组删除
int arr[] = {12, 34, 56, 7, 3, 56};
System.out.println("删除前的数组"+Arrays.toString(arr));
int index =3;
for (int i = 0;i<=arr.length-1;i++)
if (index == arr[i] )
index=i;
for (int i =index ; i<=arr.length-2;i++){
arr[i] = arr[i+1];
}
arr[arr.length-1]=0;
System.out.println("删除后的数组"+Arrays.toString(arr));
main方法
public static void main(String[] args){
}
public static --->修饰符
void --->代表方法没有返回值 对应的类型void
main --->见名知意名字
String[] args --->形参 (不确定因素) 、
参数是String[],实参是new String[0] 虚拟机在调用main方法的时候,就是传入了一个长度为0的数组
可变参数: 作用提供了一个方法,参数的个数是可变的
解决了部分方法的重载问题
int...num
double...num
可变参数在jdk1.5之后加入的新特性
方法的内部对可变参数的处理跟数组是一样的
可变参数和其他数据一起作为形参的时候,可变参数一定要放在最后
Arrays
1.toString : 对数组进行遍历查看,返回的是一个字符串
System.out.println(Arrays.toString(arr));
2.binarySearch : 二分法查找:找出指定数组中的指定元素对应的索引:
Arrays.binarySearch(arr,4);
3.sort : 排序 ---> 升序
Arrays.sort(arr);
4.copyOf : 完成数组的复制;
Arrays.copyOf(arr,4):
5.copyOfRange : 区间复制
Arrays.copyOfRange(arr,1,4); //[1,4) -->1,2,3位置
6.equals : 比较两个数组的值是否一样 布尔类型值
Arrays.equals(arr1,arr2); //true/false
(arr1==arr2); false //==比较左右两侧的值是否相等,比较的是左右两侧的地址值
7.fill :数组的填充, 重载 区间填充
Arrays.fill(arr,10)
System
1.Arraycopy(object src,int srcPos,object dest,int destPos,int length)
参考:
src - 源数组
srcPos - 源数组中的起始位置
dest - 目标数组
destPos - 目标数组的起始位置
length - 要复制的数组元素的数量
System.arraycopy(arr1,1,arr2,2,3);
四种二维数组遍历方式
int arr[][] = new int[3][];
int a1[] = {1,2,3};
arr[0] = a1;
arr[1] = new int[]{1,2,3,4};
arr[2] = new int[]{5,6};
//方式1:外层普通for循环+内层普通for循环
/*for (int i=0;i<=2;i++){
for (int j=0;j<arr[i].length;j++){
System.out.println(arr[i][j]);
}
System.out.println();
}*/
//方式2:外层普通for循环+内层增强for循环
/*for (int i=0;i<arr.length;i++){
for (int num:arr[i]){
System.out.println(num);
}
System.out.println();
}*/
//方式3:外层增强for循环+内层增强for循环
/*for (int a[]:arr){
for (int num:a){
System.out.println(num);
}
System.out.println();
}*/
//方式4:外层增强for循环+内层普通for循环
for (int a[]:arr){
for (int i=0;i<a.length;i++){
System.out.println(a[i]);
}
System.out.println();
}
二维数组初始化
int arr[][] = new int[3][2];
//本质上:定义一维数组,长度为3,每个数组“格子”中,有一个默认的长度为2的数组
arr[1] = new int[]{1, 2, 3, 4};
for (int a[] : arr) {
for (int i = 0; i < a.length; i++) {
System.out.println(a[i]);
}
System.out.println();
}
setter getter方法 利用idea快捷键生成 :alt+insert
1.面向对象的思想:找参与者
2.体会了什么叫方法的形参,什么叫方法的实参
3.类和类可以产生关系
1)将一个类作为另一个类的形参
2)将一个类作为另一个类的属性
java中类与类之间的关系
一、继承关系
继承指的是一个类(称为子类、子接口)继承另外的一个类(称为父类、父接口)的功能, 并可以增加它自己的新功能的能力。
在Java中继承关系通过关键字extends明确标识,在设计时一般没有争议性。
二、实现关系
实现指的是一个class类实现interface接口(可以是多个)的功能,实现是类与接口之间最常见的关系。
在Java中此类关系通过关键字implements明确标识,在设计时一般没有争议性。
三、依赖关系
简单的理解,依赖就是一个类A使用到了另一个类B,而这种使用关系是具有偶然性的、临时性的、非常弱的,
但是类B的变化会影响到类A。比如某人要过河,需要借用一条船,此时人与船之间的关系就是依赖。
表现在代码层面,为类B作为参数被类A在某个method方法中使用
四、关联关系
关联体现的是两个类之间语义级别的一种强依赖关系,
五、聚合关系
聚合是关联关系的一种特例,它体现的是整体与部分的关系,即has-a的关系。此时整体与部分之间是可分离的,
它们可以具有各自的生命周期,部分可以属于多个整体对象,也可以为多个整体对象共享。
比如计算机与CPU、公司与员工的关系等,
六、组合关系
组合也是关联关系的一种特例,它体现的是一种contains-a的关系,这种关系比聚合更强,也称为强聚合。
它同样体现整体与部分间的关系,但此时整体与部分是不可分的,整体的生命周期结束也就意味着部分的生命周期结束,比如人和人的大脑。
表现在代码层面,和关联关系是一致的,只能从语义级别来区分。
先写父类,再写子类 -->继承
先写子类,再写父类 -->泛化
1.多态跟属性无关,多态指的是方法的多态,而不是属性的多态。
多态就是多种状态:同一个行为,不同的子类表现出来不同的形态。
多态指的就是同一个方法调用,然后由于对象不同会产生不同的行为。
2.多态的好处:
为了提高代码的扩展性,符合面向对象的设计原则:开闭原则。
开闭原则:指的是扩展是 开放的,修改是关闭的。
注意:多态可以提高扩展性,但是扩展性没有达到最好 -->(反射)
3.多态的要素:
1)继承关系
2)重写:子类对父类的方法进行重写
3)父类引用指向子类对象
编译期的类型 = 运行期的类型
多态非常常见的应用场合:父类当方法的形参,然后传入的是具体的子类的对象,
然后调用同一个方法,根据传入的子类的不同展现出来的效果也不同,构成了多态
父类向子类转型 --> 向下转型
Animal an = p ;
子类向父类转型 --> 向上转型
Pig pig = (Pig)an ;
不仅可以使用父类做方法的形参,还可以使用父类做方法的返回值类型,
真实返回的对象可以是该类的任意一个子类对象。
简单工厂设计模式的实现,它是解决大量对象创建问题的一个解决方案。
将创建和使用分开,工厂负责创建使用者直接调用即可。简单工厂模式的基本要求是
1.定义一个static方法,通过类名直接调用
2.返回值类型是父类类型,返回的可以是其任意子类类型
3.传入一个字符串类型的参数,工厂根据参数创建对应的子类产品
final:
1.修饰变量
final修饰一个变量,变量的值不可以改变,这个变量也变成了一个字符常量,约定俗称的规定:名字大小
1).final修饰基本数据类型 不可以修改值
2).final修饰引用数据类型,那么地址值就不可以改变 //对象的属性依然可以改变
2.修饰方法
1)final修饰方法,那么这个方法不可以被该类的子类重写
3.修饰类
1)final修饰类,代表没有子类,该类不可以被继承,
一旦一个类被final修饰,那么里面的方法也没有必要用final修饰了(final可以省略不写)
4.案例:JDK提供的Math类,看源码发现
1)使用Math类的时候无需导包,直接使用即可
2)Math类没有子类,不能被其他类继承了
3)里面的属性全部被final修饰,方法也是被final修饰,只是忽略不写了
原因:子类没有必要重写。
4)外界不可以创建对象
5)发现Math类中的所有的属性,方法都被static修饰
那么不用创建对象去调用,只能通过类名.属性名 类目.方法名去调用
抽象方法:
一个方法的方法体去掉,然后被abstract修饰,那么这个方法就变成了一个抽象方法
一个类中如果有方法是抽象方法,那么这个类也要变成一个抽象类
一个抽象类中可以有0-n个抽象方法
抽象类可以被其他类继承
一个类继承一个抽象类,那么这个类可以变成抽象类
一般子类不会加abstract修饰,一般会让子类重写父类中的抽象方法
子类继承抽象类,就必须重写全部的抽象方法
子类如果没有重写父类全部的抽象方法,那么子类也可以变成一个抽象类
抽象类不可以创建对象
可以创建子类对象
抽象类作用:
在抽象类中定义抽象方法,目的是为了子类提供一个通用的模板,子类可以在模板的基础上进行开发
,先重写父类的抽象方法,然后可以扩展子类自己的内容。
抽象类设计避免了子类设计的随意性,通过抽象类,子类的设计变得更加严格,进行某些程度上的限制。
使子类更加通用。
问:抽象类不能创建对象,那么抽象类中是否有构造器?
抽象类中一定有构造器。构造器作用:给子类初始化对象的时候要先super调用父类的构造器。
问:抽象类是否可以被final修饰?
不能被final修饰,因为抽象类设计的初衷就是给子类继承用的。
1.类是类,接口是接口,它们是同一层次的概念
2.接口中没有构造器
3.接口如何声明:interface
4.在JDK1.8之前,接口中只有两部分内容:
1)常量:固定修饰符:public static final
2)抽象方法:固定修饰符:public abstract
注意:修饰符可以省略不写,IDE会自动补全
5.类和接口的关系是什么? -->实现关系 (类实现接口)
6.一旦实现一个接口,那么实现类要重写接口中的全部抽象方法
7.如果没有全部重写抽象方法,那么这个类可以变成一个抽象类。
8.java只有单继承,java还有多实现
(一个类继承其他类,只能直接继承一个父类
但是实现类实现接口的话,可以实现多个接口)
9.写法:先继承再实现
10.接口不能创建对象
11.接口中常量如何访问?
问:接口的作用是什么?
定义规则,只是跟抽象类不同地方在哪? 它是接口不是类。
接口定义好规则之后,实现类负责即可。
继承:子类对父类的继承
实现:实现类对接口的实现
多态的应用场合:
1)父类当作方法的形参,传入具体的子类的对象
2)父类当作方法的返回值,返回的是具体的子类的对象
3)接口当作方法的形参,传入具体的子类的对象
4)接口当作方法的返回值,返回的是具体的实现类的对象
问:接口和抽象类的区别?
1.抽象类允许包含某些方法的实现,而接口是不允许的;
从设计级别看,为了实现由抽象类定义的类型,
一个类必须定义为一个抽象类的子类,这限制了它在类图中的层次,
但是接口没有这个层次的限制。
2.在抽象类中提供成员方法的实现细节,
该方法只能在接口中为 publicabstract修饰,也就是抽象方法。
3.抽象类中的成员变量可以实现多个权限 public private protected final等,
接口中只能用 public static final修饰。
扩充.抽象类是一个多个子类,是一个模板式的设计;
一个接口就是一个图形,是一个辐射型的设计。
在JDK1.8之前,接口中只有两部分内容:
1)常量:固定修饰符:public static final
2)抽象方法:固定修饰符:public abstract
在JDK1.8之后,新增非抽象方法:
1)被publi default修饰的非抽象方法:
注意1:default修饰符必须要加上,否则出错
注意2:实现类中要是想重写接口中的非抽象方法,那么default修饰符必须不能加,否则出错
2)静态方法:
注意1:static不可以省略不写
问:为什么要在接口中加入非抽象方法?
如果接口中只能定义抽象方法的话,那么我要是修改接口中的内容,那么对实现类的影响太大了所有实现类都会受到影响。
现在在接口中加入非抽象方法,对实现类没有影响,想调用就去调用.
1.类的组成:属性,方法,构造器,代码块(普通块,静态块,构造块,同步块),内部类
2.内部类:成员内部类(静态的和非静态的) 和 局部内部类(位置:方法内,块内,构造器内)
3.成员内部类:
里面属性,方法,构造器等
修饰符:private,default,protect,publi,final,abstract
4.内部类可以访问外部类的内容
5.静态内部类中之能访问外部类中被static修饰的内容
6.外部类想要访问内部类的东西,需要创建内部类的对象,然后进行调用
7.内部类和外部类属性重名的时候如何调用:
System.out.println(age);
System.out.println(this.age);
System.out.println(Test.this.age);
局部内部类
1.在局部内部类中访问的变量必须是final修饰的
2.如果类b在整个项目中只使用一次,那么就没有必要单独创建一个b类,使用内部类b就可以
3.匿名内部类
public>protected(其他package)>friendly(default)(子孙类和其他package)>private(同package,子孙类和其他package)