本文主要是介绍java 对象浅解,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!
java是一种面向对象的的语言,在Java程序员眼中万物皆对象。而对象就是讲有共同点的事务的共同部分抽离出来,然后定义一个类。而那些共同事务单独进行操作或其他行为就是类的实例。
简单的理解就是现有一个模版或者模子(类),然后通过这个模板而进行创建一个对象。狗就是一个模板,尤其常有的特征毛发,腿,鼻子等属性,而其还有一些行为比如跑,叫等(对象称之为方法)。 而泰迪就是一个对象了,它必然也会有毛发,腿,鼻子,也可以跑,叫等。但是其又有自己独特的地方,比如毛发长短,颜色,以及腿鼻子的形状等特征,跑的姿势以及叫的声音。
对象其有三个主要特征:封装,继承,多态。
-
封装:增强安全性和简化编程,使用者不必了解具体的实现细节,而只要通过对外公开的访问方法,来使用类的成员。
-
继承:可以理解为,在一个现有类的基础之上,增加新的方法或已有方法,从而产生一个新类。
-
多态:相同的事物,调用其相同的方法,参数也相同时,但表现的行为却不同。
先不进行各自详细解析,因为三个特征也是总结出来的,而其完全的可以先放在一起理解一下。
何为封装,封装就是将其类必须拥有的特征封装起来也就是这个类必须拥有的特点,比如狗这个类,它的一些特点,你无法套用在鱼上。 这个时候我们在创建类的时候,肯定有人说了狗吃东西,鱼也吃东西呀,难道这个吃就不可以封装到类中?当然也可以,因为java中所有的类都继承object这个类,也就是后面所说的继承,而鱼和狗难道都不是生物吗?自然也就继承了生物的一些特种,这个就是所谓的继承。你看见泰迪你可以说时狗,你看见狼狗也可以说是狗。而两个都可以吃,狼狗在吃肉,泰迪在吃罐头,都是狗的吃的行为,但是我们指着泰迪说,这狗吃东西呢,就是说狗吃罐头。我们用狗来泛指,但是我们知道他是指泰迪,而它的吃的行为就是吃罐头。
狗类 狗=泰迪类 泰迪()狗.吃的行为()最后得到狗(泰迪)吃罐头。
多态也有其必要条件:
-
前提:必须继承,如果没有继承也就没有多态的可能
-
实现:子类必须重写父类的方法,因而才会有多态的效果
-
表现形式:等号左侧必须时父类,而右侧new的部分时子类。这个是多态的表现形式。
// 此为父类
public class Father{//方法
}public class Son extends Father{//方法
}
构造方法
既然时面向对象,那么就应该知道构造方法,什么时构造方法呢?
构造方法是一种特殊的方法,它是一个与类同名的方法。对象的创建就是通过构造方法来完成,其功能主要是完成对象的初始化
public class Son {
public Son() {// TODO Auto-generated constructor stub
}
}
默认无参的构造函数,是可以不用写出的,所以一般我们是用的时候之间new Son(),直接就可以调用。
-
注意:如果没有其他有参的构造函数,那么要使用的时候无参构造函数可以不写,但是如果有了有参构造函数还要使用无参构造函数,那么无参构造函数必须写出。
//如果不需要无参构造函数,那么不写无参函数如下 public class Son { public Son(int age) {// TODO Auto-generated constructor stub }}//如果需要无参构造函数,那么需要写无参函数如下 public class Son { public Son() {// TODO Auto-generated constructor stub } public Son(int age) {// TODO Auto-generated constructor stub } }
如果上面,第一个直接new的时候需要new Son(5),但是如果还需要无参构造函数 new Son()就会报错,需要第二种写法了,可以理解成为一个重载构造方法
而在
首先我们看一下在创建子类对象,会发生什么事情,如下:
//父类public class Father {public father() {System.out.println("father");}
}//子类
public class Son extends Father{public Son() {System.out.println("son");}}//测试类
public class Test{public static void main(String[] args) {Son s=new Son();}}//输出的结果
father
son
由此可以看出,在创建子类的时候父类也会自动实例一个对象。
先不解释为什么会这样,我们首先要知道两个关键字 super和this
//父类
public class Father {int age=55;
}
//子类
public class Son extends Father{int age=15;public void out(int age) {System.out.println(age);System.out.println(this.age);System.out.println(super.age); }
}//测试类
public class Test{public static void main(String[] args) {Son s=new Son();s.out(10);}}
//输出结果
10
15
55
this:字面意思,就是指当前类,而this+.+(方法或属性)就是指当前方法的属性或者方法。
但在使用过程中需要我们注意:
-
每个类的每个非静态方法(没有被static修饰)都会隐含一个this关键字,它指向调用这个方法的对象;当在方法中使用本类属性时,都会隐含地使用this关键字,当然也可以明确使用。
-
this关键字只能在方法内部使用,表示对“调用方法的那个对象”的引用如果是在同一类中调用另外一个方法,则可以不用写this,直接调用
也就是this就是值当前对象,但是为什么会注明一点过要在非静态方法中使用呢?
看一下代码:
//父类 public class Father {static{ System.out.println("father的static模块"); }{System.out.println("father的模块"); }public Father() {System.out.println("father");} } //子类 public class Son extends Father{public Son() {System.out.println("son");}{System.out.println("son的模块"); }static{System.out.println("son的static模块"); } }//测试类 public class Test{public static void main(String[] args) {Son s=new Son();Son s2=new Son();}}//输出结果 father的static模块 son的static模块 father的模块 father son的模块 son father的模块 father son的模块 son
简单的陈述就是看出实例化一个对象 :
第一步:父类执行了static 模块第二步:子类执行了static 模块第三步:父类执行了 模块,第四步:父类执行了构造方法第五步:子类执行了 模块,第六步:子类执行了构造方法第七步:父类执行了 模块第三步到第七步又执行了一边
我们可以看出static 模块和普通模块执行优先鱼构造方法,同时虽然生成了两次对象,但是static只是执行了一次。还有static的方法也会优先与实例化(new一个对象)而执行。所以无法在static方法中使用this,因为当时没有一个对象,所以会报错。
-
this关键字的用法
-
当类中非静态方法的参数名与类的某个成员变量名相同时,为了避免参数作用范围覆盖了成员变量的作用范围,必须明确使用this关键字来指定
而这种通常体现在对象的属性中的get和set方法中,下面属性中会呈现。
-
如果某个构造方法的第一条语句具有形式this(…),那么这个构造方法将调用本类中的其他构造方法。简单的理解上面所说的构造方法的重载,可以之间通过this来相互调用。
-
如果某个方法需要传入当前对象,则可以将当前的对象作为参数传递给它。这个很简单理解,毕竟this就是指本身对象。
-
super:super代表了父类空间的引用
-
super的作用:
-
子父类存在着同名的成员时,在子类中默认时访问子类的成员,可以通过super关键字指定访问父类的成员
-
创建子类对象时,默认会先调用父类无参的构造方法,可以通过super关键字指定调用父类的构造方法
这个就是要说的,就是子类的构造方法中默认有一个super(),如果要写的话,一定要写在子类构造函数的第一行,不然会被报错。
-
-
super的方法
super可以用来引用直接父类的实例变量。
super可以用来调用直接父类方法。super()可以用于调用直接父类构造函数
简单总结一下this与super的区别:
super必须是有继承才可以使用,不然没有父类,也就没有所谓的super使用,而this本身就是自身,所以没有这个限制
属性
既然是对象,那就有其自身的特征,但是在java 中称之为属性。
public class Son {int age;String name;}
属性一般都是private 类型,也就是私有。因为程序也会默认private,所以一般需要写出表明,从侧面也表现出对象的封装.而属性都有其默认值,比如int类属性默认是0;
这样做的好处,就是防止对象以为对属性的调用,保证对象的安全。因为是私有的,所以对对象属性的操作我们就需要get和set方法了。
public class Son {int age;String name;//得到age的值public int getAge() {return age;}//赋予age的值public void setAge(int age) {this.age = age;}public String getName() {return name;}public void setName(String name) {this.name = name;}}
在外可以通过son s=new son(),然后通过s,对属性进行赋值或得到属性的值。
类属性:作为补充,还有一个属性,那就是类属性。对于类属性的判断依据就是有static符修饰的属性。可以称之为类属性,可以知道通过对象类进行调用,而可以直接通过类名进行调用,当然你new一个对象也可以调用。如下
public class Son {static int age;}public class Test{public static void main(String[] args) {System.out.println(Son.age);Son s=new Son();System.out.println(s.age);}
}
//最后打印出为0(因为没有赋值,得到默认值0,当然也可以直接赋值)
输入的结果是:
0
0
类属性的值,是一个共享的值。也就是如果值进行了改变,无论通过类名进行修改或者new的对象进行修改,对于调用这个类属性都会改变。
可以同一下程序理解一下:
public class Son {static int age;}public class Test{public static void main(String[] args) {System.out.println(Son.age);//输出的值0Son s=new Son();System.out.println(s.age);//输出的值0// 这个是通过类名对类属性值修改 Son.age=7;Son s1=new Son();System.out.println(s1.age);//输出的值7// 这个是新new的一个对象对类属性值修改 s1.age=9;System.out.println(s.age);//输出的值9}
}
属性尤其自己的独特优势,因为java时值传递,也就是在调用方法的时候,可以理解为进行的一个副本传递过去,而本身不会发生变化。
public class Test{public static void main(String[] args) {int a=10;out(a);System.out.println(a);}public static void out(int a) {a=a+10;System.out.println(a);}
}
//输出结果
20
10
可以看出java在传递的时候只是数值的传递,而其修改后对于原来的数据没有影响。而对象的调用却不是这样,这个涉及到另一个那就值传递和引用传递的解释,此处我们单独讲解java对象,暂时不过多陈述,后面单独会出一篇文章。
public class Son extends Father{int age;public int getAge() {return age;
}public void setAge(int age) {this.age = age;
}
}public class Test{public static void main(String[] args) {Son s=new Son();
// 可以通过set方法赋值s.setAge(10);
// 通过个体方法得到值System.out.println(s.getAge());updata( s);System.out.println(s.getAge());}public static void updata(Son s) {s.setAge(20);}
}
多态:
多态也有其必要条件,上面我写过,现在重新在写一遍:
-
前提:必须继承,如果没有继承也就没有多态的可能
-
实现:子类必须重写父类的方法,因而才会有多态的效果
-
表现形式:等号左侧必须时父类,而右侧new的部分时子类。这个是多态的表现形式。
下面我会用代码演示一遍,父类用dog,如果还用father和son的话估计会有点绕不过弯,
public class Dog {public void eat() {System.out.println("狗在食物");}} //第一个子类 public class TaiDi extends Dog{public void eat() {System.out.println("泰迪在吃罐头");}}//第二个子类 public class LangGou extends Father {public void eat() {System.out.println("狼狗在吃肉");} } //测试类 public class Test{public static void main(String[] args) {Dog td=new TaiDi();td.eat();Dog lg= new LangGou();lg.eat();} } //输出 泰迪在吃罐头 狼狗在吃肉
因为子类如果有方法直接运行子类的,就不会运行父类被重新的方法。
有人就好奇问,第一和第三点可以理解,但是为什么子类必须重新父类的方法,因为左侧为父类对象,如果子类不重新,一般子类无方法会调用父类,也就是说何来多态。
public class Dog {public void eat() {System.out.println("狗在食物");}} //第一个子类 public class TaiDi extends Dog{}//第二个子类 public class LangGou extends Father {} //测试类 public class Test{public static void main(String[] args) {Dog td=new TaiDi();td.eat();Dog lg= new LangGou();lg.eat();} } //输出 狗在食物 狗在食物
如果有人脑洞大开说,那我父类没有被重写方法咋样?
public class Dog {} //第一个子类 public class TaiDi extends Dog{public void eat() {System.out.println("泰迪在吃罐头");}}//第二个子类 public class LangGou extends Father {public void eat() {System.out.println("狼狗在吃肉");} } //测试类 public class Test{public static void main(String[] args) {Dog td=new TaiDi();td.eat();//编译不过去,会报错提示没有eat方法Dog lg= new LangGou();lg.eat();//编译不过去,会报错提示没有eat方法} }
有人说那我直接将上面的dog 换程taidi和langgou不就可以输出了吗?
对,是可以输出了,不过那我们直接干嘛还用继承呀 ,直接单独写不就可以了,也不用聊多态了。
补充
上面我们使用了static修饰的属性,称之为类属性,那么我们自然也可以相想到static 修饰的方法了。也可以称之为类方法,它可以继承以及可以实现多态吗?
我们先用代码解释
public class Dog {public void eat() {System.out.println("狗在食物");}public static void run() {System.out.println("狗在跑步");}}
//第一个子类
public class TaiDi extends Dog{public void eat() {System.out.println("泰迪在吃罐头");}public static void run() {System.out.println("泰迪在跑步");}}//第二个子类
public class LangGou extends Father {public void eat() {System.out.println("狼狗在吃肉");}public static void run() {System.out.println("狼狗在跑步");}
}
//测试类
public class Test{public static void main(String[] args) {Dog td=new TaiDi();td.eat();td.run()Dog lg= new LangGou();lg.eat();lg.run()}
}
//输出结果
泰迪在吃罐头
狗在跑步
狼狗在吃肉
狗在跑步
注意:对于静态方法,完全没有继承的样子,因为静态方法和方法类有关,而对象没有关系,是在new对象之前人家就存在了,也就无法实现多态了,所以记住对于继承的时候方法类一般无法不要使用static修饰,因为那样无法被重写也无法实现多态。
这篇关于java 对象浅解的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!