JavaSE基础05(方法,重载,调用,类和对象,构造器,封装,继承,方法重写,抽象类,接口,异常)
- 面向对象
- 以类的方式组织代码,以对象的组织封装数据;
- 一个Java文件只能有一个public类,必须和文件名一样;
- java文件里也可以没有public类;
- java为了实现万物皆对象的理念,提供了基本数据类型的封装类型;
- 基本数据类型封装类型包括:Byte Short Integer Long Float Double Boolean Character ;
- 方法的定义
方法的使用,修饰符 返回值类型 方法名(参数类型 参数名){ 方法体 return 返回值};参数类型包括: 基本数据类型和引用数据类型(String和创建的所有的类)- return 终止方法
- 当方法返回一个值的时候,方法调用通常被当作一个值,例如:int larger=max(30,40);
- 如果方法返回值是void,方法调用一定是一条语句。例如: System.out.println("hello");
- return 一个方法只能返回一个对象或一个值;
- 执行return 这个方法就结束了,return后面的代码不会执行;
- 没有static 的方法需要创建类对象,通过对象名.方法名调用;
- 如果返回值类型是void的话,不需要return返回值,其他的需要返回一个该类型的数据;
- 可变参数
- 使用方法:在方法声明中,在指定参数类型后加一个省略号(int... 变量名) 指参数个数可变,类型不可变;
- 一个方法中能指定一个可变参数,它必须是方法的最后一个参数,任何一个普通参数都必须在它之前声明;
- 递归
- 递归就是用A方法调用A方法;
- 递归结构包括两个部分:递归头:什么时候不调用自身方法,如果没有头将陷入死循环;递归体:什么时候需要调用自身方法。
- 方法的调用
静态方法static方法调用,跨类调用类名.方法名()。- static修饰的属性和方法可以直接使用类名调用,否则要创建对象调用;static 修饰的方法,可以通过对象调用,但是还是通过静态方式访问的;
-
对象的 没有使用static修饰的,必须由对象调用;
类的 使用static定义的属性和方法就是类的,也叫做静态的; -
先获取对象的类,然后调用静态的方法;
- 非静态类,跨类调用时要先实例化
public static void main(String[] args) {
//调用非静态student类里面的say方法 Student student =new Student(); student.say(); } -
静态类是和类一起加载的,非静态类是实例化之后才存在的;
-
类和对象
-
类中只有属性和方法;
- this可以调用本类的的属性;
- 类是抽象的需要实例化,类实例化之后会返回一个自己的对象,这个对象就是这个类的具体实例;
Student xh = new Student(); xh.name = "小明"; System.out.println(xh.name);
- 构造器
必须和类名相同;- 没有返回类型也不能写void;
- 每个类都会有一个无参构造方法;
- 使用new关键字,本质是在调用构造器;(作用)
- 本身用来初始化值;(作用)
- 一旦定义了有参构造,就必须显示无参(一旦自己写了有参构造,Java就不会赠送无参构造了,如果父类没有无参构造会影响子类);
- 所有子类构造方法中首行默认父类的无参构造方法,如果父类的无参构造方法消失,需要明文确定调用父类的哪个构造方法;
public Son(String name) {//父类没有无参构造,有有参构造的话,子类中的明文声明调用的父类的哪个方法 super(name);
- 编写构造器的快捷方法,鼠标右击选generate---Constructor
public Student() {//无参构造 } public Student(String name) {//有参构造 this.name = name; }
- 静态代码块
-
---父类静态代码块------- -----子类静态代码----- -----父类块---------- ------父类构造方法------ -----子类块------ -----子类构造方法------
-
先运行静态 (现有类的再有对象的);
-
实例化对象后先运行代码块再运行构造方法;
- 先运行静态代码块(先父类再子类)--->然后成员代码块(先父类再子类)--->最后构造方法(先父类再子类),在子类的无参构造第一行有super(),会再次调用父类的成员代码和构造方法;
- 封装
属性私有- 访问权限修饰符 public 公共的 谁都可以访问; protected 受保护的(家族性的) 子类和本包下的都能访问 ; default 默认的(本包下的) 不写默认default ; private 私有的(自身类中)
- get,set方法可以快捷生成鼠标右击选generate---getter and setter;
- get方法是获取属性,set方法给这个属性赋值;
- 调用方法,在main主方法中初始化一个实例,构建出一个新对象,对象.set属性名();
Student student = new Student(); student.setName("小苗");//set赋值 需要有传参,不需要返回值 System.out.println(student.getName());//get调用 不需要有传参,需要返回值
- 继承
java类中只有单继承,没有多继承;- ctrl+H可以看到继承树;
- 继承作用: 减少代码量,规范了子类的行为, 简化代码的开发;子类可以对父类进行拓展;
- 对于父类和子类中重名的属性,用this和super来分辨;
- super调用的是父类的,this调用的是本类的,name是方法输入的值;
- 在main方法运行时,先调用当前类的构造方法,但是子类的构造方法的第一行有隐藏的super()构造方法,所以先执行的还是父类的构造方法;
- super在调用父类的时候,必须在构造方法的第一个;(同6)
- 调用父类有参数的构造方法时,super()要传参,就必须要在子类的构造方法中写super(参数),而且要在第一行;
- super只能出现在子类的方法和构造方法中;
- super和this不能同时调用相同的方法;
- 一个接口可以继承多个其他接口。
- 类不一定会实现多个接口(接口中有相同的抽象方法时,不能同时实现这两个接口)。
- 多态
对于不同的类要写同样的方法,为了简化产生了多态;- 把不同的数据类型(引用类型,也就是类)进行转型;
Animal ani1 =new Cat();//可以把猫当成动物来看,把子类的对象赋值给父类的引用(变量)向上转型 Animal ani2 =new Dog(); Person1 person1 = new Person1(); person1.feed(ani1); person1.feed(ani2);
- 把子类的对象赋值给父类的变量-->向上转型; 会屏蔽掉子类特有的(共同的方法,会用子类的)方法,会调用子类重写的方法,调用方法要看对象(后面的),要是子类不重写,调用的还是父类的。调用属性或赋值属性要看声明的对象是谁(前面的)。
- 把父类的变量转化回子类的变量-->向下转型;向下转型有可能有风险,java要求必须要写强制类型转换, 格式: 子类 变量= (转换之后的数据类型) 父类变量
Cat cc=(Cat)ani1;//把Animal类型转化为cat
-
强制转换:只有确定该对象属于某一个类型才能正确转换(成功转换),否则报错(发生异常);Parent pp=new Parent(); Object oo=pp; Parent pp1=(Parent)oo;//因为上面oo指向pp,因为pp是new Parent ,Parent类型,所以object类型的oo可以强制转换为Parent类型 // Son o1=(Son)oo; 报错java.lang.ClassCastException,没有new Son()
-
判断某一个对象是否属于该类型的方法;
System.out.println(oo instanceof Parent);//会返回布尔值类型 System.out.println(oo instanceof Son); System.out.println(oo instanceof Object);
- 方法重载(静态多态---编译时多态)
方法相同,但是只是传入参数类型或参数个数不同,通过不同的参数类型或个数调用对应的方法;-
可以通过创建类的对象来调用;
-
也可以用到有参构造方法,重载多个有参构造方法,在创建对象时直接传入参数;
-
在有参构造前面已经有了this.name=name;时,下面重载的可以直接写this();
- 方法重写(动态多态---运行时多态)
重写只和非静态有关(static修饰的方法不能子类重写,可以调用)子类重写范围要更大,返回值更精确;- 父类的变量可以指向任意子类的对象,子类重写父类方法引发的多态;
- 方法重写是指: 子类对父类中提供的方法进行重写定义;
- 需要有继承关系,子类重写父类的方法,重写的意义:子类不满足父类的方法,需要调用自己的方法;
- 父类和子类方法名和参数列表必须相同;
- 子类重写的方法访问权限不能小于父类的访问权限(别人访问父类要能再转到子类);
- 重写方法的返回值(类型)只能更精确(可以返回子类), 重写的参数列表不可以改(类型可以改);
- 多态,父类可以new子类;
- 快捷方式,鼠标右击generate---->Overrde Methods;
- 抽象类(abstract)
抽象类是一个约束,靠子类去实现,不能new抽象类,不能创建对象;- 抽象方法:使用abstract来修饰,不可以有方法体(就是{ }),直接用分号结束即可;
- 抽象类中可以写普通方法,但是抽象方法必须写在抽象类中;
- 子类继承抽象类,必须要先重写抽象类的所有方法;
- 非抽象子类必须要实现抽象父类的方法;
- 类没有多继承,只有单继承,但是接口有多继承;
- 抽象类存在的意义,被继承,通过抽象类可以强制的要求子类中必须有哪些方法,(规范性)因为有多态性才有的作用;
- 接口(interface)
普通类:只有具体实现;- 抽象类:具体实现(靠子类重写实现)和规范(抽象方法)都有!
- 接口:只有规范 ;
- 接口中的抽象方法可以不被实现;
- 接口里的所有定义都是抽象的,但是会省略public abstract ;
- 接口中可以声明static静态方法,但是静态方法不能是抽象的;
- 接口中所有的内容都是public 公开的,公共的,(一般的类默认default);
- 接口中所有的变量都是公共全局静态常量.(默认: public static final);
- 接口没有实例化对象,接口不能new出对象,接口不能定义构造方法,类才有构造方法;
- 接口需要实现类,类通过implements来实现接口;
- 实现了接口的类,就要实现(重写)接口所有的抽象方法(类似于抽象类的继承),抽象类例外,因为抽象类允许抽象方法存在;
public class UserServiceImple implements UserService,TimeService { @Override public void add(String str) { } @Override public void dele(int num) { } }
- 接口也不能实例化,接口中没有构造方法;
- 内部类
- 静态内部类:不可访问外部的非静态资源;
- 成员内部类:可以访问外部所有资源,但是本身内部不可有静态属性;
- 局部内部类:不可被访问修饰符和static修饰,只能访问final变量和形参;
- 匿名内部类:没有构造器,没有静态资源,无法被访问修饰符,static修饰,只能创建匿名内部类的一个实例;
内部类就是在一个类的内部再定义一个类,比如,A类中定义一个B类,那么B类相对A类来说就称为内部类,而A类相对B类来说就是外部类了;public class Outer { public void out(){ System.out.println("这是一个外部类"); } public class Inter{ public void in(){ System.out.println("这是一个内部类"); } } }
在另一个类 (有main主方法的类) 中调用这个A类时,要先实例化外部类,再通过外部类实例化内部类;public static void main(String[] args) { Outer outer=new Outer(); Outer.Inter inter = outer.new Inter(); outer.out();//外部类调用外部构造的方法 inter.in();//内部类调用内部构造的方法 }
内部类的一个作用,内部类B可以调用A中的私有方法;private int a = 10;//私有定义 public void out(){ System.out.println("这是一个外部类"); } public class Inter{ public void in(){ System.out.println("这是一个内部类"); } public void getId(){ //在内部类中定义一个方法,获取a, 在main主方法中可以直接用Inter, 调用getId然后获取定义的私有a System.out.println(a); } }
- 静态类会被先加载;
- 一个java类中可以有多个class文件,但是只能有一个public class;
- 局部内部类: 在类中直接定义class 类名{ };
public class New { public void method(){ class Inner{ public void in(){ } } } }
匿名对象: 不用把实例保存到变量中public class Applic { public static void main(String[] args) { new Apple().apple(); } } class Apple{ public void apple(){ System.out.println("你好"); } }
- 异常(Exception)
(RuntimeException) 运行时异常 包括:
- ArrayIndexOutOfBoundsException(数组下标越界);
- NullPointerException(空指针异常);
- ArithmeticException(算术异常);
- MissingResourceException(丢失资源);
- ClassNotFoundException(找不到类);
- 异常处理五个关键字
- try: try{ (监控区域看是否有异常) };
- 什么是异常? 程序运行中出现的意料之外的情况;
- try异常后的不会运行,
- 无论try是否捕捉到异常,finally都会被运行;
- e.printStackTrace();//打印异常日志;
- catch: catch捕获异常 catch(某个异常(最高是throwable)) 变量){ }
- finally(选用): 善后工作,正常捕获异常后回执行 finally{ }中的代码;
- throw: 主动抛出异常,把可能出现的异常提前抛出,一般在方法中使用;
- throws: 直接在方法上抛出,如果在方法中抛出不了异常,可以在方法上抛出;
- 捕获异常
- 快捷键,Ctrl+Alt+t可以自动把选中的代码包裹起来;
int a=1; int b=0; try { System.out.println(a/b); } catch (Exception e) { System.out.println("有异常已抛出"); } finally { System.out.println("finally"); } }
- try必须和catch一起使用,finally可以用也可以不用;
- throw和throws有区别,一个在方法中用,另一个在方法上用;
public void test(int a,int b ) throws ArithmeticException{ if(b==0){ throw new ArithmeticException(); } }
- throw和throws抛出异常需要try和catch捕获;
- 父类是Throwable,包括的子类有Exception和Error;
- Exception--->检查性异常,运行时异常;
- Error 错误
- 异常的使用
try{ System.out.println("A除以B的结果是"+a/b); }catch(Exception e) { System.out.println("输入的内容不复合规范"); e.printStackTrace();//打印异常日志 }finally { scan.close(); }
-
Throwable
-
Error(程序处理不了的情况) OOM
- Exception
- RuntimeException(运行时异常) ;
- 其他子类(检查型异常)
-
- 运行时异常
- 是RuntimeException子类;
- 不需要明文处理该异常;
- 可以通过代码规避该异常;
- 不需要使用throws声明方法中可能抛出的运行时异常;
- 检查型异常
- 是Exception子类,并且没有继承RuntimeException;
- 必须明文处理该异常,否则代码报错;
- 检查型异常多数和程序之外的资源交互,不能通过代码规避,必须是try;
- 如果方法中抛出检查型异常,必须明文声明throws异常类型;
浙公网安备 33010602011771号