类与对象
面向对象(Object Oriented)
一、面向对象
三大特性:
- 封装性:对象的成员属性和行为看做一个不可分割的整体,一些不想让外界看到的方法也隐藏起来
- 继承性:java是类的单继承,接口的多继承,是从一个基础的类上派生出反应一些特殊性的类,如几何类下面可以包括圆类,正方体类等
- 多态性:多态是指程序中允许出现重名现象。
- 方法重载:根据函数参数的不同,允许同名函数完成不同的工作
- 对象多态:子类对象可以和父类对象相互转换,根据其使用的子类不同完成的功能也不同,比如几何类实例对象,new Circle()和new Cube()是不同的,但是都可以用Gemometric定义
二、类与对象
一个类完成定义后,描述的只是一个广泛的概念,其具体操作必须通过对象来完成,格式如下:
类名称 对象名称 = new 类名称()
或者进行分步定义:
类名称 对象名称 = null对象名称 = new 类名称()
然后采取以下方法进行类结构的操作
- 对象.成员属性:表示调用类中的成员属性,可以为其赋值或者获取其保存内容
- 对象.方法():表示调用;类中的方法
public class ObjectDemo {
public static void main(String[] args) {
Person person = new Person("张三", 15);
System.out.println(person.tell());
}
}
class Person{
private String name;
private int age;
public Person(String name, int age){
this.name = name;
this.age = age;
}
public String tell(){
return "姓名: "+this.name+"、 年龄: "+this.age;
}
}
1. 对象内存分析
类属于引用数据类型,在使用过程中都要通过关键字new开辟新的内存空间,才能实现成员属性的信息保存
- 【heap】堆内存:保存的是对象的具体信息(成员属性),在程序之中内存空间的开辟是通过关键字new进行的
- 【stack】栈内存:保存的是一块堆内存的地址,可以通过地址找到内存,然后找到对象内容。
类中的成员属性都是每个对象私有的,而类中的方法是所有对象共有的,方法的信息会存储在“全局方法区”这样的公共内存中
NullPointerException表示的是没有正确实例化对象,也就是有地址,但是地址所指向的内存为空
public class ObjectDemo {
public static void main(String[] args) {
Person person1 = new Person("张三", 15);
Person person2 = person1; // 引用传递,此时person2的地址指向person1的地址,然后指向person1的内存
System.out.println(person1.tell());
System.out.println(person2.tell());
}
}
class Person{
private String name;
private int age;
public Person(String name, int age){
this.name = name;
this.age = age;
}
public String tell(){
return "姓名: "+this.name+"、 年龄: "+this.age;
}
}
当使用引用传递时,要注意栈内存只能保存一个堆内存的信息,当发生指向改变时需要断开原有连接,进行新的连接,此时原有指向的堆内存就没有了入口,成为垃圾,需要GC(Garbage Collection)垃圾回收器不定期的进行回收释放
三、成员属性封装
使用private进行属性的封装,只能够在该类中进行调用,外部无法使用,此时应该提供getter,setter方法来获取和修改private属性。
四、构造方法与匿名对象
构造方法在实例化对象时默认调用new,完成对象属性的初始化操作
- 构造方法的名称必须与类名保持一致
- 构造方法没有返回值类型声明
实例化类时会默认生成一个无返回值无参数的构造方法,如果类中明确定义了一个构造方法,则不会自动生成无参无返回值的构造方法,也就是一个类中至少存在一个构造方法
构造方法也可进行重载,而且只需考虑参数类型及个数即可
public class ObjectDemo {
public static void main(String[] args) {
Person person1 = new Person("张三"); // 使用单参数构造方法,年龄为默认值0
System.out.println(person1.tell());
}
}
class Person{
private String name;
private int age;
public Person(String name, int age){
this.name = name;
this.age = age;
}
public Person(String name){
this.name = name;
}
public String tell(){
return "姓名: "+this.name+"、 年龄: "+this.age;
}
}
匿名对象只能在创建的时候使用一次,由于没有入口,以后就无法调用
public class ObjectDemo {
public static void main(String[] args) {
System.out.println(new Person("张三", 18).tell())
}
}
在构造方法为属性初始化的过程中,除了可以传递一些数据的参数之外,也可以接受引用数据类型的内容
public class ObjectDemo {
public static void main(String[] args) {
Person person1 = new Person(new Message(), 18);
System.out.println(person1.tell());
}
}
class Person{
private String name;
private int age;
public Person(Message msg, int age){
this.name = msg.getInfo();// 接收引用数据的方法
this.age = age;
}
public String tell(){
return "姓名: "+this.name+"、 年龄: "+this.age;
}
}
class Message{
private String content = "李王八";
public Message(String content){
this.content = content;
}
public Message(){} // 定义了构造方法后,如果想要使用无参构造,必须再定义一下无参构造,否则不能使用
public String getInfo(){
return this.content;
}
public void setInfo(String newConetent){
this.content = newConetent;
}
}
五、this关键字
this描述的是本类结构调用的关键字,在Java中this关键字可以描述3中结构的调用
- 当前类中的属性:this.属性
- 当前类中的方法(普通方法、构造方法):this()、this.方法名()
- 描述当前对象
1. this调用本类属性
public class ObjectDemo {
public static void main(String[] args) {
Person person = new Person("张三", 15);
System.out.println(person.tell());
}
}
class Person{
private String name;
private int age;
public Person(String name, int age){
this.name = name; // 将接收的参数name赋值给本类的属性name
this.age = age;
}
public String tell(){
return "姓名: "+this.name+"、 年龄: "+this.age;
}
}
2. this调用本类方法
public class ObjectDemo {
public static void main(String[] args) {
Person person1 = new Person("张老汉", 18);
person1.tell();
}
}
class Person{
private String name;
private int age;
public Person(){ // 应当保留一个没有this()的构造方法,作为程序的出口
System.out.println("创建了一个构造方法");
}
public Person(String name){
this(); // this()必须放在构造方法的第一行,因为调用别的属性的时候,构造方法必须第一个被调用
this.name = name;
}
public Person(String name, int age){
this(name);
this.age = age;
}
public void tell(){ // 普通方法不能使用this()调用构造方法
System.out.println("姓名: "+this.name+"、 年龄: "+this.age);
}
}
主要用途是面对多参构造,比如四个参数的构造方法,可以通过this依次调用,省去写多个赋值语句的问题
3. this表示当前对象
public class MyThreadDemo{
public static void main(String[] args) throws Exception{
new Message().printThis();
new Message().printThis();
}
}
class Message{
public void printThis(){
System.out.println("【message类】this = "+this );
}
}
输出:
【message类】this = Message@133314b
【message类】this = Message@b1bc7ed
可以看出this表示了不同的对象
六、static关键字
普通成员(非static)和静态成员(static)
1. static属性
如果想要类中的某个属性定义为公共属性(所有的对象都可以使用的属性),则可以加上static关键字
public class ObjectDemo {
public static void main(String[] args) {
Person person1 = new Person("张老汉", 18);
person1.tell();
}
}
class Person{
static String country = "China";
private String name;
private int age;
public Person(){
System.out.println("创建了一个构造方法");
}
public Person(String name){
this();
this.name = name;
}
public Person(String name, int age){
this(name);
this.age = age;
}
public void tell(){
System.out.println("姓名: "+this.name+"、 年龄: "+this.age+"、 国籍: "+ this.country);
}
}
static表示的公共属性,如果不使用static,则会为每个属性都创建一个country的对象,造成性能下降和内存浪费。
- static的属性内容不在堆内存中保存,而是存储在公共数据区
- 使用static的属性表示的是类属性,而不是某个对象的属性,类属性可以直接用类名调用(不提倡使用对象名调用类属性)
- 类属性static虽然定义在类中,但是可以在没有实例化对象的时候直接调用该属性,因为普通属性保存在堆内存中,需要有栈内存进行引用,而static属性保存在全局数据区
2. static方法
如果static定义了方法,则此方法可以在没有实例化对象的时候调用
public class ObjectDemo {
public static void main(String[] args) {
Person person1 = new Person("孙笑川", 88);
person1.tell();
Person.setCountry("日本平津");// 使用类名调用静态方法
Person.getCountry();
}
}
class Person{
static String country = "China";
private String name;
private int age;
public Person(){
System.out.println("创建了一个构造方法");
}
public Person(String name){
this();
this.name = name;
}
public Person(String name, int age){
this(name);
this.age = age;
}
public static void setCountry(String c){ // 静态方法修改静态属性
country = c;
}
public static void getCountry(){
System.out.println("国籍: " + Person.country); // 静态属性使用类名调用
}
public void tell(){
System.out.println("姓名: "+this.name+"、 年龄: "+this.age);
}
}
输出:
创建了一个构造方法
姓名: 孙笑川、 年龄: 88
国籍: 日本平津
一些注意事项:
- static方法不能调用非static的方法,因为类操作不能变成对象操作
- 但是对象的方法可以使用类方法,非static方法可以是调用static方法或属性
- 使用static的方法或属性,可以在没有实例化的时候调用,如果没有了实例化对象,也就没有了this关键字,所以static方法中无法使用this关键字的原因就在于此
- 非static方法的调用,必须通过实例化对象才能调用
public class ObjectDemo {
public static void main(String[] args) {
new Person("孙笑川", 88);
new Person("哮喘天皇", 24);
System.out.println(Person.getCount());
}
}
class Person{
private static int count = 0; // 类共同属性,不受实例化对象影响
private String name;
private int age;
public Person(String name, int age){ // 调用构造方法,会修改static属性count+=1
this.name = name;
this.age = age;
count += 1;
}
public static int getCount(){
return count;
}
}
七、代码块
代码块使用‘{}’定义起来的一段程序,根据声明位置不同和声明关键字不同,可以分为:普通代码块,构造代码块,静态代码块和同步代码块
1. 普通代码块
普通代码块是定义在方法中的代码块,可以解决代码块在一个方法中过长,导致出现变量重复定义的问题,例如
public class ObjectDemo {
public static void main(String[] args) {
if (true){
int x = 10;
System.out.println(x);
}
int x = 100;
System.out.println(x);
}
}
输出:
10
100
变量名就不会出现重复的问题,代码块相当于一个隔断
2. 构造代码块
将代码定义在一个类中,这样就成为了构造代码块,可以在使用关键字new实例化新对象的时候进行调用,例如
public class ObjectDemo {
public static void main(String[] args) {
new Person("孙笑川",22).tell();
}
}
class Person{
private static int count = 0;
private String name;
private int age;
public Person(String name, int age){
this.name = name;
this.age = age;
count += 1;
}
{// 定义在类中的构造代码块,优先于构造方法调用
System.out.println("调用了构造代码块");
}
public static int getCount(){
return count;
}
public void tell(){
System.out.println("姓名: "+this.name+"、 年龄: "+this.age);
}
}
3. 静态代码块
使用static定义的代码块
public class ObjectDemo {
public static void main(String[] args) {
new Person("孙笑川",22).tell();
new Person("莱莱",80).tell();
}
}
class Person{
private static int count = 0;
private String name;
private int age;
public Person(String name, int age){
this.name = name;
this.age = age;
count += 1;
}
static {// 静态代码块无论进行多少次实例化对象,只在第一次实例化时调用,且优先于构造方法调用
System.out.println("调用了构造代码块");
}
public static int getCount(){
return count;
}
public void tell(){
System.out.println("姓名: "+this.name+"、 年龄: "+this.age);
}
}
总结
- 面向对象的三大特性,继承性,封装性,多态性
- 对象是类的实例,类只能通过对象来使用
- 类的组成:成员属性(Field)、方法(Method)
- 如果一个对象没有被实例化而直接使用,就会出现空指向异常
- 类属于引用数据类型,传递的是堆内存的地址
- 类通过private进行封装,封装的属性不能被外部调用,只要是属性都要被封装
- JVM自动生成一个无参构造方法,如果自己设置了有参构造,则想要使用无参构造,必须重新定义一个无参构造
- this表示当前对象,this()调用本类的构造方法,但必须放在首行,且只能放在构造方法中
- static属性是公共的,static方法是类共有的
public class Book {
public static void main(String[] args) {
new BookClass("asodi",124.23).getInfo();
new BookClass("a12s", 12.42).getInfo();
new BookClass("xsdfa",2.42).getInfo();
}
}
class BookClass{
private static long bookNumber = 1000;
private static int count = 0;
private String name;
private double price;
public BookClass(String name, double price){
this.name =name;
this.price=price;
count++;
}
public double getPrice(){
return this.price;
}
public static long getBookNumber(){
return bookNumber+count;
}
public String getName(){
return this.name;
}
public static int getCount(){
return count;
}
public void getInfo(){
System.out.println("book name is "+this.name+"、price is "+"、the number is "+ BookClass.getBookNumber());
}
}
本文是关于Java中类与对象的学习笔记,详细介绍了面向对象的三大特性:封装性、继承性和多态性,并深入讲解了类与对象的概念,包括对象内存分析、成员属性封装、构造方法、this关键字、static关键字的使用以及代码块的作用。通过对这些概念的理解,有助于深化对Java面向对象编程的掌握。

被折叠的 条评论
为什么被折叠?



