Java学习--Day6

Java学习–Day6

这是过年期间,零碎时间看的,所以是好几天的内容,基本JavaSE结束,有漏掉的,我再补充

Java方法详解(C++有接触,不多赘述)

可变参数

一个方法中只能指定一个可变参数,他必须是方法的最后一个参数,任何普通的参数必须在它之前声明。

public class Demo01 {
    public static void main(String[] args) {
        printMax(34,56,1,3,56,78,21,32);
        printMax(new double[]{1,2,3});
    }
    //可变参数,也叫不定项参数
    public static void printMax(double...numbers){
        if(numbers.length==0){
            System.out.println("No argument passed");
            return;
        }
        double result = numbers[0];
        //找最大
        for(int i = 1;i < numbers.length;i++){
            if(numbers[i] > result){
                result = numbers[i];
            }
        }
        System.out.println("The max value is" + result);
    }
}
//结果为
The max value is78.0
The max value is3.0

数组

//静态初始化:创建+赋值
int[] a={1,2,3,4,5,6};
//动态初始化:包含数值的默认初始化
int[] b= new int[10];
b[0]=10;

面向对象

三大特征

  1. 封装
  2. 继承
  3. 多态

方法回顾

  1. 静态方法加关键字,在另一个类中可以用 类名**.**方法名 来调用方法
  2. 非静态方法,在另一个类中调用该方法时只能先实例化类的对象,然后通过对象来调用方法。
  3. 在静态方法中不能调用非静态方法,因为静态方法是和类一起加载的,而非静态方法是类实例化之后才存在的。

创建与初始化对象

使用类关键字new创建对象

class student{
    //类中属性
    String s_name;
    int s_age;
    //类中方法
    public static void study(){
        System.out.println(this.name+"在学习");
    }
}
//创建学生类并初始化
Student xiaoming=new Student();
//初始化
xiaoming.s_name="小明";
xiaoming.s_age=12;
//此处若不初始化,则在用new关键字创建的时候,除了分配内存空间之外,还会给创建好的对象进行默认初始化,以及对类的构造器(下面细讲)的调用。

构造器

要求:

  1. 与类名相同,public修饰
  2. 无返回值

作用:

  1. 可以在new对象时,如果定义有参构造,一定要有无参构造(可以空着,但不能没有。)
  2. 可以用来初始化对象的值

快捷键:alt+insert添加构造器

class Person{
    String name;
    //无参构造器
    public Person(){
        
    }
    //有参构造器
    public Person(String name){
        
    }
}

封装

程序设计要求:高内聚,低耦合

class Student{
    //私有属性,不能通过 对象名.属性 来设置或获取属性值
    //而应该调用Get与Set方法获取或设置
    //快捷键:alt+insert
    /*
    *1.提高程序的安全性,保护数据
    *2.隐藏代码的实现细节
    *3.统一接口
    *4.系统可维护性增加了
    */
    private String name;
    private int id;
    private char sex;
    public Student(){

    }
    public Student(String name){

    }
    public void setName(String name) {
        this.name = name;
    }

    public void setId(int id) {
        this.id = id;
    }

    public void setSex(char sex) {
        this.sex = sex;
    }

    public String getName() {
        return name;
    }

    public int getId() {
        return id;
    }

    public char getSex() {
        return sex;
    }
}

继承

  1. 关键字extends
  2. Java中只有单继承,没有多继承,一个儿子只能有一个爸爸,但是一个爸爸可以有多个儿子。(在类中快捷键ctrl+h可查看继承的结构树)
  3. super关键字
package Base_Grammer;

//在java中,所有类都默认直接或间接继承Object类
public class Person {
    private int money=10_000_000;
    public void say(){
        System.out.println("yoyo~");
    }

    public int getMoney() {
        return money;
    }

    public void setMoney(int money) {
        this.money = money;
    }
    //super的用法
    protected String identity = "I am father";
    public void print(){
        System.out.println("Person");
    }
}


package Base_Grammer;

//子类继承父类,会继承父类所有public修饰的属性和方法
public class Student extends Person {
    private String identity="I am student";
    public void sayIdentity(String identity){
        System.out.println(identity);//I am student
        System.out.println(this.identity);//I am student
        //通过super来调用父类的属性,同时也可以用这种方法来调用父类的方法,但私有方法,super也不能调用
        System.out.println(super.identity);//I am father
    }
    public void print(){
        System.out.println("Student");
    }
    //用super调用父类方法
    public void test2(){
        print();//Student
        this.print();//Student
        super.print();//Person
    }
}
  1. 构造器的执行

此处父类必须要有无参的构造器(即使父类有有参构造器),如果没有子类的构造器会报错,这也就是为什么一个类一定要有无参构造器的原因。

package Base_Grammer;

//在java中,所有类都默认直接或间接继承Object类
public class Person {
    public Person() {
        System.out.println("Person的无参构造方法!");
    }
}

package Base_Grammer;

//子类继承父类,会继承父类所有public修饰的属性和方法
public class Student extends Person {
    public Student() {
        //这一行为隐藏代码:调用了父类的无参构造器
        super();//调用父类构造器,必须要在子类构造器的第一行
        System.out.println("Student的无参构造方法!");
    }
}


package Base_Grammer;

public class Test {
    public static void main(String[] args) {
        Student student = new Student();
        //此时newStudent类对象时会打印两行结果
        //Person的无参构造方法!
        //Student的无参构造方法!
    }
}
  1. 方法的重写

    有继承关系,子类重写父类的方法!

    先来看带static修饰的方法重写

    package Base_Grammer;
    
    //A继承B类
    public class A extends B {
        public static void test(){
            System.out.println("A=>test()");
        }
    
    }
    
    package Base_Grammer;
    
    public class B {
        public static void test(){
            System.out.println("B=>test()");
        }
    }
    
    
    package Base_Grammer;
    
    public class Test {
        public static void main(String[] args) {
            //现在看来方法的执行与定义的对象类型有关
            A a = new A();
            a.test();//A=>test()
            //父类的引用指向子类
            B b = new A();
            b.test();//B=>test()
        }
    }
    

    去掉static关键字,用ctrl+o的快捷键重写父类方法

    package Base_Grammer;
    
    public class A extends B {
        @Override//重写的功能注释
        public void test() {
            System.out.println("A=>test()");
        }
    }
    
    package Base_Grammer;
    
    public class B {
        public void test(){
            System.out.println("B=>test()");
        }
    }
    
    
    package Base_Grammer;
    
    public class Test {
        public static void main(String[] args) {
            A a = new A();
            a.test();//A=>test()
            //父类的引用指向子类
            B b = new A();//子类重写了父类方法
            b.test();//A=>test()
            //因此只有非静态方法才能被重写
        }
    }
    

总结

Java学习--Day6

多态

//举几个例子来说好了
//一个对象的实际类型是确定的
//如new Student(),new Person()...
//但可以指向的引用类型就不一定了,如父类的引用指向了子类
//1.子类可以调用自己独有的和继承父类的方法
Student student = new Student();
//2.父类的引用虽然可以指向子类,但父类只能调用自己的方法(调子类的方法也不是不行,类型强转一下),并且,一旦方法被从写,这样定义的父类引用会执行子类重写后的方法,见总结上边的例子
Person person = new Student();
Object object = new Student();

类型转换

关键字:instanceof

x instanceof y来表明x与y是否有继承关系
  1. 父类转子类是要强制转换
  2. 子类转父类,可能丢失自己的一些方法

static关键字详解

  1. 静态变量可以通过类名来访问

  2. 静态方法可以通过类名来执行

  3. 静态方法只可以调用静态方法

  4. 静态代码块:类加载执行一次,且只执行一次,可以用来赋初始值

    static{
        //静态代码块
    }
    
  5. 静态导入包

    import static java.lang.Math.random;
    //这样可以直接用random()函数,不用加Math. 但一般没有这么做的
    

抽象类

关键字:abstract

package Base_Grammer;
//1.抽象类不能new,要考子类去实现它
//2.抽象类中可以有普通方法,但是抽象方法只能在抽象类中
//3.缺点就是,类只能单继承,一个儿子只能有一个爸爸,但接口可以多继承
public abstract class Action {
    //抽象类中的抽象方法,只有方法名字,没有方法的实现
    public abstract void run();
}

package Base_Grammer;

public class A extends Action {
    //子类必须要重写父类抽象方法
    @Override
    public void run() {

    }
}

【思考】抽象类含有构造器吗?

​ 答:抽象类可以有构造方法,只是不能直接创建抽象类的实例对象而已。在继承了抽象类的子类中通过super()或super(参数列表)调用抽象类中的构造方法。

接口

关键字:interface,implements

  1. 实现了接口的类必须实现接口中的方法
  2. 接口中的方法默认是 public abstract的
  3. 接口中的常量是public static final类型的,但我们一般不定义常量
  4. 接口可以多继承:implements关键字

内部类

  1. 成员内部类

    package Base_Grammer;
    
    public class Outer {
        private int id;
        public void out(){
            System.out.println("这是外部类的方法");
        }
        public class Inner{
            public void in(){
                System.out.println("这是内部类的方法");
            }
            //内部类还可以获得外部类的私有属性
            public void getID(){
                System.out.println(id);
            }
        }
    }
    
    
    package Base_Grammer;
    
    public class Test {
        public static void main(String[] args) {
            Outer outer = new Outer();
            //通过这个外部类来实例化内部类
            Outer.Inner inner = outer.new Inner();
            inner.in();
            inner.getID();
    
        }
    }
    
    
  2. 静态内部类

    将上边的Inner类加上static修饰,这样会导致内部类无法获得外部类的私有属性

    package Base_Grammer;
    
    public class Outer {
        private int id;
        public void out(){
            System.out.println("这是外部类的方法");
        }
        public static class Inner{
            public void in(){
                System.out.println("这是内部类的方法");
            }
            //内部类还可以获得外部类的私有属性
            public void getID(){
                System.out.println(id);//这里会报错滴
            }
        }
    }
    
    
  3. 局部内部类

    package Base_Grammer;
    
    public class Outer {
        //局部内部类
        public void method(){
            class inner{
                public void in(){
    
                }
            }
        }
    }
    
  4. 匿名内部类

    package Base_Grammer;
    
    public class Test {
        public static void main(String[] args) {
            //没有名字的初始化类,不用将实例保存到变量中
            new Apple().eat();
            new Userservice(){
    
                @Override
                public void hello() {
                    
                }
            };
        }
    }
    class Apple{
        public void eat(){
            System.out.println("eat");
        }
    }
    interface Userservice{
        void hello();
    }
    

异常机制

Java分为两类,错误Error和异常Exception,异常可以抛出处理

快捷键:选中要抛出异常的部分,然后ctrl+alt+t

1.try,catch,finally

package Base_Grammer;

public class Test {
    public static void main(String[] args) {
       int a = 1;
       int b =0;
       try {//try监控区域
           System.out.println(a/b);
       }catch (ArithmeticException e){//catch捕获异常,参数为想要捕获的异常类型
           System.out.println("变量b不能为零");
       }finally {//处理善后工作
           System.out.println("finally");
       }
       //finally可以不要,但一般要写,比如关闭一些资源流的时候,如I/O流
        //假设要捕获多个异常,一定要从小到大捕获,不然会报错
        try{
            System.out.println(a/b);
        }catch (Error e){
            System.out.println("error");
        }catch (Exception e){
            System.out.println("exception");
        }catch(Throwable t){
            System.out.println("throwable");
        }finally {//处理善后工作
            System.out.println("finally");
        }
    }
}

2.throw,throws

package Base_Grammer;

public class Test {
    public static void main(String[] args) {
        try {
            new Test().test(1,0);
        } catch (ArithmeticException e) {
            e.printStackTrace();//这里是打印错误栈信息
        }
    }
    //假设这方法中,处理不了这个异常,方法上抛出异常
    public void test(int a,int b) throws ArithmeticException {
        if (b == 0) {
            //知道这里必定出错,主动抛出异常,一帮在方法中使用
            throw new ArithmeticException();
        }
        System.out.println(a / b);
    }
}

3.自定义异常

只要继承Exception类就行

package Base_Grammer;

public class MyException extends Exception {
    //假设数字大于10就产生异常
    private int detail;
    public MyException(int a){
        this.detail = a;
    }
    //为打印信息,添加个toString方法

    @Override
    public String toString() {
        return "MyException{" +
                "detail" + detail +
                '}';
    }
}


package Base_Grammer;

public class Test {
  static void test(int a) throws MyException {
      System.out.println("传递的参数为:"+a);
      if(a>10){
          throw new MyException(a);//抛出
      }
      System.out.println("ok");
  }

    public static void main(String[] args) {
        try {
            test(11);
        } catch (MyException e) {
            //这里还可以增加一些处理异常的代码块
            System.out.println("MyException===>"+e);
        }
    }
}

上一篇:Java学习笔记Day6 面向对象(一)


下一篇:day6 - 抽象类,接口,内部类