提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档
前言
提示:这里可以添加本文要记录的大概内容:
关于Java面向对象的学习。
物以类聚。
一个类里面,只有一个 public class,但有多个class。
只是学习笔记!
提示:以下是本篇文章正文内容,下面案例可供参考
一、面向过程与面向对象
对于描述复杂的事情,为了从宏观上把握、从整体上合理分析,我们需要使用面向对象的思路来分析整个系统。但是,具体到微观操作,仍需要面向过程的思路去处理。
面向过程: 适合处理一些较为简单的问题。
面向对象: 适合处理需要多人协作的问题。
二、面向对象
1.面向对象编程
Object-Oriented Programming——OOP
本质: 以类的方式组织代码,以对象的组织(封装)数据。
a,从认识角度考虑是先有对象后有类的。对象,是具体的事物;类,是抽象的,是对对象的抽象。
b,从代码运行角度考虑是先有类后有对象。类是对象的模板。
2,面向对象编程的三大特性
a,封装
高内聚、低耦合
高类聚: 类的内部数据操作细节自己完成,外部不得干涉。
低耦合: 仅暴露少量的方法给外部使用。
隐藏信息: 禁止直接访问一个对象中数据的实际表示,通过操作接口访问。
属性私有、get / set
IDEA创建 get、set 方法快捷键:Alt + Insert
代码示例如下:
public class Student {
//属性私有
private String name;
private int age;
private int id;
//get & set
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
if (0 < age || age <120){
this.age = age;
}else{
this.age = 3;
}
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
}
b,继承
extends 的意思是“扩展”,子类是父类的扩展。
代码如下:
public class Student extends Person{
//代码
}
JAVA中类只有单继承,没有多继承。
子类 继承 父类,就会拥有父类 的 全部方法。
私有的东西无法被继承
a,继承是类和类之间的一种关系。除此之外,类和类之间的关系还有依赖、组合、聚合等。
b,继承关系的两个类:一个为子类(派生类),一个为父类(基类)。
子类继承父类,使用关键字 extends来表示。
c,子类和父类之间,从意义上讲应该具有“ is a ”的关系。
(1)object类
在JAVA中,所有的类都默认直接或者间接继承 object类
(2)super
super() 隐藏代码,调用了父类的无参构造
public class Student extends Person{
public Student(){
super();//调用父类构造器,必须在子类构造器的第一行
}
}
super 注意点:
a,super 调用父类的构造方法,必须在构造方法的第一个。
b,super 必须只能出现在子类的方法或者构造方法中。
c,super 和 this 不能同时调用构造方法。
与 this 的不同
代表的对象不同:
this :指本身调用者这个对象
super :代表父类对象引用
前提:
this :没有继承也可以使用
super :只能在继承条件才可以使用
构造方法:
this() :本类的构造
super() :父类的构造
(3)方法重写(需要有继承关系,子类重写父类)
方法重写注意点
1,方法名必须相同
2,参数列表必须相同
3,修饰符:范围可以扩大但不能缩小: public > Protected > Defaule > private
4,抛出异常:范围可以被缩小,但不能扩大; ClassNotFoundException --> Exception(大)
5,static 方法不能被重写,静态方法属于类,不属于实例
6,final 和 private 的方法也不能被重写
重写子类的方法必须和父类的一致,但是方法体不同。
重写都是方法的重写,与属性无关。
为什么重写:
1,父类功能,子类不一定需要,或者不满足。
IDEA快捷键:Alt + Insert
public class A extends B{
//重写
@Override//注解:有功能的注释
public void say() {
super.say();
}
}
say()为 父类B 中拥有的方法
c,多态
多态的定义
即同一方法可以根据发送给对象的不同而采用多种不同的行为方式;
一个对象的实际类型是确定的,但可以指向对象的引用的类型(父类、有关系的类)有很多
注意事项
1,多态是方法的多态,属性没有多态
2,父类和子类,存在关系,有联系。 类型转换异常 ---> ClassCastException
多态存在的条件
(1)有继承关系
(2)子类重写父类方法
(3)父类引用指向子类对象( Father f1 = new Son(); )
代码示例如下:
public class Application {
public static void main(String[] args) {
//可以指向的引用类型不确定,父类可以指向子类
//Student 能调用的方法都是自己的或者继承父类的
Student s1 = new Student();
//Person 父类型,可以指向子类型,但是不能调用子类独有的方法
Person s2 = new Student();
Object s3 = new Student();
//对象能执行哪些方法,主要看左边的类型,和右边关系不大
s1.say();//子类重写了父类的方法,执行子类的方法
s2.say();
//两个类型都有的方法,将会执行子类的方法
}
}
instanceof
多态主要看左边
判断是否有继承关系
两者毫无继承关系,编译器会报错
类型转换
Person person = new Student();
((Student)person).go();//父类使用子类方法,需要强转换
子类型转父类型(不需要强转换),可能会丢失子类的方法
(1)子类转换成父类,直接转换。
(2)父类转换成子类,需要强制转换。
(3)方便方法的调用,简洁代码
2,方法的调用
a,静态方法
在其它类中使用, 类名加方法名 进行调用 ,代码如下:
package com.OOP;
public class Demo01 {
public static void main(String[] args) {
Good.sleep();
}
}
===================================================================
package com.OOP;
public class Good {
public static void sleep(){
System.out.println("睡着了");
}
}
在相同类中使用,方法名() 进行调用,代码如下:
public class Demo01 {
public static void main(String[] args) {
sleep();
}
public static void sleep(){
System.out.println("睡着了");
}
}
b,非静态方法
在其他类中使用,new 关键字进行调用,代码如下:
package com.OOP;
public class Demo01 {
public static void main(String[] args) {
Good good = new Good();
good.sleep();
}
}
===================================================================
package com.OOP;
public class Good {
public void sleep(){
System.out.println("睡着了");
}
}
在同一个类中使用,同样使用 new 关键字 进行调用,代码如下:
public class Demo01 {
public static void main(String[] args) {
Demo01 demo = new Demo01();
demo.sleep();
}
public void sleep(){
System.out.println("睡着了");
}
}
c,this关键字
代表当前这个类
3,值传递和引用传递
a,值传递
代码示例如下:
//值传递
public class Demo02 {
public static void main(String[] args) {
int a = 5;
System.out.println(a);//5
change(a);
System.out.println(a);//5
}
public static void change(int a){
a = 20;
}//此方法无返回值,所以对 main 方法里的 a 起不到作用。
}
b,引用传递(传递一个对象,本质还是值传递)
//引用传递
public class Demo03 {
public static void main(String[] args) {
Person person = new Person();
System.out.println(person.name);
change(person);
System.out.println(person.name);
}
public static void change(Person person){
//person 是一个对象:指向的 --->Person person = new Person();这是一个具体的人,可以改变属性!
person.name = "刍狗";
}
}
//定义一个Person类,有一个属性:name
class Person{
String name;
}
3,类与对象的关系
类是一种抽象的数据类型,它是对某一类事物整体描述/定义,但是并不能代表某一个具体的事物。
对象是抽象概念的具体实例
//学生类
public class Student {
//属性:字段
String name;
int age;
//方法
public void study(){
System.out.println(this.age +"岁的学生"+this.name + "正在学习!");
}
}
=====================================================================
package com.OOP.demo01;
//一个项目只有一个 main 方法
public class Application {
public static void main(String[] args) {
//类:抽象的,实例化
//类实例化后会返回一个自己的对象
//student对象就是一个Student类的具体实例
Student chugou = new Student();//new 实例化对象
chugou.name = "刍狗";
chugou.age = 18;
chugou.study();
Student zhongli = new Student();//每个实例对象都是独立的
zhongli.name = "钟离";
zhongli.age = 5000;
zhongli.study();
Student hutao = new Student();//互不影响
hutao.name = "胡桃";
hutao.age = 2000;
hutao.study();
}
}
4,创建和初始化对象
a,使用 new 关键字创建的时候,除了分配内存空间之外,还会给创建好的对象进行默认的初始化以及对类中构造器的调用。
b,类中的构造器也称为构造方法,是在进行创建对象的时候必须要调用的。
构造器的特点:
(1)必须和类的名字相同。
(2)必须没有返回类型,也不能写 void。
构造器作用:
(1)new 本质是在调用构造方法
(2)初始化对象的值
构造器的注意点:
(1)定义有参构造之后,如果想使用无参构造,显示的定义一个无参的的构造
IDEA生成构造器的快捷键:Alt + Insert
代码示例如下:
public class Test{
public Test(){
...
}
}
三、static 关键字详解
1,静态变量
static修饰的变量称为 静态变量
静态变量和非静态变量的区别是:
静态变量被所有对象共享
在内存中只有一个副本,它当且仅当在类初次加载时会被初始化。
非静态变量是实例对象所拥有的
在创建对象的时候被初始化,存在多个副本,各个对象拥有的副本互不影响。
2,静态方法
静态方法和非静态方法的区别是:
static修饰的方法一般称作静态方法,是没有 this的。
在静态方法中不能访问类的非静态成员变量和非静态成员方法
非静态成员方法必须依赖实例对象才能够被调用。
相关代码和解释如下:
public class Application {
运行顺序:1, 跟类一起加载,只会在类被初次加载的时候执行一次
static {
System.out.println("静态代码块");
}
运行顺序:2(对象一创造,就会运行匿名代码块,接着运行构造方法)可初始值
{
System.out.println("匿名代码块");
}
运行顺序:3
public Application() {
System.out.println("构造方法");
}
public static void say1(){
System.out.println("静态方法");
}
public void say2(){
System.out.println("非静态方法");
}
public static void main(String[] args) {
Application application = new Application();
System.out.println("===================================");
Application application1 = new Application();//静态方法不输出了
say1();//静态方法可以直接调用
say2();//非静态方法不可直接调用
new Application().say2();//非静态方法需要实例对象
}
}
四、抽象类
抽象类代码示例:
public abstract class Application {
....
}
抽象类的所有方法,子类必须要重写,除非子类也是抽象类
abstract,抽象方法,只有方法名字,没有方法的实现。
public abstract void doSomething();
1,不能 new 这个抽象类,只能靠子类去实现它:(约束)
2,抽象类中可以写普通的方法
3,抽象方法必须在抽象类中
抽象的抽象:约束
五、接口
1,认识接口
普通类:只有具体实现
抽象类:具体实现和规范(抽象方法)都有
接口:只有规范!自己无法写方法,专业的约束!约束和实现分离:面向接口编程
接口中的所有常量都是:public static final
接口中所有的方法都是:public abstract
接口中没有构造方法
接口不能被实例化
接口只用于定义方法,可以由不同的人来实现
接口的方法由实现类实现
2,接口就是钟离,就是摩拉克斯
定义一组规则,体现了现实世界中“如果你是...则必须能...”的思想。
接口本质是契约,所以接口就是钟离,就是摩拉克斯。
3,关键字
声明类的关键字是 class ,接口的声明关键字是 interface,实现类的声明关键字是 implements
抽象类使用的是 extends ,只能单继承
接口使用的 implements ,可以多继承
接口无法自己写方法,要通过其实现类实现接口的方法
接口关键字 interface ,接口都需要有实现类
在接口定义的属性都是常量
代码示例如下:
public interface UserService {
//在接口定义的属性都是常量
int age = 18;//前面默认的修饰符是 public static final
public static final String name = "刍狗";//完整的
//接口中的所有定义,其实都是抽象的 public abstract,如下所示
public abstract void sam();
void say();
}
接口实现类在 IDEA 中重写方法的快捷键:
Alt + Insert
接口实现类(实现类命名一般用 Impl 做结尾)代码如下:
//接口可以多继承
public class UserServiceImpl implements UserService,TimeService{
@Override
public void sam() {
...
}
@Override
public void say() {
...
}
}
实现接口的类必须重写接口的方法
六、初识内部类
public class Zhongli {
private String name = "钟离";
public void print(){
System.out.println("外部类");
}
public static class StaticInner{
public void print(){
System.out.println("静态内部类");
}
}
public class Inner{
public void print(){
System.out.println("非静态内部类");
System.out.println(name);
}
}
}
public class Application {
public static void main(String[] args) {
Zhongli zhongli = new Zhongli();
zhongli.print();
System.out.println("===============================");
//有 static 关键字的类
Zhongli.StaticInner zhongli1 = new Zhongli.StaticInner();
zhongli1.print();
System.out.println("===============================");
//无 static 关键字的类
Zhongli.Inner zhongli2 = zhongli.new Inner();
zhongli2.print();
}
}