java null大于0 报错_JAVA面向对象

一、类与对象的关系

类 抽象的概念

对象 看得见摸得着的具体实体

类实例化后得到对象

创建宠物猫类

package com.alan.animal;

/**

* 宠物猫类

* @author alan

*

*/

public class Cat {

//属性:昵称、年龄、体重、品种

String name; //昵称 String 默认值null

int month; //年龄 int 默认值为 0

double weight; //体重 double 默认值为0.0

String species; //品种

//方法:跑动、吃东西

//跑动的方法

public void run() {

System.out.println("小猫快跑");

}

//对跑动的方法进行重载

public void run(String name) {

System.out.println(name+"快跑");

}

//吃东西的方法

public void eat() {

System.out.println("小猫吃鱼");

}

}

宠物猫类测试

package com.alan.animal;

public class CatTest {

public static void main(String[] args) {

//对象实例化

Cat one = new Cat();

//测试 调用方法

one.eat();

one.run();

one.name = "花花";

//在类没有初始化的情况下,构造函数对其进行默认的赋值 String 为null ,int 为0,double为0.0

System.out.println("name="+one.name);

System.out.println("species="+one.species);

System.out.println("month="+one.month);

System.out.println("weight="+one.weight);

one.run(one.name);

}

}

单一责任原则

一个类只负责一个功能,如果一个类功能太多则耦合性过高,复用的可能性越低。

实例化对象

分为两个部分:

声明对象 Cat one 在栈中开辟一块空间,但是没有赋值为null

实例化对象 new cat(); 在堆里面开辟的一块空间

Cat one = new cat(); // 将堆空间中的地址赋值给栈,栈为指向堆的引用

80c52c0d384c?utm_campaign=maleskine&utm_content=note&utm_medium=seo_notes&utm_source=recommendation

image.png

构造方法(构造函数)

在new的时候构造方法会被调用,不能被对象单独调用

1、构造方法与类同名且没有返回值。

2、只能在对象实例化的时候调用。

3、当没有指定构造方法时,系统会自动添加无参的构造方法。

4、就近原则,如果使用name=name赋值,会优先选择同一个作用域,进行赋值,所以要使用不同名字,或者用this.name=name 进行赋值。

this关键字

代表当前对象的属性或者方法,例如this.name表示当前这个class的属性。

80c52c0d384c?utm_campaign=maleskine&utm_content=note&utm_medium=seo_notes&utm_source=recommendation

image.png

80c52c0d384c?utm_campaign=maleskine&utm_content=note&utm_medium=seo_notes&utm_source=recommendation

image.png

this与创建的对象具有相同的ID值,说明this调用的就是当前的对象

this();可以调用无参构造方法,但是一定是在其他构造方法的第一行。

其他的方法不能调用构造函数。

二、Java封装

将类的某些信息隐藏在类内部,不允许外部程序直接访问。

80c52c0d384c?utm_campaign=maleskine&utm_content=note&utm_medium=seo_notes&utm_source=recommendation

image.png

只有get方法 是只读属性

只有set方法 是只写属性

创建包

同一个包中不允许出现相同文件名的Cat,引用同名的

package com.alan.test;

import com.alan.animal.Cat;

import com.alan.mechanics.*; //通过.*直接加载到直接的类,不能使用com.alan.*这种方式

public class Test {

public static void main(String[] args) {

com.alan.mechanics.Cat one = new com.alan.mechanics.Cat(); //直接导入的是animal中的Cat,如果需要用mechanics中的需要在代码中加入com等具体的包路径

// System.out.println("调用成功!");

}

}

static关键字

//static 静态 静态成员 类成员 ,所有对象都使用一块内存空间,所以所有的实例化对象,static修饰的值都相同

public static int price; //用static修饰后 price变为斜体

1、类对象共享该内存信息

2、类加载时产生,直到类销毁的时候释放。生命周期长。

3、静态成员的访问方式,既可以通过对象名访问,也可以通过类名访问。

one.price (对象名访问) Cat.price(类名访问)

4、当static修饰方法时,该方法为静态方法,推荐采用类名调用,如Cat.eat();

5、有静态的属性和方法,静态方法中不能直接访问同一个类的非静态成员,只能直接调用同一个类中的静态成员。只能通过实例化后进行访问没有静态的类,没有静态的局部变量。

代码块{}

普通代码块:在方法中的代码块叫做普通代码块。顺序执行,先出现,先执行。

构造代码块:在类中的代码块叫构造代码块。创建对象时调用,优先与构造方法执行。

静态代码块:构造代码块加上static关键字,就是静态代码块。类加载时调用,优先于构造代码块执行。 无论实例化多少个对象,只执行一次。

command+shift+f 行内容过长,换行快捷键。

三、Java封装综合案例

在方法中通过对象作为参数,传递的是它的引用,可以通过引用获取该对象的所有信息。

数组未实例化会造成空指针异常 java.lang.NullPointerException

package com.alan.model;

/**

* 学生类

*

* @author alan

*

*/

public class Student {

// 成员属性:学号、姓名、性别、年龄、专业对象

private String studentNo;

private String studentName;

private String studentSex;

private int studentAge;

private Subject studentSubject;

// 无参构造

public Student() {

}

// 带参构造

public Student(String studentNo, String studentName, String studentSex, int studentAge,Subject studentSubject) {

this.setStudentNo(studentNo);

this.setStudentName(studentName);

this.setStudentSex(studentSex);

this.setStudentAge(studentAge);

this.setStudentSubject(studentSubject);

}

/**

* 获取专业对象,如果没有实例化,先实例化后再返回

* @return 专业对象

*/

public Subject getStudentSubject() {

if(this.studentSubject == null)

this.studentSubject = new Subject(); //无参构造的重要性就提现出来了

return studentSubject;

}

public void setStudentSubject(Subject studentSubject) {

this.studentSubject = studentSubject;

}

public String getStudentNo() {

return studentNo;

}

public void setStudentNo(String studentNo) {

this.studentNo = studentNo;

}

public String getStudentName() {

return studentName;

}

public void setStudentName(String studentName) {

this.studentName = studentName;

}

public String getStudentSex() {

return studentSex;

}

public void setStudentSex(String studentSex) {

this.studentSex = studentSex;

}

public int getStudentAge() {

return studentAge;

}

/**

* 给年龄赋值。限定大于10,小于50,否则赋值为18

*

* @param studentAge 传入的年龄

*/

public void setStudentAge(int studentAge) {

if (studentAge < 10 || studentAge > 50)

this.setStudentAge(18);

else

this.studentAge = studentAge;

}

/**

* 学生自我介绍的方法

*

* @return 自我介绍信息,包括姓名、学号、性别、年龄

*

*/

public String introduction() {

String str = "学生信息如下:\n姓名:" + this.getStudentName() + "\n学号:" + this.getStudentNo() + "\n性别:"

+ this.getStudentSex() + "\n年龄:" + this.getStudentAge()+ "\n所报专业名称:" + this.getStudentSubject().getSubjectName() + "\n学制年限:"

+ this.getStudentSubject().getSubjectLife();

return str;

}

/**

* 学生自我介绍的方法

*

* @param subjectName 所学专业名称

* @param subjectLife 学制年限

* @return 自我介绍信息,包括姓名、学号、性别、年龄、所学专业名称、学制年限

*/

public String introduction(String subjectName, int subjectLife) {

String str = "学生信息如下:\n姓名:" + this.getStudentName() + "\n学号:" + this.getStudentNo() + "\n性别:"

+ this.getStudentSex() + "\n年龄:" + this.getStudentAge() + "\n所报专业名称:" + subjectName + "\n学制年限:"

+ subjectLife;

return str;

}

/**

* 学生自我介绍的方法

* @param sub1 传入学科对象

* @return 自我介绍信息,包括姓名、学号、性别、年龄、所学专业名称、学制年限

*/

public String introduction(Subject sub1) {

String str = "学生信息如下:\n姓名:" + this.getStudentName() + "\n学号:" + this.getStudentNo() + "\n性别:"

+ this.getStudentSex() + "\n年龄:" + this.getStudentAge() + "\n所报专业名称:" + sub1.getSubjectName()

+ "\n学制年限:"+sub1.getSubjectLife();

return str;

}

}

学科类

package com.alan.model;

public class Subject {

// 成员属性:学科名称、学科编号、学制年限、选课学生数组、报名选修的学生个数

private String subjectName;

private String subjectNo;

private int subjectLife;

private Student[] myStudents;

private int studentNum;

// 无参构造方法,定义一下,防止出现意外的错误。

public Subject() {

}

// 带参构造方法 对学科名称、学科编号、学制年限赋值

public Subject(String subjectName, String subjectNo, int subjectLife) {

this.setSubjectName(subjectName); // 尽量采用此种赋值方式,而不用this.subjectName=subjectName

this.setSubjectNo(subjectNo); // 因为set方法中有时候会包含一些逻辑校验

this.setSubjectLife(subjectLife);

}

// 带参构造方法 对全部属性赋值

public Subject(String subjectName, String subjectNo, int subjectLife,Student[] myStudent) {

this.setSubjectName(subjectName); // 尽量采用此种赋值方式,而不用this.subjectName=subjectName

this.setSubjectNo(subjectNo); // 因为set方法中有时候会包含一些逻辑校验

this.setSubjectLife(subjectLife);

this.setMyStudents(myStudent);

}

/**

* 获取选修专业学生信息,如果保存学生信息的数组没有被初始化,则初始化长度为200

* @return 保存学生信息的数组

*/

public Student[] getMyStudents() {

if(myStudents == null)

myStudents = new Student[200];

return myStudents;

}

public void setMyStudents(Student[] myStudents) {

this.myStudents = myStudents;

}

public String getSubjectName() {

return subjectName;

}

public void setSubjectName(String subjectName) {

this.subjectName = subjectName;

}

public String getSubjectNo() {

return subjectNo;

}

public void setSubjectNo(String subjectNo) {

this.subjectNo = subjectNo;

}

public int getSubjectLife() {

return subjectLife;

}

// 设置学制年限,必须大于0

public void setSubjectLife(int subjectLife) {

if (subjectLife <= 0)

return;

this.subjectLife = subjectLife;

}

public int getStudentNum() {

return studentNum;

}

public void setStudentNum(int studentNum) {

this.studentNum = studentNum;

}

/**

* 专业介绍的方法

* @return 专业介绍的相关信息 专业名称、专业编号、学制年限

*/

public String info() {

String str = "专业信息如下: \n" + "专业名称:" + this.getSubjectName() + "\n专业编号:" + this.getSubjectNo() + "\n学制年限:"

+ this.getSubjectLife();

return str;

}

public void addStudent(Student stu) {

//1、将学生保存到数组中

for(int i=0;i

if(this.getMyStudents()[i]==null) {

this.getMyStudents()[i] = stu;

//2、将学生的个数保存到studentNum中

this.studentNum = i+1;

return;

}

}

}

}

测试

package com.alan.test;

import com.alan.model.Student;

import com.alan.model.Subject;

public class NewTest {

public static void main(String[] args) {

Subject sub1 = new Subject("计算机科学与应用","J0001",4);

System.out.println(sub1.info());

System.out.println("=======================");

Student stu1 = new Student("S01","张三","男",58,sub1);

System.out.println(stu1.introduction());

System.out.println("=======================");

Student stu2 = new Student("S02","李四","男",19,sub1);

System.out.println(stu2.introduction("计算机科学与技术", 4));

System.out.println("=======================");

Student stu3 = new Student("S03","王五","女",17,sub1);

System.out.println(stu3.introduction(sub1));

System.out.println("=======================");

sub1.addStudent(stu1);

sub1.addStudent(stu2);

sub1.addStudent(stu3);

System.out.println("学生的总数为:"+sub1.getStudentNum());

}

}

四、Java继承

子类继承父类可以直接获取父类的非私有成员(包括属性和方法)

command+shift+o 快速导入包

父类不能访问子类的特有成员(包括属性和方法)

方法重写

1、子类重写父类的方法

2、方法名相同、参数列表相同(参数顺序、个数、类型),方法返回值相同

3、方法的访问修饰符是允许有变化的,但是访问范围要大于等于父类的访问范围)

4、与方法参数名无关(string name)可以换成(string month)

访问修饰符

private 修饰的成员(属性和方法)只能在本类中访问

public 修饰的成员(属性和方法)访问范围最大,可以在本类、子类、跨包中访问。

protected 修饰的成员(属性和方法) 可以在本类,同包子类,同包非子类,跨包子类使用。跨包非子类中不允许

默认 修饰的成员(属性和方法) 可以在本类,同包子类,同包非子类,不允许在跨包子类/非子类访问

80c52c0d384c?utm_campaign=maleskine&utm_content=note&utm_medium=seo_notes&utm_source=recommendation

image.png

super关键字

父类对象的引用,当子类中重写父类方法,需要调用父类的原有方法,需要加上super关键字。

子类构造默认调用父类的无参构造,可以通过super关键字调用父类允许被访问的其他构造方法。必须放在第一行

继承的初始化顺序

首先加载父类的静态成员,父类的静态代码块

接着加载子类的静态成员,子类的静态代码块

父类的成员属性赋值

父类的构造代码块

父类的构造函数

子类的构造代码块

子类的构造函数

80c52c0d384c?utm_campaign=maleskine&utm_content=note&utm_medium=seo_notes&utm_source=recommendation

image.png

this 与 super 分别指定当前类和父类 不能在静态方法中使用

80c52c0d384c?utm_campaign=maleskine&utm_content=note&utm_medium=seo_notes&utm_source=recommendation

image.png

Object类

Object类是所有类的父类

Object中的 equals 相当于== 比较两个字符串的引用是否相同

String中的 equals 被重写 比较两个字符串的值是否相等

tostring也是重写率非常高的一个方法

/*tostring测试

* 1、输出对象名时,默认会调用toString方法

* 2、输出对象为:类型信息+@+地址信息 如:com.alan.animal.Animal@7b1d7fff

* */

final关键字

final修饰class表示该类没有子类,不允许被继承。

String类 System类都是final修饰的

final 修饰方法,该方法不允许被重写,但是可以正常被子类继承使用

final 修饰方法内局部变量,该局部变量不允许被再次修改。

final 修饰类成员属性,没有赋值的话,只能在构造函数或者构造代码块中进行赋值

final修饰引用类型的变量,初始化后不能再指向另一个对象,但对象的内容可以改变。

注释简介

快捷键 option+/

@Override 给编译器看的,编译之后注解就没有用了。

五、Java设计模式

80c52c0d384c?utm_campaign=maleskine&utm_content=note&utm_medium=seo_notes&utm_source=recommendation

image.png

单例模式

目的:使类的一个对象成为该类系统的唯一的实例。

定义:一个类有且仅有一个实例,并且自行实例化向整个系统提供

80c52c0d384c?utm_campaign=maleskine&utm_content=note&utm_medium=seo_notes&utm_source=recommendation

image.png

饿汉式代码实现

线程安全的

package com.alan.singleton;

//饿汉式:创建对象实例的时候直接初始化

public class SingletonOne {

//1、创建类中的私有构造

private SingletonOne() {

}

//2、创建该类型的私有静态实例

private static SingletonOne instance = new SingletonOne();

//3、创建公有静态方法返回静态实例对象

public static SingletonOne getInstance() {

return instance;

}

}

测试

import com.alan.singleton.SingletonOne;

public class Test {

public static void main(String[] args) {

// TODO Auto-generated method stub

// SingletonOne one = new SingletonOne(); 构造方法已经私有化,这种方式不允许

SingletonOne one = SingletonOne.getInstance();

SingletonOne two = SingletonOne.getInstance();

System.out.println(one);

System.out.println(two); //所有的引用都会指向同一个对象

}

}

懒汉式代码实现

线程不安全的

通过1、同步锁 2、双重校验锁 3、静态内部类 4、枚举 解决线程不安全问题。

package com.alan.singleton;

// 懒汉式单例模式

public class SingletonTwo {

// 1、创建私有构造方法

private SingletonTwo() {

}

// 2、创建私有静态实例,静态的实例被共享,一定需要此修饰符

private static SingletonTwo instance = null;

// 3、创建静态公有方法返回静态实例对象

public static SingletonTwo getInstance() {

if(instance == null)

instance = new SingletonTwo();

return instance;

}

}

80c52c0d384c?utm_campaign=maleskine&utm_content=note&utm_medium=seo_notes&utm_source=recommendation

image.png

六、多态

封装和继承都是为多态准备的,是最核心也是最重要的概念。

多态的必要条件:

1、继承

2、重写

3、父类引用指向子类对象

向上转型

package com.alan.test;

import com.alan.animal.Animal;

import com.alan.animal.Cat;

import com.alan.animal.Dog;

public class Test {

public static void main(String[] args) {

Animal one = new Animal();

/* 向上转型、隐式转型、自动转型

父类引用指向子类的对象,可以调用子类重写父类的方法,以及父类派生的方法,无法调用子类独有方法

小类转型为大类

*/

Animal two = new Cat();

Animal three = new Dog();

one.eat();

two.eat();

three.eat();

}

}

向下转型

package com.alan.test;

import com.alan.animal.Animal;

import com.alan.animal.Cat;

import com.alan.animal.Dog;

public class Test {

public static void main(String[] args) {

Animal one = new Animal();

/* 向上转型、隐式转型、自动转型

父类引用指向子类的对象,可以调用子类重写父类的方法,以及父类派生的方法,无法调用子类独有方法

小类转型为大类

*/

Animal two = new Cat();

Animal three = new Dog();

one.eat();

two.eat();

three.eat();

System.out.println("============================");

/*向下转型、强制类型转换

* 子类引用指向父类对象、此处必须进行强转,可以调用子类特有的方法

* 必须满足转换条件才能转换

* */

Cat temp = (Cat)two;

temp.eat();

temp.run();

}

}

抽象类

抽象类不允许实例化,可以通过向上转型,指向子类实例

80c52c0d384c?utm_campaign=maleskine&utm_content=note&utm_medium=seo_notes&utm_source=recommendation

image.png

抽象方法

不允许包含方法体;子类中需要重写父类的抽象方法。否则,子类也要设置为抽象类。

包含抽象方法的类一定是抽象类。

抽象类可以没有抽象方法。

接口

package com.alan.tel;

/**

* 具有上网功能的接口

* @author alan

*

*/

//接口可以设置的访问修饰符:public 默认

public interface INet {

//接口中抽象方法可以不写abstract关键字,访问修饰符默认为public

public void network();

//default:默认方法 可以带方法体 jdk1.8之后新增的方法

//可以在实现类中重写,并可以通过接口的引用调用

default public void connection() {

System.out.println("我是接口中的默认方法");

}

//static:静态方法 可以带方法体 jdk1.8之后新增的方法

//不可以在实现类中重写,可以通过接口调用

static void stop() {

System.out.println("我是接口中的静态方法");

}

//接口中可以包含常量,默认会自动加上public final static

int TEMP =20;

}

一个类可以实现多个接口

继承的父类和实现的接口中有同名方法,默认是实现父类中的同名方法。

继承的父类的属性和接口中的常量同名,编译器无法分辨,会报错。

接口也可以实现继承关系,并且可以继承多个父接口

内部类

在Java中,可以将一个类定义在另一个类里面或者一个方法里面,这样的类称为内部类。

与之对应,包含内部类的类叫外部类。

分为:1、成员内部类 2、静态内部类 3、方法内部类 4、匿名内部类

成员内部类

package com.alan.people;

//外部类

public class Person {

int age;

public Heart getHeart() {

return new Heart();

}

//成员内部类

/*

* 1、内部类在外部使用时,无法直接实例化,需要借由外部类信息才能完成实例化

* 2、内部类的访问修饰符,可以任意,但是访问范围会受到影响

* 3、内部类可以直接访问外部类的成员;如果出现同名属性,优先访问内部类中的定义

* 4、可以使用外部类.this.成员方式,访问外部类中的同名信息

* 5、外部类访问内部类信息,需要通过内部类实例,无法直接访问。

* 6、内部类编译后.class文件命名:外部类$内部类.class

* */

class Heart{

public String beat() {

return "心脏在跳动";

}

}

}

package com.alan.people;

public class PersonTest {

public static void main(String[] args) {

// TODO Auto-generated method stub

Person lili = new Person();

//获取内部类对象实例,方式1:new 外部类. new 内部类

Person.Heart myheart = new Person().new Heart();

System.out.println(myheart.beat());

//获取内部类对象实例,方式2:外部类对象.new 内部类

myheart = lili.new Heart();

System.out.println(myheart.beat());

//获取内部类对象实例,方式3:外部类调用方法返回内部类

myheart = lili.getHeart();

System.out.println(myheart.beat());

}

}

静态内部类

有static修饰,静态内部类对象可以不依赖于外部对象,直接创建。

方法内部类

80c52c0d384c?utm_campaign=maleskine&utm_content=note&utm_medium=seo_notes&utm_source=recommendation

image.png

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值