JAVA学习全过程(6)
现在多创建一个对象
public static void main(String[] args) {
HelloWorld h1=new HelloWorld();
HelloWorld h2=new HelloWorld();
HelloWorld h3=null;
}
这其实是3个引用,2个对象
h3这个引用指向空
public static void main(String[] args) {
HelloWorld h1=new HelloWorld();
HelloWorld h2=new HelloWorld();
HelloWorld h3=h1;
}
h1引用赋值给h3 (引用存的是地址)
那么h1 h3同时也指向一个对象
如果把h1 h3都指向空,那么那个对象就会被java自动垃圾回收机制(不再像C语言需要手动回收)给回收,至于什么时候回收,是不确定的
package Mypackage;
public class HelloWorld {
String a="hello world!";
void print(){
System.out.println(a);
}
public static void main(String[] args) {
HelloWorld h1=new HelloWorld();
HelloWorld h2=new HelloWorld();
HelloWorld h3=h1;
h1.a="haha";
h2.print();
h3.print();
} }
上面的代码很好的说明了问题
结果
hello world!
haha
也许换个类更容易理解
在Mypackage包下新建个类叫Test
package Mypackage;
public class Test {
public static void main(String[] args) {
} }
这是测试类,现在在这个文件里再新建一个类,叫Human 类 即人类
人类的属性有姓名 年龄,方法有吃饭,睡觉
这只是最简单的,其他什么身高,走路就不写了
class Human{
String name;
int age;
void eat(){
System.out.println("会吃饭");
}
void sleep(){
System.out.println("会睡觉");
}
}
假如我们是上帝,就可以创造人类,而Human类就是我们的模版,我们根据这个来创造人
Human h1=new Human(); 这样我们就创造了一个人,但是这个人没年龄没名字
所以我们可以赋值给他
h1.name="小明";
h1.age=5;
还可以创造第2个人
Human h2=new Human(); 然后给他名字和年龄
全部代码
package Mypackage;
public class Test {
public static void main(String[] args) {
Human h1=new Human();
h1.name="小明";
h1.age=5;
System.out.println("创造了一个人叫"+h1.name+"年龄是"+h1.age);
Human h2=new Human();
h2.name="小红";
h2.age=3;
System.out.println("创造了一个人叫"+h2.name+"年龄是"+h2.age);
} }
class Human{
String name;
int age;
void eat(){
System.out.println("会吃饭");
}
void sleep(){
System.out.println("会睡觉");
}
}
相信对类和对象稍微有点理解了吧
每次创造个人还要给他名字和年龄,能不能在创建的时候就初始化呢,可以的
这就要用到类的构造函数(方法)
类的构造函数跟普通方法不同
首先它必须跟类名相同,且不能有返回值
在类加载是自动调用
Human h1=new Human(); 这也是为什么后面会有括号
代码如下
package Mypackage; public class Test {
public static void main(String[] args) {
Human h1=new Human();
System.out.println("创造了一个人叫"+h1.name+"年龄是"+h1.age);
} } class Human{
String name;
int age;
Human(){
name="无名氏";
age=1;
}
void eat(){
System.out.println("会吃饭");
}
void sleep(){
System.out.println("会睡觉");
}
}
结果是
创造了一个人叫无名氏年龄是1
类的构造函数是默认存在的,如果不写,就默认为空,也就是什么也不执行
Human(){
}
就是这样
如果我想手动初始化人怎么办,也很简单,直接在创建的时候就赋值
代码如下:
package Mypackage;
public class Test {
public static void main(String[] args) {
Human h1=new Human();
System.out.println("创造了一个人叫"+h1.name+"年龄是"+h1.age);
Human h2=new Human("小红",3);
} }
class Human{
String name;
int age;
Human(){
name="无名氏";
age=1;
}
Human(String name,int age){
this.name=name;
this.age=age;
System.out.println("创造了一个人叫"+name+"年龄是"+age);
}
void eat(){
System.out.println("会吃饭");
}
void sleep(){
System.out.println("会睡觉");
}
}
结果是
创造了一个人叫无名氏年龄是1
创造了一个人叫小红年龄是3
这里你看到有两个Human构造方法,其实只会执行其中的一个,至于是哪一个,由你传的参数而定
其实这又是一个知识点,叫方法重载
一个类允许有相同名的方法,但参数个数要不同,或者相同但顺序要不同,或参数类型不同
如果我们做一个程序,实现动物走的功能的方法
假设两个动物 猫 和 狗
如果用面向过程来做
就一个方法 void go(){
System.out.println(“四条腿走路”);
}
如果是面向对象,就需要建两个类Cat 和Dog类,里面分别有go方法
如果又加了一种动物,猩猩
那么面向过程的方法go()就需要判断是否为猩猩,如果是,就打印两条腿走路,很麻烦
而面向对象,只需要在新建个类,另外建个go方法,打印两条腿走路
整个代码是这样的
package Mypackage;
public class Test {
public static void main(String[] args) {
} } class Cat{
void go(){
System.out.println("四条腿走路");
}
}
class Dog{
void go(){
System.out.println("四条腿走路");
}
}
class Xingxing{
void go(){
System.out.println("两条腿走路");
}
}
但这样有人会觉得,这样代码重复的地方很多
能解决吗?这就需要面向对象的继承了
新建一个Animal类
class Animal{
void go(){
System.out.println("四条腿走路");
}
}
Cat ,Dog,XingXing继承这个类,用extends关键字
Animal类是父类,继承它的都是子类
子类继承了父类,就可以直接使用父类的属性和方法
而且子类还可以重写父类的方法,比如XingXing类
代码如下
package Mypackage;
public class Test {
public static void main(String[] args) {
Cat cat=new Cat();
cat.go();
Xingxing x=new Xingxing();
x.go();
} } class Animal{
String a="Animal";
void go(){
System.out.println("四条腿走路");
}
}
class Cat extends Animal{
}
class Dog extends Animal{
}
class Xingxing extends Animal{
void go(){
System.out.println("两条腿走路");
}
}
结果
四条腿走路
两条腿走路
如果在类中调用父类的方法?用super关键字
super代表父类,this代表当前类
另外子类每当实例化的时候,会先运行父类的构造方法,然后才运行自己的构造方法
代码如下:
package Mypackage;
public class Test {
public static void main(String[] args) {
Cat cat=new Cat();
cat.go();
Xingxing x=new Xingxing();
x.go();
} } class Animal{
String a="Animal";
Animal(){
System.out.println("我是Animal类");
}
void go(){
System.out.println("四条腿走路");
}
}
class Cat extends Animal{
Cat(){
super.go();
}
}
class Dog extends Animal{
}
class Xingxing extends Animal{
void go(){
System.out.println("两条腿走路");
}
}
结果
我是Animal类
四条腿走路
四条腿走路
我是Animal类
两条腿走路
现在说说面向对象的另一概念--封装
先看下面代码
package Mypackage; public class Test {
public static void main(String[] args) {
Human human=new Human();
human.name="aaaa";
} }
class Human{
String name="xiaoming";
}
Human对象的name可以随意修改,对程序而言安全性太低
虽然final String name="xiaoming";定义常量可以不让外界修改,但自己也修改不了
最好的方法是建两个方法
class Human{
private String name="xiaoming";
public String getName() {
return name;
} public void setName(String name) {
this.name = name;
}
}
通过方法来对值进行读和写操作?有人会问,这不还是一样吗
不一样,可以在方法里判断条件,符合条件才能读或写,这样就实现了对数据的封装
数据必须设为private,不然没意义
package Mypackage;
public class Test {
public static void main(String[] args) {
Human human=new Human();
human.setName("aaaa");
} } class Human{
private String name="xiaoming";
public String getName() {
return name;
} public void setName(String name) {
this.name = name;
}
}
下面说说 访问修饰符
public private protected 默认(前面不写)这4个就是访问修饰符
这4个都可以修饰属性和方法
其中 private protected 不能修饰类 其他两个可以
访问修饰符的作用是 信息隐藏
public修饰的XX 是所有类都可以访问
private修饰的XX 只有当前类可以访问
protected修饰的XX 只有当前包的类或子类可以访问
默认修饰的XX 只有当前包的类可以访问
在来说说 方法修饰符
static final abstract 3个
static可以修饰属性和方法 修饰后,可以不用实例化就可以访问 如类名.方法名
但是static不可以修饰类,除了类中类
final 是常量修饰 可以修饰属性和方法,也可以修饰类,但修饰之后,其他类不可以继承
abstract是抽象修饰 可以修饰方法和类,不可以修饰属性, 构造方法 和 static 方法不能是抽象的,抽象类不能实例化
现在实现这么一个程序,人类下面有很多子类,例如学生。工人,司机等都属于人类的范畴
打印一个子类的职责
看下面代码
package Mypackage;
public class Test {
public void dothing(Student s){
System.out.println("学生可以学习");
}
public void dothing(Worker w){
System.out.println("工人可以工作");
}
public static void main(String[] args) {
Test t=new Test();
t.dothing(new Student());
} } class Human{
public void dothing(){
}
}
class Student extends Human{
} class Worker extends Human{
}
结果为:
学生可以学习
如果在新增加一个Teacher类
势必还要在Test类在新增一个方法
public void dothing(Teacher t){
System.out.println("老师可以教书");
}
哪天删除这个类,还要把这个方法删掉
能不能尽量少改动,把耦合度降低呢
这就要用到面向对象的又一特征:多态
多态指同一个实体同时具有多种形式
代码可以改成这样
package Mypackage;
public class Test {
public static void main(String[] args) {
Human h=new Teacher();
h.dothing();
} }
class Human{
public void dothing(){
}
}
class Student extends Human{
public void dothing(){
System.out.println("学生可以学习");
} } class Worker extends Human{
public void dothing(){
System.out.println("工人可以工作");
}
}
class Teacher extends Human{
public void dothing(){
System.out.println("老师可以教书");
}
}
注意这句 Human h=new Teacher();
这是父类引用指向子类对象,这就是多态的基本原理
父类引用可以调用子类重写父类的方法,而不能随便调用子类自己的方法
这样,无论增加多少个类
只要类重写了父类的方法,父类引用就可以调用
Test类也不用改动什么,只需改变引用的对象
如 新增个类叫Child 只要Human h=new Child();就Ok
其实还可以把父类改成抽象类
package Mypackage;
public class Test {
public static void main(String[] args) {
Human h=new Teacher();
h.dothing();
} }
abstract class Human{
abstract public void dothing();
}
class Student extends Human{
public void dothing(){
System.out.println("学生可以学习");
} } class Worker extends Human{
public void dothing(){
System.out.println("工人可以工作");
}
}
class Teacher extends Human{
public void dothing(){
System.out.println("老师可以教书");
}
}
有抽象方法的类就必须定义抽象类
子类必须重写父类的抽象方法
跟以后的接口差不多,只不过抽象类还可以有自己的具体实现方法
面向对象的3大主要特性继承,封装,多态就介绍到这里!
- QQ群
-
微信
- 返回首页
- 返回顶部