Java基础-04

面向对象

本质:以类的方式组织代码,以对象的组织(封装)数据

  • 三大特性
    • 封装
    • 继承
    • 多态
	//main方法
	public static void main(String[] args) {
		Student.say();
//		Student.play();
//		报错信息Cannot make a static reference to 
//		the non-static method play() from the type Student
		//非静态方法需要实例化这个类
		Student student = new Student();
		student.play();
	}
	
	public void readFile(String file) throws IOException{
		return;	
	}
	
	//和类一起加在的
	public static void a() {
		/*
		 * b();   报错
		 * Cannot make a static reference 
		 * to the non-static method b() from the type Demo01
		 */

	}
	
	//类实例化之后才存在的
	public void b() {
		
	}
public class Student {
	public static void main(String[] args) {
		
	}
	
	//静态方法 static
	public static void say() {
		System.out.print("学生说话了");
	}

	//非静态方法
	public void play() {
		System.out.print("学生在打游戏");
	}

}
public class Demo02 {
	public static void main(String[] args) {
	    //值传递
		int a = 1;
		System.out.println(a);//1
		Demo02.change(a);
		System.out.println(a);//1
		
		
		//引用传递:对象,本质还是值传递
		Person person = new Person();
		System.out.println(person.name);//null
		Demo02.change(person);
		System.out.println(person.name);//我叫袁小陌	
	}

	
	public static void change(int a) {
		a = 10;
	}
	
	public static void change(Person person) {
		//person是一个对象
		person.name = "我叫袁小陌";
	}
}

class Person{
	String name;
}

构造器

构造器也称构造方法,是在进行创建对象的时候必须要调用的

  • 特点
    • 必须和类的名字相同
    • 必须没有返回类型,也不能写void
//属性 字段
String name;

//使用new 本质上是调用构造器
//用来初始化值
public Person() {
	this.name = "我叫袁小陌";
}

//有参构造:一旦定义了有参构造,无参必须显示定义 
public Person(String name) {
	this.name = name;
}

//IDEA的快捷键 alt+insert



public class Application {
	public static void main(String[] args) {
		//类是抽象的 ,需要实例化
		//类实例化后会返回一个自己的对象
//		Student xiaoming  = new Student();
//		Student xiaohong  = new Student();
//		System.out.println(xiaoming.name);//null
//		
//		xiaoming.name = "小明";
//		System.out.println(xiaoming.name);//小明
	
		Person person = new Person();
		System.out.println(person.name);//我叫袁小陌
		
		Person person1 = new Person("张三");
		System.out.println(person1.name);//张三
	}

}

封装

private 属性私有(IDEA的alt+insert可以快速插入get/set方法)

	//属性私有  private
	//名字
	private String name;
	//学号
	private int id;
	//性别
	private String sex;
	//年龄
    private int age;
	
	//提供一些可以操作这些属性的方法,提供一些public的get、set方法
	public String getName() {
		return this.name;
	}
	
	public void setName(String name) {
		this.name = name;
	}
	
	public int getAge() {
		return this.age;
	}
	
	public void setAge(int age) {
		if (age>=120 || age<0) {
			this.age = 3;
		}else {
			this.age = age;
		}
	}

继承

关键字 extends / super

  • super注意点
    • super调用父类的构造方法,必须是构造方法的第一个
    • super必须只能出现在子类的方法或者构造方法中
    • super和this不能同时调用构造方法

Vs this

  • 代表的对象不同:
    • this 本身调用者的这个对象
    • super 代表父类对象的应用
  • 前提:
    • this 没有继承也可使用
    • super 只能在继承下面使用
  • 前提:
    • this(); 本类的构造
    • super(); 父类的构造
//java中所有的类都默认继承object类

public class Person {
	//public
	//protected
	//default
	//private 私有的公司无法被继承
	
	
	
	protected String name = "小陌-父类";
	
	public Person() {
		System.out.println("Person无参构造器执行");
	}


	public int money = 10_000_000;
	
  //Eclipse 快捷键 alt + shift +s 
  // Eclipse 查看继承树 ctrl+T  IDEA:ctrl+H
	public int getMoney() {
		return money;
	}

	public void setMoney(int money) {
		this.money = money;
	}


	public void Say() {
		System.out.println("老师说了一句话");
	}
}



public class Student extends Person {
	public Student() {
		super();//会默认调用
		System.out.println("Student无参构造器执行");
	}
	
	protected String name = "小陌-学生";
	public void test(String name) {
		System.out.println(name);
		System.out.println(this.name);
		System.out.println(super.name);
		
	}
}


public class Application {
	public static void  main(String[] args) {
		Student stu = new Student();
//		Person无参构造器执行
//		Student无参构造器执行

		
//		stu.Say();
//		stu.test("胡歌");
		
	}

}

重写

需要有继承关系:子类重写父类的方法

  • 方法名必须相同
  • 参数列表必须相同
  • 修饰符:范围可以扩大 public > protected > default > private
  • 抛出的异常:范围可以被缩小,但是不能被放大ClassNotFoundException --> Exception(大)
  • 子类和方法和父类必须要一致,方法体不同
    //静态方法和非静态方法区别很大
    //静态方法  //方法的调用只和左边,定义的数据类型有关
    //非静态方法 重写
    public static void main(String[] args) {

        A a = new A();
        a.test();//A>>test()

        //父类的引用指向了子类
        B b = new A();//   子类重写了父类的方法
        b.test();//B>>test() 重写后变成 A>>test()
    }


public class A extends B{
//    public static void test(){
//        System.out.println("A>>test()");
//    }

//        public void test(){
//        System.out.println("A>>test()");
//        }

    @Override //注解:有功能的注释
    public void test() {
//        super.test();
        System.out.println("A>>test()");
    }
}


public class B {

//    public static void test(){
//        System.out.println("B>>test()");
//    }

        public void test(){
        System.out.println("B>>test()");
    }
}

多态

  1. 多态是方法的多态
  2. 父类和子类,有联系 类型转化异常ClassCastException
  3. 存在条件 继承关系,方法需要重写,父类的引用指向子类对象Father f1 = new Son();
    • static 方法 属于类 他不属于实例
    • final 常量
    • private方法私有无法重写
public class Person {
    public void run(){
        System.out.println("run");
    }
}

public class Student extends Person{

    @Override
    public void run() {
        System.out.println("son");
    }

    public void eat(){
        System.out.println("eat");
    }
}

        //一个对象的实际类型是确定的
       //new Person();

        //可以指向的引用类型就不确定了
        //Student类型能调用的方法都是自己的或者继承父类的
        Student s1 = new Student();
        //Person父类型 可以指向子类,但是不能调用子类独有的方法
        //类型之间的转换 父    子
        //高             低
        Person s2 = new Student();
        Object s3 = new Student();
        Person s4 = new Person();

        //对象能执行哪些方法,主要看左边有哪些类型和右边关系不搭
        s1.run();//son
        s1.eat();//eat
        s2.run();//son
        s4.run();//run
//        s2.eat();//报错 Cannot resolve method 'eat' in 'Person'
        //s2 将这个对象转换为Student类型 我们就可以使用Student类型的方法
        ((Student)s2).eat();//强制转换  eat

类型转换

  • 父类的引用转向子类的对象
  • 把子类转换为父类,向上转型
  • 把父类转换为子类,向下转型:强制转换
  • 方便方法的调用,减少重复的代码

static关键字

package oop.Demo07;
//静态导入包
import static java.lang.Math.random;

public class Student {
    private static int age;//静态变量
    private double score;//非静态变量
    {
        //代码块 匿名代码块 常用来赋初始值
        System.out.println("anonymous Code");
         }
         static {
        //静态代码块  类加载直接执行 永久只加载一次
             System.out.println("Static Code");
         }

         public Student(){
             System.out.println("constructor Code");
         }
    public static void main(String[] args) {
        Student s1 = new Student();
//        System.out.println(Student.age);
//        System.out.println(s1.score);
//        System.out.println(s1.age);
    }

}
/*
执行顺序
Static Code  静态代码块
anonymous Code  匿名代码块
constructor Code 构造方法
 */

抽象类

//abstract 抽象类
public abstract class Action {
    //约束别人帮我们实现
    //abstract 抽象方法 只有方法名字 没有方法的实现
    public abstract void doSomething();

    //抽象类不能被new 只能靠子类去实现他
    //抽象类中可以写普通方法
    //抽象方法必须在抽象类中
    public static void main(String[] args) {
//        new Action();// 'Action' is abstract; cannot be instantiated
    }
}


//抽象类的所有方法 继承了它的子类 都必须要实现他的方法
public class A extends Action{
    @Override
    public void doSomething() {
    }
}

接口

  • 作用
    • 约束
    • 定义一些方法,让不同的人实现
    • 方法都是public abstract
    • 常量都是public static final
    • 接口不能实例化 没有构造方法
    • implements是可以实现多个接口
    • 必须重写接口中的方法
public interface UserService {

    //常量 public static final
     int age = 99;
//接口中的所有定义其实都是抽象的 public abstract
    void add(String name);
    void delete(String name);
    void update(String name);
    void query(String name);
}

public interface TimerService {
    void timer();
}

//类可以实现接口 implements 接口
//实现了接口的类 必须要重写接口中的方法
public class UserServiceImpl implements UserService,TimerService {
    @Override
    public void add(String name) {}

    @Override
    public void delete(String name) {}

    @Override
    public void update(String name) {}

    @Override
    public void query(String name) {}

    @Override
    public void timer() {}
}

内部类

public class Outer {

    private int id=10;
    public void out(){
        System.out.println("out");
        //局部内部类
        class Inner2{

        }
    }

    public class Inner{
        public void in(){
            System.out.println("in");
        }

        public void getId(){
            System.out.println(id);
        }
    }

    public static void main(String[] args) {
        //没有初始化类 不用将实例保存到变量中
        new A().eat();
        UserService userService = new UserService(){
            @Override
            public void hello() {

            }
        };

    }
}
//一个java类中可以有多个class类,但是只能有一个public class
class A{
    public  void eat(){
        System.out.println("1");
    }

}

interface UserService{
    void hello();
}


public class Application {
    public static void main(String[] args) {
        Outer outer = new Outer();

        //通过外部内实例化内部类
        Outer.Inner inner = outer.new Inner();
        inner.in();
        inner.getId();
    }

}

异常

  • RuntimeException
    • ArrayIndexOutOfBoundsException
    • NullPointerException
    • ArithmeticException
    • MissingResourceException
    • ClassNotFoundException

处理机制

关键字 try catch finally throw throws

  public static void main(String[] args) {
        int a = 1;
        int b = 0;
        //.ArithmeticException: / by zero
//        System.out.println(a/b);

        try {
            new Demo01().test(a,b);
        } catch (ArithmeticException e) {
            e.printStackTrace();
        }


//如果要捕获多个异常:要从小到大
        //快捷键 Ctrl+Alt+T
        try {
            System.out.println(a/b);
        }catch (ArithmeticException e){ //想要捕获的异常类型;
            System.out.println("除数不能为0");
            e.printStackTrace();//打印错误的栈信息
        }finally{
            System.out.println("finally");
        }

    }
    //假设在这个方法中处理不了这个异常,方法上抛出这个异常
    public void test(int a,int b) throws ArithmeticException{
        if (b==0){
            throw new ArithmeticException();//主动抛出异常 一般在方法中使用
        }
    }

自定义异常

  1. 创建自定义异常类(继承Exception)
  2. 在方法中通过throw关键字抛出异常对象
  3. 如果在当前抛出异常的方法中处理异常,可以使用try-catch语句捕获并处理;否则在方法中声明处通过throws关键字指明要抛出给方法调用者的异常,继续执行下一步操作
  4. 在出现异常方法的调用者中捕获并处理异常
	//自定义异常类
public class Demo02 extends Exception{
    //传递数字>10
    private int detail;
    public Demo02(int a){
        this.detail = a;
    }
//异常的打印信息
    @Override
    public String toString() {
        return "Demo02{" +
                "detail=" + detail +
                '}';
    }
}


   static void test1(int a) throws Demo02 {
        System.out.println("传递的参数为"+a);
        if (a>10){
            throw new Demo02(a);
        }
    }

    public static void main(String[] args) {
        try {
            test1(11);
        } catch (Demo02 e) {
            System.out.println("MyException>>"+e);
        }
    }

总结

  • 处理运行时异常的时候,采用逻辑去合理规避同时辅助try-catch处理
  • 在多重catch块后面,可以加上一个catch(Exception)来处理可能会遗漏的异常
  • 对不确定的代码,切忌只是简单的调用printStackTrace()去打印
  • 具体如何处理异常,要根据不同的业务需求和异常类型去决定
  • 尽量添加finally语句块去释放占用的资源
posted @ 2021-07-01 23:38  我叫袁小陌  阅读(57)  评论(0)    收藏  举报