一:自定义类:
之前我们写的类大多数是只有一个main方法并且没有返回值。一个完整的程序包括各种主力类,这些自定义类有自己的实例域和返回值。一个程序中只有一个类有一个main方法,多个主力类组成。main方法主要写各个类之间的调用。
自定义类的语法:
class classname{
fields。。。 constructor.. statement ....... }
1 public class mod_cls { 2 public static void main(String[] args){ 3 Mod_Cl get_name=new Mod_Cl(); 4 String check_name=get_name.checkName("tom"); 5 System.out.println(check_name); 6 } 7 } 8 9 class Mod_Cl{ 10 String checkName(String x){ 11 String name=x; 12 return name; 13 } 14 }
类Mod_Cl就是自定义类,通过mod_cls调用自定义类中的checkNmame方法。
注意:在一个程序中只有一个公共类和多个非公共类组成。
构造器:
之前我们的简单了解下构造器,构造器的名字和类的名字一致。构造器当初始化的时候通过new方法进行调用,将对象的初始化的值(对象null,布尔false,int0)进行改变,讲对象的引用赋值对象的变量。
特点:只能用public private protected 三个修饰符。
没有返回值,因为构造器不是函数,所以他没有返回值,也不允许有返回值,但是允许return语句,如果有返回值,编译器不会报错,但是jvm认为该类的构造器和该函数重名,会报找不到构造器。
练习:
需求:在一个公司里,有多个员工,员工有涨工资的属性,模拟员工涨工资,并且将员工的涨完的工资信息输出出来。
分析:有需求中,可以看出有employee类和一个公共类employee_test,其中类employee类为非共有类其中包含员工的字段信息,这些信息属于私有(private)只能该类的方法的才能进行修改,不能被其他类的方法进行修改,这些字段信息初始化值是放在构造器中。
即:employee类由以下组成:
1:非公有类
2:私有字段信息。
3:构造器:初始化该类的私有信息字段。
4:方法:涨工资
完整代码:
1 public class Employee_Test { 2 public static void main(String[] args){ 3 Employee[] em_arr= new Employee[3]; 4 em_arr[0]=new Employee("tom",22,1200); 5 em_arr[1]=new Employee("evil",22,22200); 6 em_arr[2]=new Employee("jack",22,2200); 7 System.out.printf("add salary information below: "); 8 for (Employee a:em_arr){ 9 System.out.printf("name is %s age: %d salary:%f ",a.getName(),a.getAge(),a.addSalary(0.5)); 10 } 11 } 12 } 13 14 class Employee{ 15 private String name; 16 private int age; 17 private double salary; 18 public Employee(String aname,int age,double asalary){ 19 this.name=aname; 20 this.age=age; 21 this.salary=asalary; 22 } 23 public double addSalary(double addpercent){ 24 double addsalary=addpercent*this.salary; 25 salary+=addsalary; 26 return salary; 27 } 28 public String getName(){ 29 return this.name; 30 } 31 public int getAge(){ 32 return this.age; 33 } 34 35 }
解析:
多个源文件编译规则:
一个java程序是由多个类组成,只有一个公共类其他非公共类,类的名字和源文件名字一样的。静态方法main方法只在公共类中。静态方法是通过类的来调用,在初始化的程序的时候,是没有创建对象,所以通过类的静态方法的来调用。
如上程序是由2个类组成,我们把这2个类放在一起,形成Employee_Test.java文件,但是在IDE编译的时候形成2个class文件。
对于大多数人来说,会把一个类放在一个文件中。形成2个java结尾的文件:Employee.java Employee_Test.java.
我们在编译的时候,该怎么操作呢?
一种使用通配符*
javac Employee*.java
一种是直接编译
javac Employee_Test.java
在java中,如果一个类的中代码调用其他的类的时候,他会在当前的目录找到该类,并编译该类,如果被调用的类代码更新,在调用的时候会重新编译。
字段:
如上程序,Employee类包含多个私有字段、一个构造器、三个方法。
三个方法修饰符都是public,表示任意的类的方法都可以对Employee类的方法进行调用。
private String name;
private int age;
private double salary
如上字段,修饰符都是private ,表示这三字段只有 Employee类的对象的方法才能进行对象状态(实例域)的修改。其他类的无法访问和操作。这符合类的封装的特性。想一想如果别的类能够操作这些字段,那数据会出现混论!
类的方法可以访问类的所有对象的私有数据!
也就是说类的字段一般设置为private修饰符
构造器:
1 public Employee(String aname,int age,double asalary){ 2 this.name=aname; 3 this.age=age; 4 this.salary=asalary; 5 }
构造器是给对象初始化状态,通过构造器修改对象初始值。
调用方式:通过new初始化对象的时候将对象的引用值传给对象变量的时候执行了构造器。
特点:
修饰符只有public、private、protected。
没有返回值。
构造器可以多个,不止一个。构造器可以进行重载多个构造器。
构造器的名字和类的名字的一致的。
不能对已经有对象的对象变量进行再次执行构造器修改状态而达到重新设置值的目的。
构造器的参数可以为0、1、。。。。多个。
参数:
参数分隐式参数和显式参数。比如上面的构造器中:
1 private String name; 2 private int age; 3 private double salary; 4 public Employee(String aname,int age,double asalary){ 5 this.name=aname; 6 this.age=age; 7 this.salary=asalary; 8 }
在构造器中,参数aname、aage、asalary,属于构造器Employee的参数这叫做显式参数。
而构造器中的name、age、salary属于类中定义的字段,并不属于构造器的参数,这叫做隐式参数。
隐式参数用this.来表示,在构造器块中 this.name表示参数name。这样用this更好区别的与构造器的自己的局部变量参数。
构造器的参数命令最好是能让人易于理解,比如上面的aname、aage等。
访问器和更改器:
如上程序中,其中方法:getName() getAge() addSalary()。其中:getName() getAge() 通过声明public 2个访问器来访问实例域。通过声明public的更改器,这样只有通过Employee类的通过访问器和更改器来访问对象的实例域和修改实例域更为安全。避免出现数据混乱。
也就是说需要获得或者更改实例域的时候,需要提供以下:
1:私有的实例域。
2:公共的域访问器方法
3:公共的域更改器方法。
1 public double addSalary(double addpercent){ 2 double addsalary=addpercent*this.salary; 3 salary+=addsalary; 4 return salary; 5 } 6 public String getName(){ 7 return this.name; 8 } 9 public int getAge(){ 10 return this.age; 11 }
这种好处是:通过内部的实现,通过类的方法之外不会影响其他的代码。
final 修饰符:
一 final数据
1.在修饰基本类型时,表示它是一个常量,在定义时必须给予赋值.
特别的一个既是static又是final 的字段只占据一段不能改变的存储空间。
2.在修饰对象或者数组时,它表示对对象或数组的引用恒定不变,然而对象本身却是可以修改的.
空白final:声明为final但末给定初值的字段,但必须确保空白final在使用前被初始化,一般在构造方法完成。
final参数:在方法的参数列表以声明的方式将参数指明为final,这意味着在方法里无法修改参数的引用所指向的对象。
如上面的字段name 可以用final来进行修饰表示该变量自始至终未发生任何的改变。
静态域合静态方法:
类似于python 的静态字段和类方法,无论创建多少个对象,他只创建一次静态域,他不伴随对象的创建而创建。静态域和静态方法通过类来进行调用,在python中需要装饰器@classmethod进行修饰,并必需参数为cls。
静态域他属于类,即使没创建类他也自己存在。100个对象,但只有一份拷贝的静态域。
静态变量用的比较少,但是静态常量用的比较多。比如Math对象中的PI
1 import java.lang.Math; 2 public class Math_test { 3 public static void main(String[] args){ 4 System.out.println(Math.PI); 5 } 6 }
他本身就是一个静态常量。
静态方法无法对对象实施操作的方法。
为什么呢?
因为静态方法、静态变量和静态常量,无需通过对象进行调用,在启动程序的时候,还没有创建对象时候,是通过类的进行调用。而不管对象创建多少,静态常量和变量只有一份拷贝。所以静态方法无法对对象实施任何操作。
在调用的时候直接通过类进行调用,比如我们每个程序都有main方法,Math中pow方法都属于静态方法。
什么时候使用静态方法呢?
1:不需要访问类对象的实例域。
2:方法的参数都是显式参数。
静态方法另一个应用:工厂方法。
方法参数:
1 public class args { 2 public static void main(String[] args){ 3 int a=2; 4 Base_Ar check_args =new Base_Ar("tom",20000); 5 check_args.set_Args(a); 6 check_args.prin_Info(); 7 System.out.printf("a is %d",a); 8 9 } 10 } 11 12 class Base_Ar{ 13 14 15 private double salary; 16 private String name; 17 public Base_Ar(String anme,double asalary){ 18 name=anme; 19 salary=asalary; 20 21 } 22 public void set_Args(int x){ 23 x+=3; 24 salary+=20; 25 } 26 public void prin_Info(){ 27 System.out.printf("name:%s salary:%f ",name,salary); 28 29 } 30 31 }
在java中变量参数的传递是值。
如上变量a,在调用set_Args中,将a的值传递给该方法,虽然在方法中进行x+=3的操作,但是a的值并没有发生变化。
而在对象中,传递的值是对象的引用值。在上面的salary中传递是对象的引用,他们都指同一个对象,所以修改了对象的状态。
总结如下:
1:一个方法不能修改一个基本数据类型的参数(即数值型和布尔型)
2:一个方法可以改变一个对象的参数的状态。
3:一个方法不能让对象参数引用一个新的对象。