目录
本文是B站遇见狂神说java基础课中面向对象编程部分看完之后个人整理的相关笔记
面向对象是什么
类:属性+方法
本质:以类的方式组织代码,以对象的组织(封装)数据
三大特性:封装,继承,多态
先有类后有对象,类是对象的模板
类是一个模板,是抽象的;对象是一个具体的实例
方法的调用
调用存在于其他类的方法
1.是静态方法时
public class Student { public static void say(){ //是和类一起加载的 System.out.println("学生说话了"); } } //调用 public class Demo { public static void main(String[] args) { Student.say(); } }
2.不是静态方法时
public class Student { public void say(){ //是类实例化之后才存在的 System.out.println("学生说话了"); } } public class Demo { public void main(String[] args) { Student student = new Student(); student.say(); }
对象的调用
public class Demo { public static void main(String[] args) { Person person = new Person(); System.out.println(person.name); Demo.change(person); System.out.println(person.name); } public static void change(Person a){ //Person是一个对象,指向Person person = new Person();相当于这是个具体的人,可以 a.name="沈央央"; } } class Person{ String name; }
构造器
一个类即使什么都不写也会存在一个方法,显示的定义构造器,与类名相同
特点:
1.和类名相同
2.没有返回值
作用:
1.使用new关键字本质是调用构造器 2.用来初始化值
public class Personn { String name; //无参构造,系统默认伴随着类出现的 public Personn(){ name="shen"; } //有参构造:一旦定义了有参构造,无参构造就必须显示定义 public Personn(String a){//String name name=a; //this.name=name; } }
public class Application { public static void main(String[] args) { Personn personn2=new Personn("央央"); Personn personn = new Personn(); System.out.println(personn.name); System.out.println(); } }
自动生成构造器快捷键
alt+Fn+insert
默认生成有参的函数,如果想生成无参的选select none
封装
程序设计“高内聚,低耦合”,高内聚就是类的内部数据操作细节自己完成,不允许外部干涉;低耦合:仅暴露少量的方法给外部使用。
封装通常情况下针对于属性,而非函数
public class Student { private String name; private int age; private int id; private char sex; //私有后在外部无法使用直接改变属性,因此需要提供一些可以操作这个属性的方法 //提供一些public的get,set的方法 //get获得需要的属性 public String getName(){ return name; } //set 给这个属性设置值 public void setName(String a){//可以写为String name name=a; //上面使用name之后,这里需要写this.name=name; } }
public class Application { public static void main(String[] args) { Student s1 = new Student(); s1.setName("沈央央"); System.out.println(s1.getName()); } }
同样,也是alt+Fn+insert 快捷键选中可以自动生成get,set函数,自己勾选需要的属性。
封装意义
1.提高程序安全性,保护程序
2.隐藏代码的实现细节
3.统一接口
4.系统的可维护性提高
继承
快捷键:ctrl+h,打开继承树,可以查看继承关系
在Java中,所有类都默认继承Object类
public class Student extends Person
javaStudent s = new Student();
在main函数中构造子类时,默认直接调用父类和子类的无参构造(相对于隐藏起来的函数调用),即在子类中其无参构造中隐藏了super();
super注意点
-
super调用父类的构造方法,必须在构造方法的第一个
-
super必须只能出现在子类的方法或者构造方法中
-
super和this不能同时调用构造方法
super和this的区别
1.代表的对象不同:
this:本身调用者这个对象
super:代表父类对象的应用
2.前提
this:没有继承也可以使用
super:继承才能使用
3.构造方法
this();本类的构造
super();父类的构造
方法的重写
重写都是方法的重写和属性无关
public class B { public static void test(){ System.out.println("B=>test()"); } }
public class A extends B{ public static void test(){ System.out.println("A=>teat()"); } }
public class Application { public static void main(String[] args) { //方法的调用只和左边定义的数据类型有关 A a = new A(); a.test(); //走A的方法 //父类的引用指向了父类 B b = new A(); b.test(); //走B的方法 } }
去掉A和B的static,删除A中的test();,然后alt+Fn+insert,选择重写方法,自动会出现test(),选择会出现
//Override 重写 @Override //注解:有功能的注释 public void test() { super.test(); }
修改之后Application 中的a,b全部走A自己的方法
知识点
重写需要存在继承关系,子类重写父类的方法
重写只和非静态方法有关和静态方法无关
1.方法名必须相同(快捷键自己会弄),方法体(里面的内容)不同
2.参数列表必须相同
3.修饰符:范围可以扩大但是不能缩小,private不行
public>protected>default>private
4.抛出的异常:范围,可以被缩小但是不能被扩大
多态
public class Personn { public void run(){ System.out.println("run"); } }
public class Student extends Personn{ @Override public void run() { System.out.println("son"); } public void eat(){ System.out.println("eat"); } }
public class Application { public static void main(String[] args) { //一个对象的实际类型是确定的 new Student Student s1 = new Student(); //但是可以指向的应用类型就不确定了,父类的引用指向子类,但是不能调用子类独有的方法 Personn s2 = new Student(); //对象能执行哪些方法,要看对象左边的类型和右边关系不大,左边类里面有的方法才能执行 //但是右边的类型决定执行的是哪个类里面的这个方法 s2.run(); s1.run(); } }
s2执行eat就会报错
注意事项
1.多态是方法的多态
2.父类和子类,有联系 类型转换异常:ClassCastException
3.存在条件:继承关系,方法需要重写,父类引用指向子类
4.不能重写的情况 :
static,final常量,private
instanceof和类型转换
instanceof 判定类是否属于另一个类的类型,输出true或者false
public class Student extends Personn public class Teacher extends Personn
public class Application { public static void main(String[] args) { Personn personn = new Personn(); System.out.println(personn instanceof Student); System.out.println(personn instanceof Personn); System.out.println(personn instanceof Object); System.out.println(personn instanceof Teacher); System.out.println("####################"); Personn personn1 = new Student(); System.out.println(personn1 instanceof Student); System.out.println(personn1 instanceof Personn); System.out.println(personn1 instanceof Object); System.out.println(personn1 instanceof Teacher); System.out.println("####################"); Student student = new Student(); System.out.println(student instanceof Student); System.out.println(student instanceof Personn); System.out.println(student instanceof Object); //System.out.println(student instanceof Teacher);会报错 } } //总结:也就是能不能比较看左边的(不能比较的情况就是没有在一个继承树上,eg:最后一个例子Teacher和Student),比较的结果Ture还是False看右边的,对于继承树而言越靠近根的包容性越强,所有的类instanceof Object都是true,因为object是根
类型转换
越靠近继承树的根级别越高,越是子类级别越低
低转高可以默认转,高转低需要强制类型转换
只能父类的引用指向子类的对象
//低转高,子类转化为父类可能会丢失自己本来的一些方法 Student student = new Student(); Personn personn=student; //高转低,强制转换 Personn obj=new Student(); ((Student)obj).go();
static关键词详解
非静态方法可以调用静态方法里面的所有东西,静态方法不能调用非静态
public class Personn { { System.out.println("匿名代码块"); } //首先执行且只执行一次 static{ System.out.println("静态代码块"); } public Personn() { System.out.println("构造方法"); } public static void main(String[] args) { Personn personn = new Personn(); System.out.println("#################"); Personn personn1 = new Personn(); } }
public static void main(String[] args) { Personn personn = new Personn(); System.out.println("#################"); Personn personn1 = new Personn(); }
public final class Personn
这样时就不能被继承
抽象类
public abstract class Action { //只有方法名字,没有方法的实现 public abstract void doSomething(); //1.抽象类不能new,只能靠子类来实现 //2.抽象类中可以写普通的方法 //3.但是抽象方法必须在抽象类中 }
public class A extends Action{ //抽象类的所有方法,继承了他的子类都必须要实现它的方法,除非子类也是个接口 @Override public void doSomething() { } }
接口
接口的本质是契约,制定好之后大家都要遵循
接口不能被直接实例化,接口中没有构造方法
接口可以多个继承,必须重写里面的方法
public interface UserService { //一般不用,用的话就是默认public static final int a=99; //接口中所有的定义其实都是默认抽象的public abstract void add(String name); void delect(String name); void update(String name); void query(String name); }
package ObjectOriented; //类可以实现接口implements //实现接口的类,就需要重写接口中的方法 //可以实现多个接口逗号隔开 public class UserServiceImpl implements UserService{ //alt+fn+insert 实现方法选就行 @Override public void add(String name) { } @Override public void delect(String name) { } @Override public void update(String name) { } @Override public void query(String name) { } }
内部类
1.内部类
public class Outer { private int id=10; public void out(){ System.out.println("这是外部类的方法"); } public class Inner{ public void in(){ System.out.println("这是内部类的方法"); } //获得外部类的私有属性 public void getID(){ System.out.println(id); } } }
public class Application { public static void main(String[] args) { Outer outer = new Outer(); Outer.Inner inner = outer.new Inner(); inner.getID(); } }
public class Outer { //2.局部内部类 public void method(){ class Inner{ public void in(){ } } } } //3.一个java文件中可以有多个class类但是只有有一个public class class A{ }
4.匿名初始类
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("1"); } } interface UserService{ void hello(); }
异常
错误:Error 异常:Exception
区别:
Error通常是灾难性的致命错误,是程序无法控制和处理的,出现这些异常时,java虚拟机(jvm)一般会选择终止线程;Exception通常情况下是可以被程序处理的,并且在程序中应该尽可能的去处理这些异常。
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("程序出现异常"); }catch (Exception e){ } catch (Throwable){ } //可有多个catch捕获异常,但是越大的异常越要放在后面 //捕获多个异常,要从小到大,否则会报错 finally { //处理善后工作,finally区域可以不要,上面两个必须有 System.out.println("finally"); } } }
自动生成抓取异常的代码:
选中被测试的语句,ctrl+alt+t,一般选try,catch,finally
public static void main(String[] args) { int a=1; int b=0; try { System.out.println(a/b); } catch (Exception e) { e.printStackTrace(); //打印异常栈信息 throw new RuntimeException(e); //异常包在一个运行时异常中抛出 } finally { } }
换成函数后
//假设这个方法中,处理不了这个异常,方法上抛出异常 public void test(int a,int b) throws ArithmeticException{ if(b==0){ throw new ArithmeticException(); //主动抛出异常一般在方法中使用 } }
自定义异常
只需要继承exception类即可