一、java类的最基本元素:Field和Method
java类可以由哪些部分组成?
属性Field
方法Method
构造器Constructor:1创建对象 2初始化对象
代码块
内部类
java类的定义
public class Animal {
public int legs;
public void eat(){
System.out.println(“Eating.”);
}
public void move(){
System.out.println(“Moving.”);
}
}
legs是类的属性 ,也叫类成员变量 。
eat(),move()是函数,也叫类的成员方法。
二、java中类与对象
java类的最基本元素:Field和Method
Field = 属性 = 成员变量,Method = (成员)方法 = 函数
对象的创建和使用
public class TestPerson {
public static void main(String[] args) {
Person p1 = new Person("Peter");
Person p2 = new Person("Peter");
System.out.println(p1.name == p2.name); //true
}
}
class Person{
String name;
public Person(String name){
this.name = name;
}
}
三、构造器的使用
根据参数不同,构造器可以分为如下两类:
隐式无参构造器(系统默认提供)
显式定义一个或多个构造器(无参、有参)
注 意: Java语言中,每个类都至少有一个构造器
默认构造器的修饰符与所属类的修饰符一致
一旦显式定义了构造器,则系统不再提供默认构造器
一个类可以创建多个重载的构造器
父类的构造器不可被子类继承
重载构造器的迭代使用
package lesson04;
class Person {
//属性
private String name;
private int age;
//方法
public int getAge(){
return age;
}
public void setAge(int age){
this.age = age;
}
public String getName(){
return name;
}
public void setName(String name){
this.name = name;
}
public void walk(){
System.out.println("人走路");
}
@Override
public String toString() {
return "Person [name=" + name + ", age=" + age + "]";
}
//构造器
public Person(){
//this(12);如果有n个构造器,只能有 n-1 个 调用构造器
super();//调用的是object类的
System.out.println("this is Person's Constructor with no args");
}
public Person(int age){
this();//这里调用的是上面无参数的构造器
this.age = age;
System.out.println("这是Person的int的参数构造器");
}
public Person(int age,String name){
this(age);//通过this,调用父类或本类重载构造器。根据参数列表识别调用的是哪个构造器。要放在构造器的第一行
//this.age = age;
this.name = name;
System.out.println("这是Person的int&String的参数构造器");
}
}
调用父类的构造器
子类中所有的构造器默认都会访问父类中空参数的构造器
当父类中没有空参数的构造器时,子类的构造器必须通过this(参数列表)或者super(参数列表)语句指定调用本类或者父类中相应的构造器,且必须放在构造器的第一行
如果子类构造器中既未显式调用父类或本类的构造器,且父类中又没有无参的构造器,则编译出错
调用父类构造器举例
package lesson04;
public class Student extends Person{
String school;
public Student(int age,String name,String s){
super(age,name);
school = s;
}
public Student(int age,String s){
super(age);
school = s;
}
public Student(){
//super();//如果不显示调用父类构造器的话,默认调用父类的空参构造器
}
public Student(String s){
// super();
school = s;
}
public String toString(){
return "Student[school = "+ school+", name=" + this.getName() + ",age=" + this.getAge() + "]";
}
}
四、关键字static
当我们编写一个类时,其实就是在描述其对象的属性和行为,而并没有产生实质上的对象,只有通过new关键字才会产生出对象,这时系统才会分配内存空间给对象,其方法才可以供外部调用。
我们有时候希望无论是否产生了对象或无论产生了多少对象的情况下,某些特定的数据在内存空间里只有一份,例如所有的中国人都有个国家名称,每一个中国人都共享这个国家名称,不必在每一个中国人的实例对象中都单独分配一个用于代表国家名称的变量。
关键字static
class Circle{
private double radius;
public Circle(double radius){this.radius=radius;}
public double findArea(){return Math.PI*radius*radius;}}
创建两个Circle对象
Circle c1=new Circle(2.0); //c1.radius=2.0
Circle c2=new Circle(3.0); //c2.radius=3.0
Circle类中的变量radius是一个实例变量(instance variable),它属于类的每一个对象,不能被同一个类的不同对象所共享。
上例中c1的radius独立于c2的radius,存储在不同的空间。c1中的radius变化不会影响c2的radius,反之亦然。
如果想让一个类的所有实例共享数据,就用类变量!
package lesson04;
public class TestStatic {
public static void main(String[] args){
Circle c1 = new Circle(2.0);
c1.name = "这是一个圆";//name加上static,c1更改 name值,将影响c2的 name
System.out.println(c1);
System.out.println();
Circle c2 = new Circle(3.0);
System.out.println(c2);
}
}
class Circle {
double radius = 1.0;
// static String name = "圆形";//加上static,存放空间就由常量池改变到静态域中,多个对象调用者属性时,可以节省内存空间;但是一个对象更改这个属性时,会影响其他对象的该属性值
//static代码块(初始化块)
// static{
// name = "circle";//代码块的赋值,和static 的赋值顺序,取决于 语句顺序
// }
String name = "圆形";
{
System.out.println("this is Circle's block...");
name = "yuan";
}
public Circle(double r){
radius = r;
}
public String toString(){
return "Circle [radius = " + radius +", name = "+ name +"]";
}
}
static修饰初始化块
一个类中初始化块若有修饰符,则只能被static修饰,称为静态代码块(static block ),当类被载入时,类属性的声明和静态代码块先后顺序被执行,且只被执行一次。
static块通常用于初始化static (类)属性
class Person {
public static int total;
static {
total = 100;//为total赋初值
}
…… //其它属性或方法声明
}
非静态代码块:没有static修饰的代码块
1.可以有输出语句。
2.可以对类的属性、类的声明进行初始化操作。
3.可以调用静态的变量或方法。
4.若有多个非静态的代码块,那么按照从上到下的顺序依
次执行。
5.每次创建对象的时候,都会执行一次。且先于构造器执行静态代码块:用static 修饰的代码块 1.可以有输出语句。 2.可以对类的属性、类的声明进行初始化操作。 3.不可以对非静态的属性初始化。即:不可以调用非静态的属 性和方法。 4.若有多个静态的代码块,那么按照从上到下的顺序依次执行。 5.静态代码块的执行要先于非静态代码块。 6.静态代码块只执行一次
静态初始化实例
class Person {
public static int total;
static {
total = 100;
System.out.println("in static block!");
}
}
public class Test {
public static void main(String[] args) {
System.out.println("total = "+ Person.total);
System.out.println("total = "+ Person.total);
}
}
五、方法的参数传递
方法只有被调用才会被执行
方法调用的过程分析
方法的参数传递
方法,必须有其所在类或对象调用才有意义。若方法含有参数:
**形参:**方法声明时的参数
实参:方法调用时实际传给形参的参数值
Java的实参值如何传入方法呢?
Java里方法的参数传递方式只有一种:值传递。 即将实际参数值的副本(复制品)传入方法内,而参数本身不受影响。
基本数据类型的传递
引用数据类型的传递
补充:变量的分类
在方法体外,类体内声明的变量称为成员变量。
在方法体内部声明的变量称为局部变量。
注意:二者在初始化值方面的异同:
同:都有生命周期
异:局部变量除形参外,需显式初始化。
方法参数传递实例1
package lesson04;
class DataSwap {
public int a;
public int b;
}
package lesson04;
public class TestTransfer1 {
public static void swap(DataSwap ds){
int tmp = ds.a;
ds.a = ds.b;
ds.b = tmp;
System.out.println("swap方法里,a Field 的值是"+ ds.a +";b Field的值是" +ds.b);
}
public static void main(String[] args){
DataSwap ds = new DataSwap();
ds.a = 6;
ds.b = 9;
swap(ds);
System.out.println("交换结束后,a Field的值是"+ds.a+";b Field的值是"+ds.b);
}
}
方法参数传递实例2
package lesson04;
class Value{
int i = 15;
}
class Test {
public static void main(String[] args){
Test t = new Test();
System.out.println(t);
t.first();
}
public void first(){
int i = 5;
Value v = new Value();
v.i = 25;
second(v,i);
System.out.println(v.i);
}
public void second(Value v,int i){
i = 0;
Value val = new Value();
v = val;
System.out.println(v.i+" "+ i);
}
}
输出结果
lesson04.Test@15db9742
15 0
25
内存图: