目录
面向对象是什么
方法的调用
调用存在于其他类的方法
对象的调用
构造器
自动生成构造器快捷键
封装
封装意义
继承
super注意点
super和this的区别
方法的重写
知识点
多态
注意事项
instanceof和类型转换
类型转换
static关键词详解
抽象类
接口
内部类
异常
本文是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的区别
super调用父类的构造方法,必须在构造方法的第一个
super必须只能出现在子类的方法或者构造方法中
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类即可



