9.30上课问题的整理与思考

上周五的java课上,王建民老师主要围绕类与对象展开他的讲解,主要是以下内容:

1.编写类的模板

    类的模板:

public/private class 类名

{     public/private 数据类型 变量名;

       public/private 数据类型 方法名(参数列表){ }

}

public :访问与存取不受限制

private :除非是属于类自己的方法,其它对象不能访问与存取

class MyClass 
{
    // 公有字段
    public String Information = "";

    // 自定义公有Java实例方法
    public void myMethod(String argu) 
    {
        System.out.println(argu);
    }

    // 定义属性:私有字段+get方法+set方法
    private int value;
    public int getValue() 
    {
        return value;
    }
    public void setValue(int value) 
    {
        this.value = value;
    }

}

在Java中,可以通过组合一私有字段和一对get/set方法来定义一个属性。

对类的应用:

package practice;

public class ClassAndObjectTest {
    public static void main(String[] args) 
    {
        //创建类的实例,定义一个对象变量引用这一实例
        MyClass obj = new MyClass();
        //通过对象变量调用类的公有方法
        obj.myMethod("Hello");
        //给属性赋值
        obj.setValue(100);
        //输出属性的当前值
        System.out.println(obj.getValue());
        //直接访问对象公有字段
        obj.Information = "Information";
        //输出对象公有字段的当前值
        System.out.println(obj.Information);
    }
}

二、一种新的变量形式

原始数据类型:int float之类的变量,int a=100

引用类型:引用一个对象的变量称为“引用类型”的变量,形如 

MyClass obj = new MyClass();


三、变量与内存分配
声明一个对象类型的变量时,实际上并没有创建一个对象,此变量为null:MyClass obj = new MyClass() obj------null
定义一个原始类型的变量时,会马上给其分配内存:int a=100 a-----100
null:代表一个对象变量不引用任何对象

独特的对象引用:this
对象中所有数据字段都是通过this指针间接引用的
作为常量的对象变量
用final定义一个“常量”对象变量
final MyClass obj=new MyClass()
“常量”对象变量不能指向另一个对象,但可以修改对象,比如设置它所引用对象的某个公有字段值
四、对象判等
对于原始数类型的变量可以直接用“==”来判断是否一样
对象变量是否可以用“==”来判断呢?
public class ObjectEquals 
{
    public static void main(String[] args) 
    {
        
        MyTestClass obj1=new MyTestClass(100);
        
        MyTestClass obj2=new MyTestClass(100);
                        System.out.println(obj1==obj2);//false
        
        System.out.println(obj1.equals(obj2));//true
    
    }


}

通过代码可以发现,对象变量不能通过“==”来直接判断是否相等,能通过equals函数来判断。

原因如下

当“==”施加于原始数据类型变量时,是比较变量所保存的数据是否相等

当“==”施加于引用类型变量时,是比较这两个变量是否引用同一对象。

引用代表地址,所以“==”实际上相当于比较两个引用类型变量中保存的对象地址是否相同。

五、动手动脑
以下代码为何无法通过编译?
public class Test
{
  public static void main(String [] args){
            Foo obj1=new Foo();
      }
}


class Foo{
   int value;
     public Foo(int initValue){
     value=initValue;
      }
}
通过编译发现该代码无法运行,查找发现类里面提供了有参构造方法,系统没有提供默认构造方法,无法被调用
结论:
当类里面没有构造方法时,系统自己提供一个默认构造方法
当类里面有了自定义的构造方法时,系统不会再提供默认构造方法,如果需要无参构造方法,需要自己定义。

六、类的初始化块
类的初始化块:在类中使用{和}将语句包围起来,直接将其作为类的成员
public class InitializeBlockDemo {

    /**
     * @param args
     */
    public static void main(String[] args) {
        
        InitializeBlockClass obj=new InitializeBlockClass();
        System.out.println(obj.field);
        
        obj=new InitializeBlockClass(300);
        System.out.println(obj.field);
    }

}

class InitializeBlockClass{
    //下面这句在初始化块之前与之后,会影响到field字段的初始值
    //public int field=100;
    
    {
        field=200;
    }
    public int field=100;
    public InitializeBlockClass(int value){
        this.field=value;
    }
    public InitializeBlockClass(){
        
    }
}

通过运行以上代码,结果为

100

300

通过该结果可以看出 java字段初始化的规律为

在使用默认构造方法时,初始化块和public定义的变量,两个都调用,谁在后面就初始化为谁
类的初始化块不接受任何参数,一旦被调用就会执行,用于封装一些必须被执行的代码

七、静态初始化块
动手动脑
静态即加一个static关键字
package practice;



class Root
{
    static
    {
        System.out.println("Root的静态初始化块");
    }
    {
        System.out.println("Root的普通初始化块");
    }
    public Root()
    {
        System.out.println("Root的无参数的构造器");
    }
}
class Mid extends Root
{
    static
    {
        System.out.println("Mid的静态初始化块");
    }
    {
        System.out.println("Mid的普通初始化块");
    }
    public Mid()
    {
        System.out.println("Mid的无参数的构造器");
    }
    public Mid(String msg)
    {
        //通过this调用同一类中重载的构造器
        this();
        System.out.println("Mid的带参数构造器,其参数值:" + msg);
    }
}
class Leaf extends Mid
{
    static
    {
        System.out.println("Leaf的静态初始化块");
    }
    {
        System.out.println("Leaf的普通初始化块");
    }    
    public Leaf()
    {
        //通过super调用父类中有一个字符串参数的构造器
        super("Java初始化顺序演示");
        System.out.println("执行Leaf的构造器");
    }

}

public class TestStaticInitializeBlock
{
    public static void main(String[] args) 
    {
        new Leaf();
        

    }

}

通过运行可以知道:

  • 静态初始化块只执行一次。
  • 创建子类型的对象时,也会导致父类型的静态初始化块的执行。

八、一个有趣的问题:如何在静态方法中访问类的实例成员
public class Test
{
 int x = 3;//类的实例变量,初始化值为3
 static int  y = 4;//类的静态变量,初始化值为4
 public static void method()//静态方法
  {
   System.out.println("实例变量x = " + new Test().x);//在静态方法中访问类的实例变量需首先进行类的实例化
   System.out.println("静态变量y = " + y);//在静态方法中可直接访问类的静态变量
  }

 public static void main(String[] args)
    {
         Test.method();
        Test ex = new Test();
        System.out.println("x = " + ex.x);
    }
}


在外部调用静态方法时,可以使用"类名.方法名"的方式,也可以使用"对象名.方法名"的方式。而实例方法只有后面这种方式。也就是说,调用静态方法可以无需创建对象。


静态方法在访问本类的成员时,只允许访问静态成员(即静态成员变量和静态方法),而不允许访问实例成员变量和实例方法;实例方法则无此限制。

 
posted @ 2022-10-04 22:19  伽澄  阅读(21)  评论(0编辑  收藏  举报