By Kevin Song
面向对象的四个基本特征
- 封装
- 继承
- 抽象
- 多态
类:事物的描述
对象:该类事物的实例
描述汽车
class Car {
int num;//成员变量
String color; //成员变量
void run() { //成员方法
System.out.println(num+"..."+color);
}
}
class CarDemo {
public static void main(String[ args[]) {
Car c = new Car();//c是一个类类型的引用变量,指向了该类的对象。
c.num = 4;
c.color = "Red";
c.run();
}
}
成员变量和局部变量的区别
类类型参数使用
//骑车改装厂
public static void show(Car c) { //类类型的变量一定指向对象,要不就是null。
c.num = 3;
c.color = "black";
System.out.println(c.num+“...”+c.color);
}
匿名对象:当对象对方法仅调用一次,就可以简化成匿名对象
new Car();//定义对象的简写格式
new Car().run();
隐藏对象的属性和实现细节,仅对外提供公共访问方式。
class Person {
private int age; //私有:只在本类中有效,外部无法访问
public void setAge(int a) {
if (a>0 && a<130)
age = a;
else
System.out.println("数据错误");
}
void speak() {
System.out.println("age="+age);
}
}
clasee PersonDemo {
public static void main(String[] args) {
Person p = new Person();
p.setAge(20);
p.speak();
}
}
构造对象的时候用的方法
特点:
作用:
给单一对象进行初始化
默认构造方法:
一个类中如果没有定义过构造方法,那么该类中会有一个默认的空参数构造方法。
class Person {
private int age;
private String name;//私有:只在本类中有效,外部无法访问
//定义一个Person类的构造方法
Person() {
Syetem.out.println("person run");
}
//初始化就有名字
Person(String n) {
name = n;
}
//初始化就有名字和年龄
Person(String n, int a) {
name = n;
age = a;
}
void speak() {
System.out.println("age="+age);
}
}
clasee PersonDemo {
public static void main(String[] args) {
Person p = new Person();//构造方法:构建创造对象时用的方法
Person p1= new Person("就很舒服");//重载构造方法
Person p2= new Person("就很舒服",10)//重载构造方法
}
}
构造方法和一般方法的区别:
当成员变量和局部变量重名,可以用关键字this区分
class Person {
private int age;
private String name;//私有:只在本类中有效,外部无法访问
//定义一个Person类的构造方法
Person(String name) {
this.name = name;//this代表当前对象
}
void speak() {
System.out.println("age="+age);
}
}
this关键字细节:
Person(String name) {
this.name = name;
}
Person(String name, int age) {
this(name);//必须放在构造方法第一行
this.age = age;
}
成员变量和静态变量的区别:
String name;
static String country = "CN";
static注意事项
主方法解析
public static void main(String[] args)
static关键字使用场合
特点:随着类的加载而执行。而且只执行一次
作用:给类初始化
class StaticCode {
static {
System.out.println("haha");
}
}
{//构造代码块。可以给所有对象进行初始化
System.out.println("Person run");
}
class ArraryToolDemo {
public static void main(String[] args) {
int[] arr = {3,5,7,72,6};
int max = ArrayTool.getIndex(arr,10);//静态方法可以直接被类名调用,不需要创建对象,节约内存空间
System.out.println("max="+max);
}
}
/**
建立一个用于操作数组的工具类,期中包含着对数组常见的操作
@author Kevin Song
@version V1.0
*/
class ArrayTool {
private ArrayTool() {}//该类中的方法都是静态的,所以该类不需要创建对象,为了保证不让其他人创建该类对象可以将构造方法私有化
/**
获取整形数组的最大值
@param arr 接收一个元素为int类型的数组
@return 该数组的最大的元素值
*/
public static int getMax(int[] arr) {
int max = arr[0];
for (int x =1; xif (arr[x]>max)
max = arr[x];
}
return max;
}
}
作用:可以保证一个类在内存中的对象是唯一的
实现思想:
步骤:
//通过在类中创建一个对象供其他程序使用
//不允许其他程序自己new对象
//对该类对象的修改都是对同一个对象的修改
//饿汉式
class Single {//类一加载,对象就已经建立
private static Single s = new Single();
private Single(){}//私有构造方法不允许其他程序new对象
public static Single getInstance() {
return s;
}
}
//懒汉式
class Single2 {//只有调用了getInstance方法才会建立对象
private static Single2 s = null;
private Single2() {}//私有构造方法不允许其他程序new对象
public static Single2 getInstance() {
if(s==null)
s = new Single();
return s;
}
}
class SingleDemo {
public static void main(String[] args) {
Single s = Single.getInstance();
}
}
从已有的类中派生出新的类,新的类能吸收已有类的数据属性和行为,并能扩展新的能力。
class Person {
String name;
int age;
}
//继承Person类的数据
class Student extends Person {
void study() {
System.out.println(name+"..student study.."+age);
}
}
//继承Person类的数据
class Worker extends Person {
void work() {
System.out.println(name+"..worker work.."+age);
}
}
class ExtendsDemo {
public static void main(String[] args) {
Student s = new Student();
s.name = "Kevin";
s.age = 24;
s.study;
}
}
继承的优点:
Java中继承的特点:
Java中支持单继承。不直接支持多继承,但对C++中的多继承机制进行改良
java支持多层(多重)继承
1. 成员变量
原理:
class Fu {
private int num = 4;//子类不能直接访问父类中的私有内容
//子类可以通过父类提供的方法间接访问父类中的私有内容
public int getNum() {
return num;
}
}
class Zi extends Fu {
private int num = 5;
void show() {
System.out.println(this.num+"....."+super.getNum());
}
}
class ExtendsDemo2 {
public static void main(String[] args) {
Zi z = new Zi();
z.show();
}
}
2. 成员方法
方法的两个特性:
重写注意事项:
class Fu {
void show() {
System.out.println("fu show run");
}
}
class Zi extends Fu {
void show() { //重写父类方法
System.out.println("zi show run");
super.show();
}
}
class ExtendsDemo3 {
public static void main(String[] args) {
Zi z = new Zi();
z.show();
}
}
3. 构造方法
子类构造对象时,访问子类构造方法时,父类构造方法也会运行。
原因:在子类的构造方法中第一行有一个默认的隐式语句。super();
子类的实例化过程:子类中所有的构造方法默认都会访问父类中的空参数的构造方法
原因:子类继承父类,获取了父类中内容,需要了解父类是如何对内容进行初始化的。
如果父类中没有定义空参数构造方法,子类的构造方法必须在第一行用super明确要调用父类中哪个构造方法。同时子类构方法数中如果使用this调用了本类构造方法时,super就没有了,因为super和this都只能定义在第一行。
class Fu {
Fu() {
System.out.println("A fu run");
}
Fu(int x) {
System.out.println("B fu run");
}
}
class Zi extends Fu {
Zi() {
//super();隐式语句,调用父类中空参数的构造方法
System.out.println("C zi run");
}
Zi(int x) {
//super();隐式语句,调用父类中空参数的构造方法
System.out.println("D zi run");
}
}
class ExtendsDemo4 {
public static void main(String[] args) {
new Zi(6);//输出结果A D
}
}
一个对象实例化过程
Person p = new Person();
对象的初始化过程:
class Fu {
Fu() {
System.out,println("fu constructor run");
show();
}
void show() {
System.out.println("hehe");
}
}
class Zi extends Fu {
int num = 9;
{ //第五步 构造代码快初始化
System.out.println("constructor code..."+num);
}
Zi() { //第一步
super; //第二步
//第四步 显示初始化
System.out.println("zi constructor..."+ num); //第六步
}
void show() { //第三步
System.out.println("show..."+num);
}
}
class Fu { //final修饰的类不可以被继承
void method() { //final修饰的方法不可以被重写
//调用底层系统资源
}
}
class Zi extends Fu {
void method() {
public static final double MY_PI = 3.14; //final修饰的变量是一个常量,只能被赋值一次
System.out.println(MY_PI);
}
}
class FinalDemo {
public static void main(String[] args) {
System.out.println("Hello World");
}
}
常量命名规则:
全部大写,不同单词之间用_分隔。例:MY_PI
全局变量:public static修饰的变量
public static int num = 9;
全局常量:public static final修饰的变量
public static final double MY_PI = 3.14;
当一个类描述一个事物时,没有足够的信息描述事物,就是抽象类
abstract class Pet { //含有抽象方法的类是抽象类
abstract void voice();//抽象修饰的方法
}
class Dog extends Pet{
void voice() {
System.out.println("woof")
}
}
class Cat extends Pet{
void voice() {
System.out.println("meow")
}
}
class AbstractDemo {
public static void main(String[] args) {
System.out.println("Hello World");
}
}
抽象类特点:
抽象类细节:
示例:
/*
员工:
属性:姓名,工号,薪水
行为:工作。
程序员:
属性:姓名,工号,薪水。
行为:工作。
经理:
属性:姓名,工号,薪水,奖金。
行为:工作。
*/
abstract class Employee {
private String name;
private String id;
private double pay;
Employee(String name, String id, double pay) {
this name = name;
this id = id;
this pay = pay;
}
public abstract void work(); //没有方法体的抽象方法
}
class Programmer extends Employee { //描述程序员
Programmer(String name, String id, double pay) {
super(name, id, pay);
}
public void work() { //加入方法体,重写父类方法
System.out.println("programming");
}
}
class Manager extends Employee { //描述经理
Manager(String name, String id, double pay, int bonus) {
super(name, id, pay);
this.bonus = bonus;
}
public void work() { //加入方法体,重写父类方法
System.out.println("managing");
}
}
class AbstractTest {
public static void main(String[] args) {
System.out.println("Hello World");
Programmer Kevin = new Programmer(Kevin, 1110009945, 7330);
}
}
interface {}
抽象类中的方法都是抽象的抽象类就可以定义为接口
接口中的成员都是公共权限:
public static final int NUM = 3;
public abstract void show(); //返回值类型void可以改变
接口不可以实例化
只能由实现了接口的子类重写了接口中所有的方法后,该子类才可以实例化,否则这个子类是一个抽象类
interface Demo {
public static final int NUM = 3; //全局常量
public abstract void show1(); //抽象方法
}
class DemoImp1 implements Demo {
public static final int NUM = 3;
public abstract void show1(){}
}
class InterfaceDemo {
public static void main(String[] args) {
DemoImp1 d = new DemoImp1();
System.out.println(d.NUM);
System.out.println(DemoImp1.NUM);
System.out.println(Demo.NUM);
}
接口多实现
接口的方法前修饰符是固定的都是public abstract 返回值类型,因此只要两个接口中的方法名相同,多实现不会存在不确定性
interface A {
public void show();
}
interface B {
public void show();
}
class Test implements A, Z {
public void show(){} //接口都是抽象方法,不存在不确定性,因此可以多实现
}
一个类实现另一个类的同时,还可以实现多个接口,避免了单继承的局限性
class Test2 extends Q implements A,Z {}
相同点:都是向上抽取而来
不同点:
与子类的关系:
方法的定义:
性质
示例:
//Dog Classification: GuideDog, DetectDog
abstract class Dog {
abstract void bark();
}
interface Guide {
abstract void guide();
}
class GuideDog extends Dog implement Guide{
public void bark() {}
public void guide() {}
}
接口的应用
/*
Laptop Usage
为了扩展笔记本的功能,定义一个规则,以后不论什么设备只要符合这个规则就可以使用
*/
interface USB {
public void open();
public void close();
}
//一年后,出现了U盘和鼠标
//实现规则
class Udisk implement USB {
public void open() {
System.out.println("Udisk Open");
}
public void open() {
System.out.println("Udisk Open");
}
}
class UsbMouse implement USB {
public void open() {
System.out.println("UsbMouse Open");
}
public void open() {
System.out.println("UsbMouse Open");
}
}
class Laptop {
public static void main(String[] args) {
useUSB(new Udisk());
useUSB(new UsbMouse());
}
//使用规则
public static void useUSB(USB u) { //接口类型的引用,用于指向接口的子类对象
u.open();
u.close();
}
}
定义:某一类事物的多种存在形态
体现:父类或者接口的引用指向其子类的对象
Fu z = new Zi();
多态优缺点
多态的前提
/*
狗具备狗形态,也具备动物形态
猫具备猫形态,也具备动物形态
*/
abstract class Animal {
abstract void eat();
}
class Dog extends Animal {
void eat() {
System.out.println("eat bone");
}
void housekeep() {
System.out.println("house keeping");
}
}
class Cat extends Animal {
void eat() {
System.out.println("eat fish");
}
void catchMouse() {
System.out.println("catching mouse");
}
}
class DuoTaiDemo {
public static void main(String[] args) {
Animal c = new Cat();//父类引用指向子类对象
Animal d = new Dog();//父类引用指向子类对象
method(c);
method(d);
public static void method(Animal a) {
a.eat(); //Animal父类特有内容可以直接调用
if(a instanceof Cat) { //判断对象是否为猫类,如果是
Cat c = (Cat)a; //转换成猫类
c.catchMouse(); //调用猫类特有方法
} else if(a instanceof Dog) { //判断对象是否为狗类,如果是
Dog d = (Dog)a; //转换成狗类
d.housekeep(); //调用狗类特有方法
}
}
}
转型
父类引用指向子类对象时,对象只能访问子父类共有内容。
Animal c = new Cat();//向上转型,猫对象提升到动物类型
c.eat();//只能访问共有功能,不能访问特有功能
Cat c = (Cat)a;//向下转型,猫对象降低到猫类
c.catchMouse//可以访问特有功能
类型判断
instanceof:用于判断对象的具体类型。只能用于引用数据类型判断
public static void method(Animal a) {
a.eat(); //Animal父类特有内容可以直接调用
if(a instanceof Cat) { //判断对象是否为猫类,如果是
Cat c = (Cat)a; //转换成猫类
c.catchMouse(); //调用猫类特有方法
} else if(a instanceof Dog) {
Dog d = (Dog)a;
d.housekeep();
}
}
成员变量
示例:
class Fu {
int num = 3;//如果父类没有num,则编译失败
}
class Zi extends Fu {
int num = 5;
}
class DuoTaiDemo {
public static void main(String[] args) {
Fu f = new Zi();
System.out.println(f.num);// 输出3
}
}
成员方法
写程序时只能调用父类的方法,实际运行时调用的是子类重写父类后的方法。
class Fu {
void show() {
System.put.println("fu show");
}
}
class Zi extends Fu {
void show() {
System.put.println("zi show");
}
}
class DuoTaiDemo {
public static void main(String[] args) {
Fu f = new Zi();
f.show();//输出"zi show"
}
}
静态方法
其实对于静态方法,是不需要对象的,可以直接被类名调用
class Fu {
static void method() {
System.put.println("fu static");
}
}
class Zi extends Fu {
static void method() {
System.out.println("zi static");
}
}
class DuoTaiDemo {
public static void main(String[] args) {
Fu f = new Zi();
f.method();//输出"fu static"
}
}
定义在一个类内部的类,又称为内置类,嵌套类
内部类访问特点:
class Outer {
private int num = 3; //内部类可以直接访问私有内容
static class Inner { //内部类
void show() {
System.out.println("show run.."+num);
}
//如果内部类中方法是静态的,则内部类也是静态的
static void staticShow() { //静态直接调用,不需要对象
System.out.println("staticShow run.."+num);
}
}
//外部类需要创建内部类对象才能访问非静态内部类内容
public void method() {
Inner in = new Inner();
in.show();
}
}
class InnerClassDemo {
public static void main(String[] args) {
//直接访问外部类的成员
Outer out = new Outer();
o.method;
//直接访问外部类中的内部类中的成员
Outer.Inner in = new Outer().new Inner();
in.show();
//如果内部类是静态的,相当于一个外部类
Outer.Inner in = new Outer.Inner();
in.show();
//如果内部类是静态的,成员也是静态的,直接调用,不需要对象
Outer.Inner.staticShow();
}
}
内部类可以存放在局部位置上
内部类在局部位置上只能访问局部中被final修饰的变量
class Outer {
int num = 3;
void method() {
final int x = 9; //内部类中访问的局部变量必须是final
class Inner {
void show() {
System.out.println("show..."+x);
}
Inner in = new Inner();
in.show();
}
}
}
内部类的简写格式
new 父类or接口() {
子类内容;
}
前提:内部类必须继承一个外部类,或者实现一个接口
匿名内部类其实就是一个子类对象
abstract class Demo {
abstract void show();
}
class Outer {
int num = 4;
//匿名内部类不能有名字,所以不能这样定义
//class Inner extends Demo {
// void show() {
// System.out.println("show..."+num);
// }
//}
public void method() {
//相当于 new Inner().show();
new Demo() { //创建匿名内部类
void show() { //重写Demo抽象方法
System.out.println("show..."+num);
}
}.show();
}
}
class InnerClassDemo {
public static void main(String[] args) {
new Outer().method();
}
}
匿名内部类应用
当方法参数是接口类型时,而且接口中的方法不超过三个,可以用匿名内部类作为实际参数进行传递
interface Inter {
void show1();
void show2();
}
class Outer {
//class Inner implements Inter {
// public void show1() {}
// public void show2() {}
//}
public void method() {
// Inner in = new Inner();
// in.show1();
// in.show2();
Inter in = new Inter() { //重写接口方法,创建匿名内部类对象
public void show1() {}
public void show2() {}
}
in.show1;
in.show2;
}
}
异常:运行时发生的不正常情况,根据面向对象的思想被java封装成了对象
异常类:在java中用类的形式对不正常的情况进行了描述和封装对象,描述不正常的情况的类,就称为异常类。
class ExceptionDemo {
public static void main(Stirng[] args) {
int[] arr = new int[3];
arr = null;
System.out.println(arr[3]);
}
public static void sleep(int time) {
if(time < 0) {
//抛出一个对象
new FuTime();//新建一个负time对象,这个对象中包含问题的名称,信息,位置等信息
}
if (time > 100000) {
//抛出一个对象
new BigTime();
}
}
}
不正常的情况分成两类
Throwable(可抛出):可以被throws和throw两个关键字操作的类和对象都具备可抛性
该体系的特点:子类的后缀名都是用其父类名作为后缀
ArrayIndexOutOfBoundsException
自动抛出异常
//自动抛出异常:
class Demo {
public void method(int[] arr, int index) {
//JVM在这里封装了一个对象然后丢出:throw new ArrayIndexOutOfBoundsException(index)
System.out.println(arr[index]);
}
}
class ExceptionDemo {
public static void main(Stirng[] args) {
int[] arr = new int[3];
Demo d = new Demo();
d.method(arr,3);
}
}
手动抛出异常:
自定义异常:java中没有定义过的异常,按照java异常的创建思想和面向对象的思想,对异常进行自定义描述,并封装成对象。
自定义异常类:自定义异常类必须继承异常体系,因为只有称为异常体系的子类才具有可抛性,才可以被throw,throws操作。要么继承Exception,要么继承RuntimeException
throw:异常抛出的关键字
throws:声明自定义异常类的关键字
throws和throw的区别
Exception类的所有子类中分为两种
异常声明
只声明,不处理的异常,无法通过编译,可以自定义报错信息
//手动抛出异常
/*
角标为负的异常在java中没有定义过,需要自定义
*/
class FuShuIndexException extends Exception {
FuShuIndexException() {}//空参数构造方法
FuShuIndexException(String msg) {
super(msg);//直接调用父类构造方法
}
}
class Demooo {
//创建自定义异常类对象的方法需要用throws声明自定义异常
public int method(int[] arr, int index) throws FuShuIndexException {
if(index>=arr.length) {
//手动抛出异常
throw new ArrayIndexOutOfBoundsException("数组角标越界"+index);
} else if(index<0) {
throw new FuShuIndexException("数组角标不能是负数"+index);
}
return arr[index];
}
}
class ExceptionDemo {
//有自定义异常的主方法需要用throws声明自定义异常
public static void main(String[] args) throws FuShuIndexException {
int[] arr = new int[3];
Demooo d = new Demooo();
d.method(arr,3);
}
}
异常捕捉
try-catch处理完程序可以继续运行
try {
需要被检测异常的代码
}
catch(FuShuIndexException e) {
处理异常的代码
}
catch(Exception e) { //多个catch,父类catch一定要放在后面
处理异常的代码
}
finally {
一定会被执行的代码
}
try-catch-finally代码块特点:
class FuShuIndexException extends Exception {
FuShuIndexException() {}//空参数构造方法
FuShuIndexException(String msg) {
super(msg);//直接调用父类构造方法
}
}
class Demoo {
public int method(int[] arr, int index) throws FuShuIndexException {
if(index<0) {
throw new FuShuIndexException("Index must be positive");
}
return arr[index];
}
}
class ExceptionDemo {
public static void main(String[] args) {
int[] arr = new int[3];
Demoo d = new Demoo();
try {
int num = d.method(arr, -3);
System.out.println("num=" + num);
} catch (FuShuIndexException e) {
//FuShuIndexException e = new FuShuIndexException("Index must be positive")
//获得自定义的异常提示信息
System.out.println("Message:"+e.getMessage());
//获得字符串形式的自定义异常类信息
System.out.println("String:"+e.toString());
//获得出现异常的代码位置
e.printStackTrace();
System.out.println("负数角标异常");
}
System.out.println("over");
}
}
/*
输出:
Message:Index must be positive
FuShuIndexException: Index must be positive
String:FuShuIndexException: Index must be positive
at Demoo.method(ExceptionDemo.java:10)
负数角标异常
at ExceptionDemo.main(ExceptionDemo.java:20)
over
*/
异常处理的原则:
finally代码块
通常用于关闭(释放)资源,比如关闭数据库连接
class Demo {
public void show(int index) throws ArrayIndexOutOfBoundsException :
if(index < 0)
throw new ArrayIndexOutOfBoundsException("越界");
int[] arr = new int[3];
return arr[index];
}
}
class ExceptionDemo {
public static void main(String[] args) {
Demo d = new Demo();
try {
int num = d.show(-3);
System.out.println("num"+num);
} catch (ArrayIndexOutOfBoundsException e) {
System.out.println(e.toString());
//return; 如果加了return;则不会运行over
//System.exit(o);如果加了这句,则不会运行finally代码块,直接退出JVM
} finally { //一定会被执行,除非System.exit(0);退出JVM
System.out.println("finally");
}
System.out.println("over");
}
}
//自定义蓝屏异常类
class BlueScreenException extends Exception {
BlueScreenException(String msg) {
Super(msg);
}
}
//自定义冒烟异常类
class MaoYanException extends Exception {
MaoYanException(String msg) {
Super(msg);
}
}
//自定义无法处理异常类
class NoPlanException extends Exception {
NoPlanException(String msg) {
Super(msg);
}
}
class Computer {
private int state = 0;
//定义电脑运行功能
public void run() throws BlueScreenException, MaoYanException {
if(state == 1) { //状态值为1时电脑蓝屏
throw new BlueScreenException("蓝屏");
} else if(state == 2)
throw new MaoYanException("冒烟");
System.out.println("电脑运行");
}
//定义电脑重启功能
public void reboot() {
state = 0; //重置电脑到正常状态
System.out.println("重启");
}
}
class Teacher {
private String name;
private Computer comp;
Teacher(String name) {
this.name = name;
}
public void teach() throws NoPlanException {
try {
comp.run(); //电脑运行
System.out.println("讲课"); //正常讲课
} catch (BlueScreenException e) {
System.out.println(e.toString());
comp.reset();
teach();
} catch (MaoYanException e) {
System.out.println(e.toString());
test();
//异常转换:收到冒烟异常,转换成NoPlan异常对外进行告知
throw new NoPlanException("课时进度无法完成");
}
}
public void test() {
System.out.println("大家练习");
}
}
class ExceptionTest {
public static void main(String[] args) {
Teacher t = new Teacher("Kevin");
try (
t.teach();
) catch(NoPlanException e) {
System.out.println(e.toString()+"...");
System.out.println("换老师");
}
}
}
异常的注意事项:
Object类是所有类的根类,是不断抽取而来,具备所有对象都具备的共性内容
equals方法
当两个引用值指向同一个对象时才返回true
class Person extends Object {
private int age;
Person(int age) {
this.age = age;
}
}
Class EqualsDemo {
public static void main(String[] args) {
Person p1 = new Person();
Person p2 = new Person();
Person p3 = p1;
System.out.println(p1 == p2);//false
System.out.println(p1.equals(p2));//false
System.out.println(p1.equals(p3));//true
}
}
equals方法重写
equals方法一般都会被重写,根据对象的特有内容,建立判断对象是否相同的依据
class Person extends Object {
private int age;
Person(int age) {
this.age = age;
}
public boolean equals(Object obj) {//重写Object类中的equals方法,进行对象年龄比较
if(!(obj instanceof Person)) {
return false;
throw new ClassCastException("类型错误");
}
Person p = (Person)obj;
return this.age == p.age;
}
}
Class EqualsDemo {
public static void main(String[] args) {
Person p1 = new Person(20);
Person p2 = new Person(20);
System.out.println(p1 == p2);//false
System.out.println(p1.equals(p2));//true
System.out.println(p1.equals(new Demo()));//报错,类型错误
}
}
hashCode方法
判断两个对象是否完全相同
class Person extends Object {
private int age;
Person(int age) {
this.age = age;
}
public int hashCode() { //重写object类中的hashCode方法,输出年龄
return age;
}
}
Class EqualsDemo {
public static void main(String[] args) {
Person p1 = new Person(20);
Person p2 = new Person(20);
System.out.println(p1);//输出p1的哈希值
System.out.println(p1.hashCode());//输出p1的哈希值
System.out.println(Integer.toHexString(p1.hashCode()));//输出p1的十六进制哈希值
}
}
getClass方法
获取当前对象所属字节码对象
Class clazz1 = p1.getClass();
Class clazz1 = p2.getClass();
System.out.println(clazz1 == clazz2);//true
System.out.println(clazz1.getNma());//Person
toString方法
返回对象的字符串表示形式,它的值等于:
getClass().getNmae() + '@' + Integer.toHexString(hashCode())
建议重写该方法
public String toString() {
return "Person: " + age;
}
System.out.println(p1);//Person: 20
System.out.println(p1.getClass().getNmae() + '@' + Integer.toHexString(hashCode()));////Person@61de33
对类文件进行分类管理
package allpack.boypack.mypack;
class PackageDemo {
public static void main(String[] args) {
System.out.println("Hello Package!");
}
}
//javac -d . PackageDemo.java
//java mypack.PackageDemo
包与包之间的类进行访问,被访问的包中的类必须是public的,被访问的包中的类的方法也必须是public
package packa;
public class DemoA { //包与包之间访问必须是public
public void show() //包与包之间访问必须是public{
System.out.println("demoa show run");
}
}
package packb;
public class DemoA { //包与包之间访问必须是public
protected void method() { //protected只能被继承了父类的访问
System.out.println("demoa show run");
}
}
package mypack;
class PackageDemo {
public static void main(String[] args) {
packa.DemoA d = new packa DemoA();
d.show();
System.out.println("Hello Package!");
}
}
位置 | public | protected | default | private |
---|---|---|---|---|
同一类中 | ok | ok | ok | ok |
同一包中 | ok | ok | ok | |
子类中 | ok | ok | ||
不同包中 | ok |
导入import
package packa;
public class DemoA { //包与包之间访问必须是public
public void show() //包与包之间访问必须是public{
System.out.println("demoa show run");
}
}
package packb;
public class DemoA { //包与包之间访问必须是public
protected void method() {
System.out.println("demoa show run");
}
}
package mypack;
import packa.*//导入了packa包中所有的类
class PackageDemo {
public static void main(String[] args) {
packa.DemoA d = new packa DemoA();
d.show();
System.out.println("Hello Package!");
}
}
Jar包
Java的压缩包