Java 教程 在线

1281Java 对象和类

错误: CMD 编译 Java 源文件时出现的编码 GBK 的不可映射字符的错误。

办法:使用 javac -encoding UTF-8 .java 指定编码形式。

原因:由于 JDK 是国际版的,在编译的时候,如果我们没有用 -encoding 参数指定 JAVA 源程序的编码格式,则 java.exe 首先获得我们才做系统默认采用的编码格式,也即在编译 JAVA 程序时,若我们不指定源程序文件的编码格式,JDK 首先获得操作系统的 file.encoding 参数(它保存的就是操作系统默认的编码格式,如 win2k,他的值为 GBK),然后 JDK 就把我们的 JAVA 源程序从 file.encoding 编码格式转化为 JAVA 内部默认的 UNICODE 格式放到内存中。之后,javac 把转换后的 UNICODE 格式的文件进行编译成 class 类文件,此时 .class 文件是 UNICODE 编码的,它暂放在内存中,紧接着,JDK 将此以 UNICODE 编码编译后的 .class 文件保存到操作系统中形成我们见到的 .class 文件。但我们不加设置就编译时,相当于使用了参数: javac -encoding gbk xx.java,就会出现不兼容的情况。

1280Java 对象和类

JAVA 和 C++ 一样,若是不定义任何的构造函数,会自动构造;如果定义了任何一个构造函数,就不会再自动构造,需要自己定义全部的构造函数。

//一个带显式构造函数的类
Public class People{
    int age = 23;
        Public void getAge(){
        System.out.print("the age is "+ age);
    }
    // 显式声明一个带参数的构造函数,用于初始化年龄
    Public People(int a){
        this.age = a; 
    }
}

//用这个类来实例化一个对象
People xiaoMing = new People(20); // 使用带参数的构造函数来实例化对象
People xiaoMing2 = new People();  // ERROR:一旦显示定义了一个构造函数,就不会再生成默认的构造函数
xiaoMing.getAge(); // 打印出来的年龄变为20

1279Java 对象和类

更多内容参考:Java 中 this 和 super 的用法总结

  • this 指向对象本身的指针,形参与成员名字重名,用 this 来区分。
  • super 超(父)类对象的一个指针。

对构造函数对引用:

class Person { 
    public static void prt(String s) { 
       System.out.println(s); 
    } 
   
    Person() { 
       prt("父类·无参数构造方法: "+"A Person."); 
    }//构造方法(1) 
    
    Person(String name) { 
       prt("父类·含一个参数的构造方法: "+"A person's name is " + name); 
    }//构造方法(2) 
} 
    
public class Chinese extends Person { 
    Chinese() { 
       super(); // 调用父类构造方法(1) 
       prt("子类·调用父类”无参数构造方法“: "+"A chinese coder."); 
    } 
    
    Chinese(String name) { 
       super(name);// 调用父类具有相同形参的构造方法(2) 
       prt("子类·调用父类”含一个参数的构造方法“: "+"his name is " + name); 
    } 
    
    Chinese(String name, int age) { 
       this(name);// 调用具有相同形参的构造方法(3) 
       prt("子类:调用子类具有相同形参的构造方法:his age is " + age); 
    } 
    
    public static void main(String[] args) { 
       Chinese cn = new Chinese(); 
       cn = new Chinese("codersai"); 
       cn = new Chinese("codersai", 18); 
    } 
}

运行结果:

父类·无参数构造方法: A Person.
子类·调用父类”无参数构造方法“: A chinese coder.
父类·含一个参数的构造方法: A person's name is codersai
子类·调用父类”含一个参数的构造方法“: his name is codersai
父类·含一个参数的构造方法: A person's name is codersai
子类·调用父类”含一个参数的构造方法“: his name is codersai
子类:调用子类具有相同形参的构造方法:his age is 18

1278Java 对象和类

内部类:将一个类的定义放在另一个类的定义内部,这就是内部类。

如同一个人是由大脑、肢体、器官等身体结果组成,而内部类相当于其中的某个器官之一,例如心脏:它也有自己的属性和行为(血液、跳动)

显然,此处不能单方面用属性或者方法表示一个心脏,而需要一个类,而心脏又在人体当中,正如同是内部类在外部类当中。

1)不用内部类:

public class Person {
    private int blood;
    private Heart heart;
}

public class Heart {
    private int blood;
    public void test() {
        System.out.println(blood);
    }
}

2)使用内部类:

public class Person {
    private int blood;
    public class Heart {
        public void test() {
            System.out.println(blood);
        }
    }

    public class Brain {
        public void test() {
            System.out.println(blood);
        }
    }
}

内部类优点和缺点:

  • 优点:可访问外部类私有属性(心脏可访问身体的血液,而不是外部抽血)。
  • 缺点:破坏原有类的程序结构(属性、构造方法、普通方法、内部类)。

应用举例

//外部类
class Out {
    private int age = 12;
     
    //内部类
    class In {
        public void print() {
            System.out.println(age);
        }
    }
}
 
public class Demo {
    public static void main(String[] args) {
        Out.In in = new Out().new In();
        in.print();
        //或者采用下种方式访问
        /*
        Out out = new Out();
        Out.In in = out.new In();
        in.print();
        */
    }
}

运行结果:12

从上面的例子不难看出,内部类其实严重破坏了良好的代码结构,但为什么还要使用内部类呢?

因为内部类可以随意使用外部类的成员变量(包括私有)而不用生成外部类的对象,这也是内部类的唯一优点。

如同心脏可以直接访问身体的血液,而不是通过医生来抽血。

程序编译过后会产生两个 .class 文件,分别是 Out.class 和 Out$In.class。

其中 $ 代表了上面程序中 Out.In 中的那个。

Out.In in = new Out().new In() 可以用来生成内部类的对象,这种方法存在两个小知识点需要注意:

  • 1.开头的 Out 是为了标明需要生成的内部类对象在哪个外部类当中。
  • 2.必须先有外部类的对象才能生成内部类的对象,因为内部类的作用就是为了访问外部类中的成员变量。

实例2:内部类中的变量访问形式

更多详细内容可参考:

java 中的内部类总结

Java 内部类详解

1277Java 对象和类

成员变量和局部变量区别

1.声明位置不同

成员变量也就是属性,在类中声明的。

局部变量,在方法中声明或代码块中声明。

2.初始值不同

成员变量如果没有赋值则是有默认值的,数据类型不同则默认值不同。

局部变量是没有默认值,也就是说必须先声明,再赋值,最后才使用。

3.在一个类中,局部变量可以与成员变量同名,但是局部变量优先,如果非要访问成员变量的属性,则必须使用 this.color

this 代表当前这个对象,也就是当前谁调用这个方法则这个对象就是谁。

对象与引用区别

对象是具体的一个实例,如:new Student(); new 表示创建一个对象,并在堆内存中开辟一块空间。

引用名称是存放的对象的地址。