JAVA---面向对象编程

本文深入探讨Java面向对象编程的核心概念,包括函数参数传递、构造函数、静态成员、类的封装、继承、多态性、抽象类、接口、final关键字及Object类的使用。解析这些概念的实际应用,提供代码示例帮助理解。

关于JAVA面向对象中一些注意点

1函数参数的传递

简单数据类型
引用数据类型
形参
值传递
引用传递

2函数的重载(静态多态)

*注意形参的有所区别

3构造函数(对象的初始化

原则:(1)函数名称与类名称相同 (2)不含返回类型

class Customer{
    String name;
    String sex;
    Customer(String name,String sex){
        this.name=name;
        this.sex=sex;
        } 
 }
public class C{
    public static void main(String[] args){
        Customer zhangan=new Customer("张三","男");
        }
 }

注意:
1)当一个类的对象创建时,构造函数自动被调用,所以在构造函数中加入初始化的代码。在对象的生命周期中,构造函数只会被调用一次
2)构造函数也可以被重载,故可以定义多个构造函数,根据参数调用构造函数。
3)当没有写构造函数时,系统会自动调用一个无参的构造函数;但是如果写了构造函数,那么系统将不会自动调用无参函数,如果自己没有写这个无参的函数将不能用。

4静态变量和静态函数

静态函数
1)为什么引入静态变量"static"?
为了让一个类的所有对象的共有内容只用一个空间保存,实现互通操作(该一个都改)
2)访问: 可以通过"对象名.变量名"或者"类名.变量名"访问。一般情况下推荐用“类名.变量名”访问,而非静态变量不可以通过这种方式访问。
3)从底层讲,静态变量在类被载入时创建,只要类存在,静态变量就存在,不管类是否被实例化对象。

静态变量的常见应用

1 跨对象保存信息————>实现对象之间的通信
对象通信是比较复杂的,例如登陆界面中输入账号,密码,然后点击登陆按钮到达应用界面,那么应用界面是如何根据登陆界面中的账号显示不同的应用界面的?
解决方案:用静态变量保存账号,在登陆界面中如果登陆成功。就将账号存入一个静态变量中,然后在应用界面读取这个静态变量即可
2 统计对象个数
在类中定义一个静态变量num,每创建一个对象+1(所以得写到构造函数之中),每撤销一个对象-1

package game;
class person{
	String name;
	static int num=0;
	person(String s){
		this.name=s;
		num++;
		System.out.println("chaungjianle"+s);
	}
	void die(){
		num--;
		System.out.println(name+"die");
		if(num<=3) {
			System.out.println("警告");
		}
	}
}
public class youxi {

	public static void main(String[] args) {
		// TODO Auto-generated method stub
		person p1=new person("张三");
		person p2=new person("sss");
        person p3=new person("ddd");
        person p4=new person("dddd");
        person p5=new person("eee");
        p1.die();
        p3.die();
	}

}


结果:
chaungjianle张三
chaungjianlesss
chaungjianleddd
chaungjianledddd
chaungjianleeee
张三die
ddddie
警告

静态函数
1)静态函数同样可以通过“类名.函数名”和“对象名.函数名”访问。推荐使用“类名.函数名”
2)注意在静态函数调用时对象还没有创建,因此静态函数中不能直接访问类中的非静态成员函数和成员变量,当然也不能使用this关键字。
静态代码块

对所有对象的共同信息进行初始化(构造函数是对某个对象进行初始化)==并对所有对象只执行一次的机制。

class Customer{
	String name;
	static String bankName;
	static {
		bankName="中国银行";
		System.out.println(bankName+"执行几次");
	}
}
public class bank {

	public static void main(String[] args) {
		// TODO Auto-generated method stub
		Customer zhangsan=new Customer();
		Customer lisi=new Customer();

	}

}



结果:中国银行执行几次

这说明当类被载入时,静态代码块被执行,且只被执行一次,静态代码块经常用来实现类属性的初始化。

5类的封装

1)步骤:①将不能暴露的成员隐藏起来,不能让其在类外部直接使用,方法是将该成员定义为私有的,在其前边加上private;②用公共方法来暴露对该隐藏成员的访问

注意以下几点:
1)私有成员只能在定义它的的内部访问(即通过类内部的函数访问)不可通过实例化对象访问。

class Customer{
	String name;
	private int age;
	public void setAge(int age) {
		if((age>0)&&(age<100)) {
			this.age=age;
		}else
			System.out.println("年龄不合规则");
	}
	public int getAge() {
		return age;
	}
}
public class age {

	public static void main(String[] args) {
		// TODO Auto-generated method stub
		Customer zhangsan=new Customer();
		zhangsan.setAge(4);
		int a=zhangsan.getAge();
		//错误示例
		//zhangsan.age=4;
		System.out.print(a);

	}

}


结果    4
错误示例提示  The filed Customer.age is not visiable

6包

1)src文件下可以建包,包下可以建立.java文件(建类),.java文件根据类的多少编译为多个.class文件
2)在实际操作中最好把类单独写在.java文件中。
3)建包有俩种方法
一:src->new->package
二:定义文件头上加上“package 包名;”
4)建议包名用小写字母,便于阅读。有时候还加入".",例如face.express。类就放在了包“face.express”中。当遇到“."号时,系统会认为是要建立一个子文件夹,此时.java文件放在src->face->express中。.class文件放在bin->face->express中。
5)当要在命令行运行时,首先到达包目录的上一级即bin,然后 java face.express.类名,这样就可以运行主函数。
6)命令行下的编译问题:编译一个.java文件,默认是不会生成相应的目录,直接与.java文件放在一起(javac 类名.java)。但是如果不把.class文件放在包目录下是不能执行的,所以用(javac -d 类名.java)编译则可生成相应的包目录。
7)编写一个类,编译成.class 文件之后随意放在一个目录下,并不等于把类放在了包中。包名必须在源代码中通过package指定。

8)访问包中的类
①在同一个包中直接使用类名来访问。
②不在同一个包中有俩种解决方法。

指明类的路径
import 包名.类

注意:
一:可以用import 包名.* 导入包中所有类。
二:必须保证被访问的类是public的,即在类前加上public关键字。

7访问修饰控制符

1 类的访问控制修饰符
定义类时,可以在前边加上访问控制修饰符public,也可以不加。
1)不加时,可以被同一个包中所有类访问
2)加public,就是一个公共类,可以被包内、包外所有类访问。类名和文件名必须相同,因此一个.java文件只有一个公共类。
2 成员的访问控制修饰符
开放程度private<default<protected<public
1)private类型成员只能在定义它的类内部使用
2)default类型成员可以在定义它的类的内部使用,也可以被这个包中的其他类访问。
3)protected可以在定义的类内部使用,也可以被包中的其他类访问,还可以被包外的子类访问。
4)public可以被定义它的类使用,也可以被包内包外其他的类访问。

8使用类中类

内部类可以访问外部类中的成员,内部类成员只能在内部类中使用。

public class Outer {
	int a;
	void funOuter() {
		Inner inner=new Inner();
	}
	class Inner{
		int b;
		void fun() {
			a=3;
			this.b=5;
		}
	}

}

此例中外部类要实例化内部类,内部类可以使用外部类的成员。

8继承

8.1继承

1继承的出发点是提取共同项
2注意:java不支持多重继承,一个子类只能有一个父类,不允许出现一下这种情况:
class 子类 extends 父类1,父类2{}
但是java支持多层继承,如A继承了B,B继承了C,相当与A间接继承了C。
3如果一个成员要被子类继承后使用,这个成员不能是private的,一般情况下,成员变量定义为protected,成员函数定义为public
4继承的本质:

package extends2;
class Dialog{
	protected String title;
	public Dialog(){
		System.out.println("父类的构造函数");
		
	}
	public void show() {
		System.out.println(title+"对话框显示");
	}
}
class FontDialog extends Dialog{
	private String fontName;
	public FontDialog(String title,String fontName) {
		System.out.println("子类的构造函数");
		this.fontName=fontName;
		this.title=title;
		
	}
	
}
public class Main {

	public static void main(String[] args) {
		// TODO Auto-generated method stub
		FontDialog fd=new FontDialog("字体","宋体");

	}

}


结果:父类的构造函数
子类的构造函数

说明了只要实例化子类对象,系统就会先自动实例化一个父类对象与之对应,当然此时调用的父类是没有参数的构造函数。
如果父类的构造函数有参数有俩种解决方式:
(1)增加一个不带参数的构造函数
(2)用super给父类构造函数传参数

class FontDialog extends Dialog{
        private String fontName;
        public FontDialog(String title,String fontName){
             super(title);
             this.fontName=fontName;
             }
             
 }

注意:super()函数必须写在子类构造函数第一句。

8.2成员的覆盖

子类中的函数定义与父类的相同,叫做重写或覆盖。
注意点:
①如果在子类中定义了一个名称和参数列表与父类相同的函数,但是返回类型不同,此时系统会报错。
②重写时,子类函数的访问权限不能比父类函数更严格,比如父类的成员函数访问权限是public,子类的重写就不能写成protected.
③在覆盖的情况下,如果一定要使用父类的这个函数,可以使用super.函数名
例如:

...
class FontDialog extends Dialog{
        private String fontName;
        public FontDialog(String title,String fontName){
                this.title=title;
                this.fontName=fontName;
                }
        public void show(){
              super.show();//调用父类构造函数
              System.out.printin("FontDialog.show");
              }
   }

成员覆盖有何作用?
最大的作用是在不改变源代码的情况下对一个模块的功能进行改造
因为改造源代码就意为着读懂源代码,耗时太多。

9多态性

重载其实就是一种静态多态性
动态多态性的理论基础是父类应用可以指向子类对象

package poly1;

class Dialog{
	public void show() {
		System.out.println("Dialog.show");
	}
}
class FontDialog extends Dialog{
	public void show() {
		System.out.println("FontDialog.show");
	}
}
public class Main {

	public static void main(String[] args) {
		// TODO Auto-generated method stub
		Dialog fd=new FontDialog();      //父类引用指向子类对象。
		fd.show();

	}

}

结果:FontDialog.show

本例中父类和子类都有show函数,调用的是子类的。
如果子类中没有,则会调用父类的。
如果父类中没有,则会报错。
多态的作用:
①函数传入的形参是父类类型,实际传入的实参可以是子类对象,就可以使不同的子类都可以被这个函数操作。

public class Main{
     public static void toCenter(Dialog fd){
           fd.show;
        }
    public static void main(String[] args){
       FontDialog fd=new FontDialog();
       toCenter(fd);        //形参是父类,实参是子类,每个子类都可以被这个函数操作。
       }

}

②函数的返回类型是父类类型,实际返回的可以是子类对象

...
public class Main{
      public static Dialog fun(){
           return FontDialog();
           }
      public static void main(String[] args){
              Dialog dialog=fun();
              dialog.show();
              }
   }

可以看出,主函数中更本没有FontDialog的痕迹,如果fun函数中改为返回其他类型,更本不需要修改主函数。

父类和子类对象的类型转换
①根据多态性,子类对象无需转换就可以赋值给父类引用
②严格来讲父类类型对象是无法转换为子类类型的,

Dialog dialog=new Dialog();

FontDialog fd=dialog;

错误

但是有一种特殊情况,如果父类类型对象原来就是某一种子类类型对象,则可以转换为相应的子类类型对象,只需强制转换即可

Dialog dialog=new FontDialog();

FontDialog fd=(FontDialog)dialog;

正确

可以用instanceof 函数判断是否是某一类型
格式“对象名 instanceof 类名”
正确返回true,错误返回false

10抽象类

1)为什么需要抽象类?
在多态的例子中,关于父类作为形参,子类作为形参的例子中。如果父子类中都有同一个函数,则调用的是子类的。如果只有父类有则调用的是子类的。如果只有子类有则会报错。为了避免这种情况,能否要求父类函数一定被重写?于是有了抽象类。

abstract class Dialog{
        public abstract void show(){
        }
  }

含有抽象函数的类叫抽象类,抽象类一定要用abstract修饰。
注意:
①抽象类不能被实例化
②抽象类必须被重写,除非子类也是抽象类。
③抽象类中也可以含有普通成员函数。

11接口

如果一个抽象类中的所有成员函数都是抽象的,也可以定义为接口(interface).
一般叫做“实现(implements)接口”,子类也叫实现类。

package poly1;

interface Dialog{
	public void show() ;
}
class FontDialog implements Dialog{
	public void show() {
		System.out.println("FontDialog.show");
	}
}
public class Main {

	public static void main(String[] args) {
		// TODO Auto-generated method stub
		Dialog fd=new FontDialog();
		fd.show();

	}

}

说明:
①接口的方法中不需要专门指出abstract,系统默认为抽象函数,在接口中只能包含常量和函数。
②在接口中的成员函数默认为public,成员变量默认为 public static final标识的,所以在接口中定义的变量就是全局静态变量。
③接口可以用extends继承另外一个接口,类通过implements实现一个接口。
④一个类在继承一个父类的同时可以实现多个接口,多个接口用“,”隔开。
class 子类 extends 父类 implements 接口1,接口2,…{}

12final关键字

1)修饰一个类,标识该类不能被继承。

final class FontDialog{}

2)修饰 一个函数,该类被子类继承的情况下,该函数不能被重写。

class FontDialog{
      public final void show();
      }

3)修饰一个成员变量,表示该成员变量的值不允许被改变,因此一般用final来定义一个常量。

class Math{
     public final double PI=3.14159;
     }

13Object 类

在java中,如果没用extends的话,那么默认继承自Object 类,因此Object类是所有类的父类。
一 toString 方法
重写toString方法的例子

package object;

public class Customer {
    private String name;
    public Customer(String name) {
    	this.name=name;
    }
    public String toString() {     //重写toString方法
    	return this.name;
    }
	public static void main(String[] args) {
		// TODO Auto-generated method stub
        Customer cus=new Customer("张三");
        System.out.println(cus);
	}

}

结果:张三

实际上,System.out.println(cus)会自动调用其toString 方法。

二 equals
如何判断俩个对象相等?如果认为行姓名相等就相等用==可以吗?

package object;

public class Customer {
    private String name;
    public Customer(String name) {
    	this.name=name;
    }
  
	public static void main(String[] args) {
		// TODO Auto-generated method stub
        Customer cus1=new Customer("张三");
        Customer cus2=new Customer("张三");
        System.out.println(cus1==cus2);
	}

}
结果:false

实际上,除非俩个引用指向同一个对象,这俩个引用“==”判断才会相等。
如果要自定义相等的条件,就要重写Object继承过来的equals

package object;

public class Customer {
    private String name;
    public Customer(String name) {
    	this.name=name;
    }
    public boolean equals(Customer cus) {
    	if(name.equals(cus.name)) {
    		return true;
    	}
    	return false;
    }
  
	public static void main(String[] args) {
		// TODO Auto-generated method stub
        Customer cus1=new Customer("张三");
        Customer cus2=new Customer("张三");
        System.out.println(cus1.equals(cus2));
	}

}

结果:true

注意:
“name.equals(cus.name)"说明了判断俩个字符串相等也不能用==,用的是equals方法。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值