12月6日

 

排序方法

冒泡排序,总共有八大排序

 package array;
 
 import java.util.Arrays;
 
 public class Demo4 {
     public static void main(String[] args) {
         int[]a={5,9,78,8977,7,8,89,13};
         int[]sort=sort(a);
         System.out.println(Arrays.toString(sort));
    }
     //冒泡排序:比较数组中,两个相邻的元素,如果第一个数比第二个数大,我们就交换他们的位置
     //每一次比较,都会产生一个最大或者最小的数字
     //下一轮则可以少一次循环
     //一次循环,知道结束
     public static int[] sort(int[] array) {
         //外层循环,判断要走多少次;
         for (int i = 0; i < array.length-1; i++) {
             //内层循环,比较判断两个数,如果前一个比后一个大,就交换位置
             for (int j = 0; j <array.length-i-1 ; j++) {
                 if (array[j+1]<array[j]){
                     int temp=0;
                     temp=array[j];
                     array[j]=array[j+1];
                     array[j+1]=temp;
                }
            }
        }
         return array;
    }
 }
 

 

稀疏数组

是一种数据结构

image-20201206142030320

遍历二维数组:

用for,each循环

  for (int[] ints : array1) {
             for (int anInt : ints) {
                 System.out.print(anInt+"\t");
            }
             System.out.println();
        }

增强for循环,打array1.for和ints.for就有

把二维数组的每个数组元素先给数组ints,再遍历ints里的每个数

  int count=0;
         for (int i = 0; i < array1.length; i++) {
             for (int j = 0; j <array1[i].length ; j++) {
                 if(array1[i][j]!=0) {
                     count++;
                     array2[count][0] = i;
                     array2[count][1] = j;
                     array2[count][2] = array1[i][j];
                }
            }
        }

在遍历二维数组时,注意如果要对每个元素进行判断,就不能用增强型for循环,而是老老实实写两层,外层循环是以二维数组的长度为循环次数,内层则以每个元素数组的个数为循环次数。

 

面向对象(00P)

初识面向对象

image-20201206150505866

image-20201206150834793

正确的写法应该是:以类的方式组织代码,以对象的形式封装数据

方法回顾与加深

image-20201206151626515

方法的调用

如果在A类调用B类中的方法,就需要判断B类的这个方法是不是静态方法,即声明时有没有stati修饰,如果有

则可以直接B.fangfa这种形式来调用

如果没有,则需要实例化这个类再调用,即设计new

对象类型 对象名 =对象值(new 对象类型)

然后再通过对象名.方法来调用

同一个类的方法互相调用

 public class Demo1{
     public static void main(String[] args){}
     public static void a(){
         b()
    }
     public  void b(){
        ...
    }
 }

这种是错的,ab都是非静态或者都是静态是可以的,但是a静态,b非静态,a调用b方法不行

解释:static方法是和类一起加载的,而非静态方法是必须等类实例化(new一个)之后才存在,所以时间顺序出错无法调用。

比较静态方法和非静态方法的区别

 public class Demo1 {
     public static void main(String[] args) {
         int add = Demo1.add(1, 2);
         System.out.println(add);
    }
     public static int add(int a,int b){
         return a+b;
    }
 }

静态的不需要实例化,即不不用new一个对象,直接通过类名.方法调用即可

 public class Demo1 {
     public static void main(String[] args) {
         Demo1 demo1=new Demo1();
         int add = demo1.add(1, 2);
         System.out.println(add);
    }
     public int add(int a,int b){
         return a+b;
    }
 }

非静态的要先new一个对象,通过这个对象.方法名来调用。

值传递和引用传递

之前说的java一定是值传递

值传递

 public class Demo2 {
     public static void main(String[] args) {
         int a=1;
         Demo2.change(a);
         System.out.println(a);
    }
     public static int change(int a){
         return a=10;
    }
 }

引用传递

 public class Demp3 {
     public static void main(String[] args) {
         Person person=new Person();
         System.out.println(person.name);
         Demp3.change(person);
         System.out.println(person.name);
    }
     public static void change(Person person){
         person.name="xyj";
    }
 }
 class Person{
     String name;  //没赋值时应该为null
 }

这里小注意:只能有一个public类,但可以定义其他的非public类,注意一定要放在public类的外面定义

注意这里的区别,第一个经过change方法后并没有改变a的大小,输出的仍然是1

第二个经过change后person的属性name确实改变了,这个后面才能解释(面向对象和内存)

对象的创建分析

类与对象的关系

image-20201206155651254

对象实例化就是用的new

image-20201206161209093

先输入new student后,还是一样的alt加回车,自动创建一个student对象

image-20201206161150292

student对象就是一个Student类的具体实例。

image-20201206161345559

 

构造器

image-20201206162917671

一个类即使什么都不写,它也会存在一个方法,打开class文件可以看到显示的就是定义构造器

具体举例

public class Student {
}

我先构造一个空的类,什么方法属性都不写;

public class Test {
    public static void main(String[] args) {
        Student student = new Student();
    }
}

然后我在main方法里创建Student实例,发现程序并没有问题。

回头看Student的class文件

public class Student {
    public Student() {
    }
}

会发现编译时自动创建了一个public Student()

这个就称作构造方法/构造器

就像前面说的构造方法必须和类的名字相同,必须没有返回值,也没有void

这里叫做无参构造

注意无参构造可以用于创建实例时初始化值,因为一旦创建实例,就必须走一遍构造器

public class Student {
    String name;
    public Student(){
        this.name="yj";
    }
}

这里这个this指代的就是这个对象。所以对象一创建name默认是yj。


但是还有有参构造,这里一定注意,没有有参构造时,无参构造也可以不写,因为系统编译时会默认生成一个无参构造器,但是

一旦有了有参构造,系统就不会生成无参构造器了,就必须自己手动写(显示定义),如果一个类只有有参构造就会报错。

public class Student {
    String name;
    public Student(String name){
        this.name=name;
    }
}

这里注意this.name指代的是对象的name,而后面的name指形参,也就是传进来的参数。(this.表示当前类的)

public class Student {
    String name;
    public Student{
    }
    public Student(String name){
        this.name=name;
    }
}

应该这样写,无参构造器空着,然后在实例化对象时

Student student = new Student("yj");

就会根据你给的参数跳到有参构造器,这也就是方法的重载!

总结

image-20201206184159341

面向对象的三大特性

封装

image-20201206184358854

继承

extends关键字

image-20201206185622403

写了三个代码:

package extend.demo1;
import extend.demo2.Person;
import extend.demo3.Student;

public class Application {
public static void main(String[] args) {
Student student = new Student();
student.print();
student.test1();
}
}

 

package extend.demo3;

import extend.demo2.Person;

public class Student extends Person {
public Student() {
System.out.println("Student无参执行了");
}
private String name = "yj";
public void print(){
System.out.println("student");
}
public void test1(){
print();
this.print();
super.print();
}
public void test(String name){
System.out.println(name);
System.out.println(this.name);
System.out.println(super.name);
}
}

这里test方法调用时就会发现,如果先输出的是给形参的name,再输出student的name,最后输出父类的

注意,所有private的东西都是无法继承的

package extend.demo2;

public class Person {
public Person() {
System.out.println("Person无参执行了");
}
public void print(){
System.out.println("Person");
}
}

其中Person是Student的父类。

可以发现我们用super来调用父类的同名的方法,子类的加this或者不加都是直接调用子类的

重要:子类和父类的无参构造器同时有语句要执行时,会发现先执行了父类的无参构造器

这里其实在子类的无参构造器中还省略了一句super()用来调用父类的构造器;

如果手动写出来且放在无参构造器中语句的下面还会报错,说明确实super()要先执行(所以才会先执行父类的无参构造器)

super()必须在子类构造器的第一行

super详解

super()这个方法的作用是在子类中调用父类的无参构造器,且必须放在子类的构造器的第一行

对比一下this()这个方法,这个可以调用子类自己的有参构造器

public Student() {
    this("yj");
    System.out.println(this.name);
}
public Student(String name) {
    super("name");
    System.out.println("Student无参执行了");
}

像这里一个无参构造,一个有参构造,可以在无参构造中通过this("yj");就是通过给this()一个参数来调用相应的有参构造

这里有个问题,也就是this()也必须在第一行,与super()起冲突,所以构造器中this()与super()只能用一个。

还要注意:super()是默认调用的,即使不写也会调用的。但如果用this()来调用自己的有参构造器,这里默认调用的super()就不再调用了。举例子

子类:

public class Student extends Person {
    public Student() {
        this("yj");
        System.out.println(this.name);
        System.out.println("Student无参执行了");
    }
    public Student(String name) {
        super("name");
        System.out.println("Student有参执行了");
    }

父类:

public Person() {
    System.out.println("Person无参执行了");
}
public Person(String name) {
    System.out.println("Person有参执行了");
}

main方法中我以无参的形式实例化一个Student对象

Student student = new Student();

则得到的结果为

image-20201206203657709

 

具体顺序为:无参,先调用student的无参构造器,然后由于this(“yj”)命令,不再执行super(),即不再调用父类的无参

先调用自己的有参,自己的有参第一行是super("name");调用父类的有参,故第一个输出Person有参执行了

再输出Student有参执行了,最后再把student的无参剩下的给走完。

同理,我把this(“yj”)删掉,则得到:

image-20201206204025828

这样的结果,虽然没有写super(),但它还是默认先调用父类的无参构造器。

最后补充一点,如果父类只有有参构造,没写无参构造,这按照前面的说法应该是错误的。

此时子类的无参写不写都会出错(本身父类就没无参)

但是如果在子类的无参中调用了父类的有参

即super(“yj”);

这样的话子类是不会报错,能成功创建对象且先调用父类的有参再执行自身的无参

当然,父类没有无参的话是无法创建父类对象的,只是父类的有参被子类的无参调用了就不会影响子类的使用。

总结

image-20201206204734546

抽象类和接口

内部类及OOP实战

小技巧

demo1.add(1, 2);
int add = demo1.add(1, 2);

输完第一行后按alt加回车,可以自动把这个值给一个自动创建的变量。

image-20201206160529128

点这个可以把代码页放右边进行对比

一个项目只能有一个main方法,一般放在一个叫Application的类中

其余的每个类中去定义要用的类,注意类只能有一个public类。

如何把class文件添加到目录下

先点击项目结构

image-20201206162415114

添加根目录,把out目录添加进来即可。

image-20201206162559999

alt加Insert,自动生成构造器

image-20201206165945146

选择Constructor构造器

image-20201206170013877

选择就是有参构造器,Select None就是无参构造器

还可以直接生成get和set方法

posted @ 2020-12-06 20:54  YJ菌  阅读(144)  评论(0)    收藏  举报