继承性严格来讲就是扩充一个类已有的功能。
继承的基本实现
// An highlighted block
class Person{
private String name;
private int age;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
}
class Student extends Person{
}
public class Demo {
public static void main(String[] args) {
Student stu = new Student();
stu.setName("张三");
stu.setAge(20);
System.out.println("姓名:"+stu.getName()+",年龄:"+stu.getAge());
}
}
执行结果:姓名:张三,年龄:20
在子类中扩充方法
// An highlighted block
class Person{
private String name;
private int age;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
}
class Student extends Person{
private String school;
public String getSchool() {
return school;
}
public void setSchool(String school) {
this.school = school;
}
}
public class Demo {
public static void main(String[] args) {
Student stu = new Student();
stu.setName("张三");
stu.setAge(20);
stu.setSchool("山东大学");
System.out.println("姓名:"+stu.getName()+",年龄:"+stu.getAge()+",学校:"+stu.getSchool());
}
}
执行结果:姓名:张三,年龄:20,学校:山东大学
限制一:Java不允许多重继承,但是允许多层继承
// An highlighted block
错误示例:
class A{
}
class B{
}
class C extends A,B {
}
// An highlighted block
多层继承
class A{
}
class B extends A {
}
class C extends B {
}
限制二:子类在继承父类时,严格来讲会继承父类中的全部操作,但是对于所有私有操作属于隐式继承,而所有的非私有操作属于显式继承。
// An highlighted block
class A{
private String msg;
public String getMsg() {
return msg;
}
public void setMsg(String msg) {
this.msg = msg;
}
}
class B extends A{
}
public class Demo {
public static void main(String[] args) {
B b = new B();
b.setMsg("张三");
System.out.println(b.getMsg());
}
}
执行结果:张三
限制三:在子类对象构造前一定会默认调用父类的构造(默认使用无参构造),以保证父类的对象先实例化,子类对象后实例化。
// An highlighted block
class A{
public A() {
System.out.println("A类构造方法");
}
}
class B extends A{
public B() {
System.out.println("B类构造方法");
}
}
public class Demo {
public static void main(String[] args) {
new B();
}
}
执行结果:A类构造方法
B类构造方法
上面代码虽然实例化的是子类对象,但是发现它会默认先执行父类构造,调用父类构造的方法体执行,再实例化子类对象并且调用子类的构造方法。对于子类的构造而言,就相当于隐含了super()的语句调用,由于super()主要调用父类的构造方法,所以必须放在子类构造方法的首行。
子类隐含语句
// An highlighted block
class B extends A{
public B() {
super(); //父类中有无参构造时,加与不加无区别,如果编写则必须出现在首行
System.out.println("B类构造方法");
}
}
父类不提供无参构造方法
// An highlighted block
class A{
public A(String title) {
//父类提供的有参构造方法
System.out.println("A类构造方法,title="+title);
}
}
class B extends A{
public B(String title) {
//子类提供有参构造
super(title); //明确调用父类构造,否则将出现编译错误
System.out.println("B类构造方法");
}
}
public class Demo {
public static void main(String[] args) {
new B("hello");
}
}
执行结果:A类构造方法,title=hello
B类构造方法
没有实现方法覆写
// An highlighted block
class A{
public void fun(){
System.out.println("A类中的fun()方法");
}
}
class B extends A{
}
public class Demo {
public static void main(String[] args) {
new B().fun();
}
}
执行结果:A类中的fun()方法
实现方法覆写
// An highlighted block
class A{
public void fun(){
System.out.println("A类中的fun()方法");
}
}
class B extends A{
@Override
public void fun() {
System.out.println("B类中的fun()方法");
}
}
public class Demo {
public static void main(String[] args) {
new B().fun();
}
}
执行结果:B类中的fun()方法
定义更多的子类
// An highlighted block
class A{
public void fun(){
System.out.println("A类中的fun()方法");
}
}
class B extends A{
@Override
public void fun() {
System.out.println("B类中的fun()方法");
}
}
class C extends A{
@Override
public void fun() {
System.out.println("C类中的fun()方法");
}
}
public class Demo {
public static void main(String[] args) {
new B().fun();
new C().fun();
}
}
执行结果:B类中的fun()方法
C类中的fun()方法
覆写权限问题:被子类覆写的方法不能拥有比父类更严格的访问控制权限
例如:如果父类的方法是default(默认),那么子类覆写方法时候只能使用default或者public,注意pirvate的方法不能被覆写。
// An highlighted block
class A{
void fun(){
System.out.println("A类中的fun()方法");
}
}
class B extends A{
@Override
public void fun() {
//此时子类中的方法权限与父类相比更加宽松
System.out.println("B类中的fun()方法");
}
}
利用super()方法访问父类中的方法
// An highlighted block
class A{
void fun(){
System.out.println("A类中的fun()方法");
}
}
class B extends A{
@Override
void fun() {
super.fun();
}
}
public class Demo {
public static void main(String[] args) {
new B().fun();
}
}
执行结果:A类中的fun()方法
如果子类定义了和父类完全相同的属性名称时,就称位属性的覆盖。
// An highlighted block
class A{
String info = "hello";
}
class B extends A{
int info = 10; //名称相同,发生属性覆盖
void fun() {
System.out.println(super.info);
System.out.println(this.info);
System.out.println(info);
}
}
public class Demo {
public static void main(String[] args) {
new B().fun();
}
}
执行结果:hello
10
10
注意:在任何开发中,属性一般使用private封装,那么一旦封装后属性覆盖时没有任何意义的,因为父类定义的私有属性子类根本就看不见,更不会相互影响了。
this与super的区别
NO. | 区别 | this | super |
---|---|---|---|
1 | 功能 | 调用本类构造、本类方法、本类属性 | 子类调用父类构造、父类方法、父类属性 |
2 | 形式 | 先查找本类中是否存在有指定的调用结果,如果有则直接调用,如果没有则调用父类定义 | 不查找子类,直接调用父类操作 |
3 | 特殊 | 表示本类的当前对象 | – |
在开发中,对于本类或父类中的操作,强烈建议加上“this.”或者“super.”的标记,便于维护。
// An highlighted block
class Array{
private int data[];
private int foot;
public Array(int len) {
if(len > 0){
this.data = new int[len];
}else {
this.data = new int[1];
}
}
public boolean add(int num){
if(this.foot < this.data.length){
this.data[this.foot++] = num; //this.foot++的值为0
return true;
}
return false;
}
public int[] getData(){
return this.data;
}
}
public class Demo {
public static void main(String[] args) {
Array arr = new Array(3);
System.out.println(arr.add(20)+"、");
System.out.println(arr.add(10)+"、");
System.out.println(arr.add(30)+"、");
System.out.println(arr.add(100)+"、"); //不可以保存数据,返回false
int [] temp = arr.getData();
for(int x = 0; x < temp.length; x++){
System.out.print(temp[x]+"、");
}
}
}
执行结果:true、
true、
true、
false、
20、10、30、
提示:以上代码存在缺陷,存粹只是举个例子而已。
问:i++和++i的区别
// An highlighted block
public class Message {
static int num ; //初始值为0
static int sum; //初始值为0
public static void main(String[] args) {
System.out.println("sum = num++:"+num++);
System.out.println(num);
System.out.println("sum = ++num:"+(++num));
System.out.println(num);
}
}
执行结果:sum = num++:0
1
sum = ++num:2
2
由以上结果可以看出:sum = num++ 此时 sum = num(也就是0),然后num会自加1(也就是num为1)。sum = ++num ,此时,num会先自加1(也就是num 为 1),然后sum 为num自加之后的值,也就是1.
// An highlighted block
class SortArray extends Array{
public SortArray(int len){
super(len);
}
public int[] getData(){
java.util.Arrays.sort(super.getData());
return super.getData();
}
}
public class Demo {
public static void main(String[] args) {
SortArray arr = new SortArray(3);
System.out.println(arr.add(20)+"、");
System.out.println(arr.add(10)+"、");
System.out.println(arr.add(30)+"、");
System.out.println(arr.add(100)+"、"); //不可以保存数据,返回false
int [] temp = arr.getData();
for(int x = 0; x < temp.length; x++){
System.out.print(temp[x]+"、");
}
}
}
执行结果:true、true、true、false、
10、20、30、
反转类指的是进行数组数据取得时,可以实现数据的首尾交换。
// An highlighted block
class ReverseArray extends Array{
public ReverseArray(int len){
super(len);
}
public void reverse(){
int center = super.getData().length/2;
int head = 0;
int tail =super.getData().length-1;
for(int i = 0; i < center; i++) {
int temp = super.getData()[tail];
super.getData()[tail] = super.getData()[head];
super.getData()[head] = temp;
head++;
tail--;
}
}
@Override
public int[] getData() {
return super.getData();
}
}
public class Message {
public static void main(String[] args) {
ReverseArray reverseArray = new ReverseArray(5);
reverseArray.add(10);
reverseArray.add(20);
reverseArray.add(30);
reverseArray.add(40);
reverseArray.add(50);
reverseArray.reverse();
for(int i = 0 ; i < reverseArray.getData().length ; i++) {
System.out.println(reverseArray.getData()[i]);
}
}
}
执行结果:50、40、30、20、10
在Java中final称为终结器,可以使用final定义类、方法和属性。
// An highlighted block
final class A{
//此类不能够有子类
}
class B extends A{
//错误继承
}
// An highlighted block
class A{
public final void fun(){
} //此方法不允许子类覆写
}
class B extends A{
public void fun(){
} //此处不允许覆写
}
// An highlighted block
class A{
final double AA = 10.1;
public final void fun(){
AA = 1.1; //不能修改常量
}
}
全局常量指的是利用了public static final 这3个关键字联合定义的常量。例如:public static final String MSG = “hello”;
需要记住的是,在定义常量时必须对其进行初始化赋值,否则将出现语法错误。
方法的多态性:重载与覆写;
重载:同一个方法名称,根据不同的参数类型及个数可以完成不同的功能;
覆写:同一个方法,根据实例化的子类对象不同,所完成的功能也不同。
对象的多态性:父子类对象的转换。
向上转型:子类对象变为父类对象,格式:父类 父类对象 = 子类实例,自动转换;
向下转换:父类对象变为子类对象,格式:子类 子类对象 = (子类)父类实例,强制转换;
// An highlighted block
class A{
public void print(){
System.out.println("A");
}
}
class B extends A{
@Override
public void print() {
System.out.println("B");
}
}
public class TestDemo {
public static void main(String[] args) {
B b = new B();
b.print();
}
}
执行结果:B
B对象自动向上转型
// An highlighted block
public class TestDemo {
public static void main(String[] args) {
A a = new B(); //实例化的是子类对象,对象向上转型
a.print();
}
}
执行结果:B
向上转型特点:不要看类名称,而要看实例化对象的类。
对象向下转型
// An highlighted block
public class TestDemo {
public static void main(String[] args) {
A a = new B(); //实例化的是子类对象,对象向上转型
B b = (B)a; //对象需要强制性地向下转型
b.print();
}
}
执行结果:B
因为有强制性转换的操作,所以向下转型操作本身是有前提条件的,即必须发生向上转型后才可以发生向下转型。
错误的向下转型
// An highlighted block
public class TestDemo {
public static void main(String[] args) {
A a = new A();
B b = (B)a;
a.print();
}
}
执行结果:Exception in thread "main" java.lang.ClassCastException: A cannot be cast to B at TestDemo.main(TestDemo.java:16)
如果两个没有关系的类对象强制发生向下转型时会带来类转换异常。所以向下转型是会存在安全隐患的,应尽量避免。
向上转型作用分析
// An highlighted block
class A{
public void print(){
System.out.println("A");
}
}
class B extends A{
@Override
public void print() {
System.out.println("B");
}
}
class C extends A{
@Override
public void print() {
System.out.println("C");
}
}
public class TestDemo {
public static void main(String[] args) {
A a1 = new B();
A a2 = new C();
fun(a1);
fun(a2);
}
public static void fun(A a){
//方法中参数类型只能是一个可以包含B类和C类的的统一类型
a.print();
}
}
执行结果:B、C
由以上可知,向上转型的主要目的是统一调用的参数类型。
向下转型,调用子类中的特殊功能
// An highlighted block
class A{
public void print(){
System.out.println("A");
}
}
class B extends A{
@Override
public void print() {
System.out.println("B");
}
public void msg(){
System.out.println("B类中的扩充方法");
}
}
public class TestDemo {
public static void main(String[] args) {
A a = new B();
fun(a);
}
static void fun(A a){
B b = (B)a;
b.msg();
}
}
执行结果:B类中的扩充方法
instanceof关键字
instanceof关键字可以判断某一个对象是否是指定类的实例。
// An highlighted block
对象 instanceof 类 返回boolean 型 //是返回true,否则返回false
public class TestDemo {
public static void main(String[] args) {
A a = new B(); //对象向上转型
System.out.println(a instanceof A);
System.out.println(a instanceof B);
System.out.println(null instanceof A);
}
}
执行结果:true
true
false
向下转型时建议使用instanceof判断下
// An highlighted block
class A{
public void print(){
System.out.println("A");
}
}
class B extends A{
@Override
public void print() {
System.out.println("B");
}
public void msg(){
System.out.println("B类中的扩充方法");
}
}
public class TestDemo {
public static void main(String[] args) {
A a = new B(); //对象向上转型
fun(a);
}
static void fun(A a){
if(a instanceof B){
B b = (B)a;
b.msg();
}
}
}
执行结果:B类中的扩充方法
抽象类就是指在普通类的结构里面增加抽象方法的组成部分,抽象方法指的是没有方法体的方法,同时抽象方法还必须使用abstract关键字进行定义。。拥有抽象方法的类一定属于抽象类,抽象类要使用abstract声明。
定义抽象类
// An highlighted block
abstract class A{
public void print(){
System.out.println("A");
}
public abstract void fun();
}
注意:抽象类不能直接实例化对象(因为有抽象方法,但是抽象方法没有方法体,怎么可能去调用?)
使用抽象类,需要遵循一下原则:
// An highlighted block
abstract class A{
public void print(){
System.out.println("A");
}
public abstract void fun();
}
class B extends A{
@Override
public void fun() {
System.out.println("hello");
}
}
public class TestDemo {
public static void main(String[] args) {
A a = new B(); //对象向上转型
a.fun();
}
}
执行结果:hello
// An highlighted block
abstract class A{
public void print(){
System.out.println("A");
}
}
class B extends A{
}
public class TestDemo {
public static void main(String[] args) {
A a = new B(); //对象向上转型
a.print();
}
}
执行结果:A
// An highlighted block
abstract class A{
abstract class B{
public abstract void fun();
}
}
class X extends A{
public void print(){
System.out.println("访问:www.baidu.com");
}
class Y extends B{
@Override
public void fun() {
System.out.println("方法覆写");
}
}
}
public class TestDemo {
public static void main(String[] args) {
X x = new X();
x.print();
X.Y xy = x.new Y();
xy.fun();
}
}
执行结果:访问:www.baidu.com
方法覆写
// An highlighted block
abstract class A{
static abstract class B{
public abstract void fun();
}
}
class X extends A.B{
@Override
public void fun() {
System.out.println("访问:www.baidu.com");
}
}
public class TestDemo {
public static void main(String[] args) {
A.B ab = new X();
ab.fun();
}
}
执行结果:访问:www.baidu.com
// An highlighted block
abstract class A{
public static void fun(){
System.out.println("访问:www.baidu.com");
}
}
public class TestDemo {
public static void main(String[] args) {
A.fun();
}
}
执行结果:访问:www.baidu.com
隐藏抽象类子类
// An highlighted block
abstract class A{
public abstract void print();
private static class B extends A{
@Override
public void print() {
System.out.println("访问:www.baidu.com");
}
}
public static A getInstance(){
return new B();
}
}
public class TestDemo {
public static void main(String args[]){
A a = A.getInstance();
a.print();
}
}
执行结果:访问:www.baidu.com
抽象类的最主要特点相当于制约了子类必须覆写的方法,同时抽象类中也可以定义普通方法,而且最为关键的是,这些普通方法定义在抽象类时,可以直接调用类中定义的抽象方法,但是具体的抽象方法内容就必须由子类提供。
// An highlighted block
abstract class A{
public void fun(){
this.print();
}
public abstract void print();
}
class B extends A{
@Override
public void print() {
System.out.println(11);
}
}
public class TestDemo {
public static void main(String args[]){
A a = new B();
a.fun();
}
}
执行结果:11
定义一个行为类
// An highlighted block
abstract class Action{
public static final int EAT = 1;
public static final int SLEEP = 5;
public static final int WORK = 7;
public void command(int flag){
switch(flag){
case EAT:
this.eat();
break;
case SLEEP:
this.sleep();
break;
case WORK:
this.work();
break;
case EAT + WORK:
this.eat();
this.work();
break;
}
}
public abstract void eat();
public abstract void sleep();
public abstract void work();
}
定义描述机器人的行为子类
// An highlighted block
class Robot extends Action{
public void eat(){
system.out.println("机器人充电");
}
public void sleep(){
//此操作不需要但必须覆写,所以方法体为空
}
public void work(){
system.out.println("机器人在工作");
}
}
定义人的类
// An highlighted block
class Human extends Action{
public void eat(){
system.out.println("人在吃饭");
}
public void sleep(){
system.out.println("人在睡觉");
}
public void work(){
system.out.println("人在工作");
}
}
定义猪的类
// An highlighted block
class Pig extends Action{
public void eat(){
system.out.println("猪在吃食物");
}
public void sleep(){
system.out.println("猪在睡觉");
}
public void work(){
}
}
测试类
// An highlighted block
public class TestDemo {
public static void main(String args[]){
fun(new Robot());
fun(new Human());
fun(new Pig());
}
public static void fun(Action act){
act.command(Action.EAT);
act.command(Action.SLEEP);
act.command(Action.WORK);
}
}
执行结果:机器人充电
机器人在工作 (省略)...
如果一个类只是由抽象方法和全局常量组成的,那么将其定义为接口。所谓接口就是一个特殊的类,而且这个类里面只有抽象方法和全局常量。
定义接口
// An highlighted block
interface A{
public static final String MSG = "HELLO";
public abstract void print();
}
接口的简化定义
// An highlighted block
interface A{
String MSG = "HELLO";
public void fun();
}
实现接口
// An highlighted block
interface A{
String MSG = "HELLO";
public void fun();
}
interface B{
public abstract void get();
}
class X implements A,B{
public void fun(){
system.out.println("A接口的抽象方法");
}
public void get(){
system.out.println("B接口的抽象方法");
}
}
public class TestDemo{
public static void main (String args[]){
X x = new X();
A a = x;
B b = x;
a.fun();
b.get();
system.out.println(a.MSG)
}
}
执行结果:A接口的抽象方法
B接口的抽象方法
HELLO
判断类型
// An highlighted block
interface A{
String MSG = "heelo";
public void fun ();
}
interface B{
public void get();
}
class X implements A,B{
@Override
public void fun() {
}
@Override
public void get() {
System.out.println("B接口的抽象方法");
}
}
public class Main {
public static void main(String[] args) {
// write your code here
A a = new X();
B b = new X();
b.get();
System.out.println(a instanceof A);
System.out.println(b instanceof B);
}
}
执行结果:B接口的抽象方法
true
trueru
如果一个子类既要继承抽象类又要实现接口,那么应该采用先继承extends后实现接口implements的顺序完成
// An highlighted block
interface A{
public void fun ();
}
interface B{
public void get();
}
abstract class C{
public abstract void change();
}
class X extends C implements A,B{
@Override
public void fun() {
System.out.println("A接口的抽象方法");
}
@Override
public void get() {
System.out.println("B接口的抽象方法");
}
@Override
public void change() {
System.out.println("C类的抽象方法");
}
}
接口的多继承
// An highlighted block
interface A{
public void funA();
}
interface B{
public void funB();
}
interface C extends A,B{
public abstract void funC();
}
class X implements C{
@Override
public void funA() {
System.out.println("A接口的抽象方法");
}
@Override
public void funB() {
System.out.println("B接口的抽象方法");
}
@Override
public void funC() {
System.out.println("C类的抽象方法");
}
}
在定义接口C时使用extends关键字继承了两个父接口,这就相当于C接口中一共定义3个抽象方法,所以在定义X子类时必须覆写3个抽象方法。
在接口里面定义抽象类
// An highlighted block
interface A{
public void funA();
abstract class D{
public abstract void funD();
}
}
class X implements A{
@Override
public void funA() {
System.out.println("A接口的抽象方法");
}
class Y extends D{
@Override
public void funD() {
//可以选择性继承
}
}
}
如果在一个接口内部使用static去定义一个内部接口,该接口就表示是一个外部接口
// An highlighted block
interface A{
public void funA();
static interface B{
public void funB();
}
}
class X implements A.B{
@Override
public void funB() {
System.out.println("A接口的抽象方法");
}
}
在日常的生活中,人们会经常听到接口这一词,而最常见的就是USB接口。利用USB接口可以连接U盘、电脑等设备。
如果要进行代码开发,一定要首先开发处USB接口标准,因为有了标准后,计算机才可以去使用这些标准,设备厂商才可以设计USB设备。
定义USB标准
interface USB{
public void start();
public void stop();
}
定义计算机类
class Computer{
public void plugin(USB usb){
usb.start();
usb.stop();
}
}
在计算机类中提供一个plugin()方法,这个方法可以接收USB接口实例,这样不管有多少种USB设备(USB接口对应的子类)都可以插入计算机上进行工作。下面依据USB接口标准定义出两个子类。
定义U盘子类
class Flash implements USB{
public void start(){
system.out.println("U盘开始使用");
}
public void stop(){
system.out.println("U盘停止使用");
}
}
定义打印机
class Print implements USB{
public void start(){
system.out.println("打印机开始使用");
}
public void stop(){
system.out.println("打印机停止使用");
}
}
按照上述方式,可以准备几万个子类,并且这几万个子类都可以在电脑的plugin()方法上使用
测试代码
public class Main {
public static void main(String args[]) throws Exception {
Computer com = new Computer();
com.plugin(new Flash());
com.plugin(new Print());
}
}
结果:U盘开始使用
U盘停止使用
打印机开始使用
打印机停止使用
interface Fruit{
public void eat();
}
class Apple implements Fruit{
@Override
public void eat() {
System.out.println("吃苹果");
}
}
public class Main {
public static void main(String args[]) throws Exception {
Fruit f = new Apple();
f.eat();
}
}
结果:吃苹果
上述例子是一个比较熟悉的结构,但是这样的作法真的合理么?
如果要确认一个代码的编写风格是否良好,应该遵循以下两个标准。
1.客户端(现在为主方法main)调用简单,不需要关注具体的细节
2.程序代码的修改,不影响客户端的调用,即使用者可以不去关心代码是否变更。
根据以下2个标准,就可以发现本程序设计上的问题。在取得接口实例化对象时明确地指明了要使用的子类“Fruit f = new Apple()”,如果扩充了子类,客户端就需要去修改。为了解决问题,即想办法让客户端只看见接口而不让其看见子类,就需要一个中间的工具类来取得接口对象。
增加一个工厂类过渡
interface Fruit{
public void eat();
}
class Apple implements Fruit{
@Override
public void eat() {
System.out.println("吃苹果");
}
}
class Orange implements Fruit{
@Override
public void eat() {
System.out.println("吃橙子");
}
}
class Factory{
public static Fruit getInstance(String className){
if("apple".equals(className)){
return new Apple();
}else if("orange".equals(className)){
return new Orange();
}else {
return null;
}
}
}
public class Main {
public static void main(String args[]) throws Exception {
Fruit f = Factory.getInstance("orange");
f.eat();
}
}
结果:吃橙子
➢代理设计也是在java开发中使用较多的一种设计模式,所谓的代理设计就是指一个代理主 题来操作真实主题,真实主题执行具体的业务操作,而代理主题负责其他相关业务的处理,就好比在生活中经常使用到的代理上网那样,客户通过网络代理连接网络,由代理服务器完成用户权限,访问限制等与上网操作相关的操作
代理设计模式实现
interface Network{
void browse();
}
class Real implements Network{
@Override
public void browse() {
System.out.println("上网浏览信息");
}
}
class Proxy implements Network{
//代理上网
private Network network;
public Proxy(Network network){
this.network = network;
}
public void check(){
System.out.println("检查用户是否合法");
}
@Override
public void browse() {
this.check(); //调用其他相关业务操作
this.network.browse(); //调用真实上网操作
}
}
public class Main {
public static void main(String args[]) throws Exception {
Network net = null;
net = new Proxy(new Real());
net.browse();
}
}
结果:检查用户是否合法
上网浏览信息
有一种类是所有类的父类,这就是Object类。
利用Object类来接收对象
class Book{
}
public class Main {
public static void main(String args[]) throws Exception {
Object book = new Book();
}
}
class Book{
}
public class Main {
public static void main(String args[]) throws Exception {
Object book = new Book();
System.out.println(book.toString());
}
}
结果:Book@4554617c
在Object类,默认的equals()方法比较的是两个对象的内存地址信息,而不是对象内容。
class Book{
private String title;
private double price;
public Book(String title, double price) {
this.title = title;
this.price = price;
}
public boolean equals(Object obj){
if(this == obj){
//判断是不是自己
return true;
}
if(obj == null){
return false;
}
if(!(obj instanceof Book)){
return false;
}
Book book = (Book) obj;
if(this.title.equals(book.title) && this.price == book.price){
return true;
}
return false;
}
}
public class Main {
public static void main(String args[]) throws Exception {
Book book1 = new Book("aa", 79.9);
Book book2 = new Book("aa", 79.9);
System.out.println(book1.equals(book2));
}
}
结果:true
➢Object是所有类的父类,那么0bject类可以接收所有类的对象, 但是在Java设计的时候,考虑到引用数据类型的特殊性,所以0bject类实际上是可以接收所有引用数据类型的数据,这就包括了数组、接口、类。
接收数组数据
接收接口对象
Object除了可以接收数组对象外,接口对象也同样可以利用Object接收。
但是要记住,接口不会继承任何类,所以也不会继承Object。
➢内部类指的是在一个类的内部定义了另外的类结构,利用内部类可以方便的实现私有属性的互相访问,但是内部类是需要明确的使用class进行定义的。而匿名内部类的是没有名字的内部类,但是其必须在抽象类或接口基础上才可以定义。
interface Message{
void fun(); //接口默认使用public,可以不写
}
public class Main {
public static void main(String args[]) throws Exception {
fun(new Message() {
//使用匿名内部类实例化接口对象
@Override
public void fun() {
System.out.println("hello");
}
});
}
public static void fun(Message msg){
msg.fun();
}
}
结果:hello
➢为了方便用户的开发,专门给出了-组包装类, 来包装八种基本数据类型: byte (Byte) 、short (Short) . int (Integer) 、long (Long)、float (Float) 、double (Double)、char (Character) 、boolean boolean (Boolean)
➢但是以上给出的包装类又分为两种子类型:
➢对象型包装类(Object直接子类):Character、Boolean
➢数值型包装类(Number直接子类):Byte、Short、Integer、Long、Float、Double
➢Number是一个抽象类, 里面一共定义了六个操作方法: intValue()、 doubleValue0、 floatValue(、 byteValue0、 shortValue0、 longValue()。
➢现在已经存在有基本数据类型与包装类类,那么这两种类型间的转换就通过以下方式定义:
➢装箱操作:将基本数据类型变为包装类的形式;
➢每个包装类的构造方法都可以接收各自数据类型的变量;
➢拆箱操作:从包装类之中取出被包装的数据;
➢利用从Number类中继承而来的一系列: xxxValue()方法完成。
使用int和Integer
public class Main {
public static void main(String args[]) throws Exception {
Integer integer = new Integer(10);
int value = integer.intValue();
System.out.println(value);
}
}
结果:10
使用double和Double
public class Main {
public static void main(String args[]) throws Exception {
Double aDouble = new Double(10.2);
double value = aDouble.doubleValue();
System.out.println(value);
}
}
结果:10.2
使用boolean和Boolean
public class Main {
public static void main(String args[]) throws Exception {
Boolean aBoolean = new Boolean(true);
boolean value = aBoolean.booleanValue();
System.out.println(value);
}
}
结果:true
public class Main {
public static void main(String args[]) throws Exception {
Integer obj = 10;
int value = obj;
System.out.println(value);
}
}
结果:10
➢使用包装类最多的情况实际上是它的数据类型转换功能上,在包装类里面提供有将String型数据变为基本数据类型的方法,使用Integer、 Double、 Boolean几个常用类做说明:
➢Integer类: public static int parselnt(String s); .
➢Double类: public static double parseDouble(String s);
➢Boolean类: public static boolean parseBoolean(String s);
将字符串变为int型数据
public class Main {
public static void main(String args[]) throws Exception {
String str = "123"; //字符串需要都是数字
int i = Integer.parseInt(str);
System.out.println(i);
}
}
结果:123
将字符串变为double型数据
public class Main {
public static void main(String args[]) throws Exception {
String str = "10.3"; //字符串需要都是数字
double i = Double.parseDouble(str);
System.out.println(i);
}
}
结果:10.3
将字符串变为boolean型数据
public class Main {
public static void main(String args[]) throws Exception {
String str = "True"; //大小写随便写,不要写错就好
boolean i = Boolean.parseBoolean(str);
System.out.println(i);
}
}
结果:true