java快速入门
遗产在上一篇文章中,我们已经介绍了面向对象编程的一个重要概念,即封装。 这些文章不是有关面向对象编程的文章,而是有关Java编程的文章,但是我将介绍面向对象编程的所有重要方面,因为Java完全支持面向对象
即使它不是完全面向对象的语言(从某种意义上讲,您可以使用Java编写非面向对象的程序)也可以进行编程。
本文重点讨论继承,继承是面向对象编程中非常重要的概念,并且是Java编程语言设计中的重要因素。
但是,我确实保证首先要看String类,所以这里是这样:
旁:Java中的字符串Java中的字符串文字是java.lang.String类的实例。 字符串文字可以通过用双引号“”引起来识别。 字符串本质上是一个字符数组。 (稍后将查看数组)。 认识到Java字符串是常量,其值不能更改(不可变),就像整数文字3或Java中的任何其他文字一样,这一点非常重要。 这意味着,一旦创建了字符串,字符串将保持不变,直到将其从内存中删除为止。 因此,让我们在这里真正弄清一切。 字符串类型与字节,整数,双精度型,字符型和长型类型不同,因为字符串类型实际上是一个类,而所有其他类型都是原始类型,并且不是从任何类构造的。 但是,字符串文字本身就是常量,它们的值不会改变。 因此,当您使用诸如concat之类的字符串方法时,请勿修改调用该方法的字符串
String hello = "Hello";
String world = " World";
hello.concat(world);
System.out.println(hello);
在屏幕上打印Hello。
调用该方法不会更改字符串文字“ Hello”,因为文字值无法更改。
但是,该调用创建了一个新的String并返回了它。
我只是在那里没有使用它。
为了看到它,我们将其分配给一个字符串变量,例如
String hello = "Hello";
String world = " World";
String helloWorld = hello.concat(world);
System.out.println(helloWorld);
您可以更改字符串变量引用的值。
让我们来看一下:
String string = "something";
可变字符串指的是文字“东西”。
从这一刻起,“某物”将永远是“某物”。
无论我们对变量字符串做什么,文字都不会改变。
但是,如果我们接下来写:
string = "nothing";
现在,字符串是指文字“ nothing”。
我们没有将“某物”更改为“一无所有”。
我们只是从文字“某物”中删除了对文字“什么都没有”的引用。
这应该很好理解。
您可能会注意到,我们不再有任何涉及“某物”的信息。
这当然很有趣(事实上如此有趣,以至于我们有一天可能会全班学习)。
当你做
1.String s = "hello";
2.s = s.concat(" world");
您可以在第1行中创建一个引用文字“ hello”的变量,这很好。
在第2行中,首先创建一个字符串,该字符串的s所指的文字与该文字“世界”连接在一起,然后将s所指的值从“ hello”更改为新创建的
串。 没有字符串被扩展。 仅将引用从引用较短的字符串更改为引用较长的字符串。 当然可以了。 我特意为此花费了很长的时间,因为一旦您掌握了这一点,其余的字符串操作将更加容易。
让我们暂时减少继承,并将其保留到下一个地方。
Defn:继承我们称其为类或接口(我们将在本文结尾处介绍接口)使用另一类(或接口)的属性和方法的子集的能力,并增加了添加其自身的属性和功能的能力。方法。 这里要记住一些要点:
1.)继承发生在类或接口级别。 类从其他类继承,接口从其他接口继承。 不混合。 (我们将看到一个人实际上是另一个人的老板,所以他们真的不应该混在一起)。
2.)如果类B从类A继承,则并不意味着类B的所有属性和方法都可以在类B中访问。可以隐藏某些属性和方法,以使它们在继承类中不可访问。
3.)继承类可以添加自己的属性和方法。 通常是这种情况,否则它们将不会在程序中引入新类。
4.)小心,构造函数不是继承的!
这是一个例子
class Animal {
boolean domestic;
public Animal () {
}
public Animal(boolean domestic) {
this.domestic = domestic;
}
public boolean isDomestic() {
return domestic;
}
}
class Cat extends Animal {
public Cat(boolean domestic) {
this.domestic = domestic;
}
public String toString() {
return "This cat domestic?:"+isDomestic();
}
}
class Dog extends Animal {
public Dog(boolean domestic) {
this.domestic = domestic;
}
public String toString() {
return "This dog domestic?:"+isDomestic();
}
}
public class AnimalTest{
public static void main(String[] args) {
System.out.println(new Dog(false).toString());
System.out.println(new Cat(true).toString());
}
}
关键字extends用于定义继承关系。
在Dog和Cat类中都继承了变量domestic和方法isDomestic。 无需再次重新声明它们。 就像在此处定义它们一样使用它们。
现在不要说错话。 术语是,继承的类称为子类,而从其继承的类称为超类。 因此,在这种情况下,“狗”和“猫”是“动物”的子类。
除Object类外,每个用Java编写的类都只有一个超类。 那就是继承对Java的重要性。 您要编写的每个类都将有一个超级类。 如果没有超类,则所有类直接从对象类继承;如果具有超类,则间接从对象类继承。 您不必在类中扩展Object,这会自动为您完成。 对象类包含一个默认构造函数,当您从没有构造函数的类中实例化对象时,该构造函数会自动调用。
在Java中,您不能从多个类中继承(不允许直接多重继承)。
超级关键字如果您有一个从类A继承的类B,则可以使用关键字super提供与要调用的构造函数相匹配的参数,从而在类B的任何构造函数中调用类A的构造函数。 为此,使用super进行的构造函数调用必须是构造函数的第一条语句。 追逐,
class Product {
String code;
double price;
public Product() {
code = "No code";
price = 0.0;
}
public Product(String code, double price) {
this.code = code;
this.price = price;
}
public void setCode(String code) {
this.code = code;
}
public String getCode() {
return code;
}
public void setPrice(double price) {
this.price = price;
}
public double getPrice() {
return price;
}
}
class DVD extends Product {
String title;
}
我在那里上了两节课。
产品看起来确实穿着很好,而关于DVD类可以说很多。
如果我们编写另一个类(您现在应该这样做),称为TestProducts,那么我们可以使用提供的两个构造函数中的任何一个在其main方法中创建Products。
Product useless = new Product();
Product better = new Product("0001", 2.50); //well you can call your variables anything that is not a keyword
现在,在代码中说DVD扩展了产品。
让我们探讨一下含义:
DVD dvd = new DVD();
编译器允许这样做。
但是,这里有一个窍门。
new DVD()调用DVD类中的不带参数的构造函数。
不幸的是,代码中没有这样的东西。
这就是使用super关键字的时候。
在DVD类中看不到任何构造函数,编译器首先为DVD插入默认的构造函数(我们在上一类中这样做),然后在该构造函数中插入super()行。
这将在类DVD的直接超类中调用默认构造函数,本例中为Product。 所以代码
DVD dvd = new DVD();
System.out.println(dvd.getCode());
在屏幕上打印“ No code”,因为Product的默认构造函数将代码初始化为字符串“ No code”。
这就是Java中的构造函数。
在编写课程时,请确保牢记这些内容。 当然,如果您打算使用该类来创建对象,则除了测试类之外的所有类都应具有构造函数。
现在观看,将DVD类更改为
class DVD extends Product {
String title;
public DVD (String title) {
this.title = title;
}
}
进行编译时,找不到符号:构造函数DVD()。
这说明了两个要点。 我们已经看过的第一点是,如果一个类至少包含一个构造函数,则编译器不会自动创建默认构造函数。 这就是为什么编译器说DVD没有no-arg构造函数的原因。
第二点是构造函数不被继承。 超类Product包含一个默认构造函数,但DVD类中的编译器将忽略它,因为DVD中现在有一个构造函数,因此未添加任何调用超类构造函数的构造函数。 现在,这是每个Java程序员都必须完全理解的东西。
DVD类别更体面的是
class DVD extends Product {
String title;
public DVD() {
super();
title = "No title";
}
public DVD (String code, double price, String title) {
super(code, price);
this.title = title;
}
public void setTitle(String title) {
this.title;
}
}
注意super的正确使用。
在no-arg构造函数中,对super的调用将按照Product的no-arg构造函数指定的代码和价格进行初始化。
之后,构造函数将初始化仅DVD独有的标题。
第二个构造函数执行类似的操作,但是这次在Product中调用两个参数的构造函数。
这显示了继承的一大优势。
代码重用。
通过说DVD扩展了产品,我们没有说过在DVD中重新声明代码和价格,我们已经说过DVD具有这两个属性。
无需在DVD类中初始化代码和价格,我们只需使用super关键字来调用已经编写的代码即可。
在此特定示例中,Product类中的所有方法(getter和setter)在DVD类中也可用。
我们已将产品从产品继承到DVD的所有内容,并添加了
自己的属性,标题。 在这一点上,您可能想了解关键字“ this”和“ super”之间的区别。 回想一下,“ this”调用同一类中的构造函数,并且必须是该构造函数的第一条语句,而“ super”调用其“直接超类”构造函数,并且还必须是该构造函数的第一行。
何时使用继承现在您知道了继承是如何完成的,让我们看看它何时完成。 嗯,但是首先为什么要使用继承? 继承促进代码重用和多态性。
我们已经看到了代码重用部分,在这些部分中,当它们确实具有相同的定义时,就不要再定义与定义相同的东西。 我们不久将介绍多态性。 因此,当您要使用它时,基本上就是您拥有一个通用类型以及该通用类型的几个更特定的类型。 要使用的关系是is-A关系。 DVD是A产品,因此DVD扩展了Product。 秘书是-员工,因此秘书扩展了Employee。 员工是人,因此员工扩展了人。 我确定您现在可以提出其他一些无聊的示例。
访问修饰符和继承我暗示子类无法访问其超类的所有属性和方法的可能性。 这是使用访问修饰符完成的。
public-标记为public的变量(包括方法)在同一包和其他包中的所有类中均可用。 它对公众开放。
protected-标记为protected的变量可以在它们所属的类中以及该类的子类中访问。 请记住,如果未指定,则为默认访问权限。
专用-专用变量仅在它们所属的类中可见。
class Product {
private String code;
private double price;
public Product() {
code = "No code";
price = 0.0;
}
public Product(String code, double price) {
this.code = code;
this.price = price;
}
}
class DVD extends Product {
String title;
public DVD() {
super();
title = "No title";
}
public DVD (String code, double price, String title) {
super(code, price);
this.title = title;
}
}
然后做
DVD dvd = new DVD();
System.out.println(dvd.code);
将使编译器抱怨试图访问DVD中产品的私有成员代码。
如果您对某人感到害羞,并且碰巧在走廊上遇到他们,却不知道要考虑什么,则可以(当然是无声地)与自己争论私有变量是否是继承的并且不能在子类中访问或根本不继承。
现在让我们再次回顾封装,并在其上添加更多内容。 我说过Java代码封装在类中,而类属性封装在方法和字段中。 在好的程序中,数据应仅在需要的地方可用。 您不应四处走动,并在程序中不必要地公开数据。 一些数据应该被隐藏。 如果某人想知道产品的价格,请给他们价格,而不是所有有关该产品的数据。 给出所有产品数据会在产品类中暴露其他信息,我们可能希望将其保密。 如果我们有偏见
计算产品中的价格方法,我们当然不希望所有人看到它。 那就是我们使用private关键字的地方。 如果我们将类中的所有属性和方法都定义为私有,那么其他任何类都无法从该类外部访问这些属性和方法。 从我们的类继承是没有用的,因为我们不能从超类访问任何东西。 通常,您将在类中定义为私有的字段中看到字段,然后具有用于获取这些字段或设置其值的公共方法。 像这样
class Product {
private String code;
private double price;
public double getPrice() {
return price;
}
public String getCode() {
return code;
}
}
class DVD extends Product {
}
这意味着所有扩展Product的类都不能使用点运算符直接访问代码和价格属性,但可以使用提供的getter进行访问,因为这些getter是公共的,因此可以在子类中访问。
DVD d = new DVD();
d.code;
会给出一个错误,但是
d.getCode();
允许,因为getCode()是公共的。
您经常会看到类中定义的每个私有字段的getter和setter方法。 这真是太糟了。 它首先破坏了将字段私有化的目的。 您应该仅向希望在子类中访问的字段提供获取器和设置器。
class Product {
private String code;
private double price;
private final double addedProfit = 500;
public Product(String code, double price) {
this.code = code;
this.price = price;
}
public double getPrice() {
return price + addedProfit;
}
public String getCode() {
return code;
}
}
class DVD extends Product {
String title;
public DVD(String code, double price, String title) {
super(code, price);
title = title;
}
}
在此产品类别中,即使扩展类别,所获得的利润也保持秘密。
人们可以得到价格,但不知道价格中已包含增加的利润。
addProfit字段没有吸气剂。 现在
DVD d = new DVD("001", 500, "Test");
System.out.println(d.getPrice());
打印1000.0。
DVD类对增加的利润一无所知,但是每次创建价格为x的DVD时,其上的getPrice将始终给出x +500。这表明私有字段实际上是继承的,但不能在子类中访问。
DVD中有增加的利润,但DVD类中无法访问字段addProfit。
那不是很整洁吗?
练习这些事情并弄清楚它们,它们是使我们一次又一次地回到Java编译器的小事情。
让我们从继承中休息一下,然后再次来看一下覆盖
旁:数组和字符串当必须存储许多相同类型的数据时,Java中有一个数组类型可以比拥有许多单独的变量更有效地存储数据。
如果要为某人存储十个分数,则可以使用以下命令定义十个int变量:
int score1;
int score2;
int score3;
//...e.t.c
如果您使用相同的方法来存储500个分数,您会感到疲劳。
因此,应用程序会在设计中展示自己。
每当您需要将许多东西存储在您的
程序需要一种能够在一个变量中存储许多项目的数据类型,数组是一种选择。 现在,数组只能存储相同类型的项目。 您不能存储
int和同一数组中的double。 您可以将类类型(或接口类型)的对象存储在数组中。 因此,您可以拥有产品阵列,DVD阵列等。阵列的另一个重要属性是阵列具有固定的大小。 数组对象只能存储相同数量的对象。 要定义大小为10的int数组
int[] scores = new int[10];
要么
int scores[] = new int[10];
我喜欢第一种方法,因为这样您就可以将其读取为int数组,scores是大小为10的数组。
您可以声明一个数组,而无需使用int []分数对其进行初始化; 您可以在以后知道代码的大小时在代码中对其进行初始化。 要将项目添加到初始化的数组,您需要知道数组中您要首先放置该项目的位置。 然后您只需分配为
scores[index] = value;
其中index是整数,值是数组类型。
数组索引从零开始。
请注意,数组索引可以是字节,字符,整数,但不能长。
Sun的家伙们刚刚决定,他们不允许将long类型用作索引,仅此而已。
如果您尝试在数组大小之外的位置设置值,则代码会编译,但在运行时会给出Exception(我们将在下一篇文章中介绍异常)。
因此,在编译时检查数组类型,但在运行时检查数组索引。
以下代码演示了这些内容:
double[] test; //declaration without initialization
int i = 5;
long l = 20l;
test = new double[i]; //initializing the array same as test = new double[5];
//test = new double[l]; error. long cannot be used as array index
test[0] = 3.5; // the first position in the array is now filled with the double 3.5
test[5] = 4.0 //compiles but gives runtime exception
如果将数组定义为
Type[] array = new Type[x];
其中Type是数组的类型(原始或其他),x是有效的索引值,那么您将获得一个具有可访问位置的数组array [0],array [1],array [2],...,array [ x-1]。
这些是数组中的x个位置(从0到x-1)。
访问array [x]将给出运行时异常。
数组可以是任何维度。
要声明一个n维数组,只需使用n []作为声明。 例如2 dim int数组定义为
int[][] twoDim = new int[5][8];
是的,你可以写
int twoDim[][] = new int[5][8];
注意
int[][] twoDim = new int[5][];
被允许但是
int[][] twoDim = new int[][5];
不被允许。
您将乐于对此进行研究。
让我们再次将这些字符串带回图片中。 如果您对自己有好处,那么您可能已经在考虑String只是字符数组。 String类中的某些方法返回数组。 例如,要将字符串分解成其组成字符,只需按如下所示调用toCharArray()方法
String abc = "abc";
char[] chars = abc.toCharArray();
并且chars现在是大小为3的char数组,其中chars [0] =='a',chars [1] =='b'和chars [2] =='c';
一个更有用的方法是String类中的split方法,该方法根据您提供给此方法的参数将字符串拆分为子字符串。 最简单的示例是使用字符(最常见的是空格字符)分割字符串。
String s = "This is a stupid string";
String[] stupid = s.split(" ");
在这里s.split(“”);
使用参数“”(空格)调用split()方法。
这将使用空格将字符串分解成字符串数组。
因此,在这种情况下,愚蠢的数组现在包含组成句子s的单词。
如有需要,请务必使用此方法。
它将简化字符串的大部分工作。
java.util包中有一个名为Arrays的类,它具有一些可用于数组的有用方法。 其中的关键方法是排序,二进制搜索和toString。 您应该编写一个程序来测试其用途
并熟悉它们。
现在让我们回到继承,并在重载上继承它。
Dfn:重写是指类中的实例(非静态)方法与该类的父类中的方法具有相同的签名(名称参数类型和顺序),并且返回类型也相同。 从1.5版本开始,重写方法还可以返回重写方法返回的类型的子类型。 这称为协变返回类型。
class A {
int a = 0;;
public int getA() {
return a;
}
}
class B extends A {
public int getA () {
return a + 2;
}
}
new A().getA();
返回0
但
new B().getA();
返回2;
一些注意事项。
具有继承时会发生覆盖。 没有继承,就没有超类方法可以覆盖。 从1.5开始编译
1. class A {
2. int a;
3. public Object getA() {
4. return a;
5. }
6. }
7. class B extends A {
8. public Number getA () {
9. return a + 2;
10. }
11. }
请注意,如何自动将A类中的a装箱到Integer,然后将其作为正确的返回类型被接受。
本质上,第4行被视为
return new Integer(a);
现在,类B中的重写方法返回一个类型为Number的对象,该对象是Object类的子类,因此,重写被编译器接受。
翻译自: https://bytes.com/topic/java/insights/740392-quick-introduction-java-concepts-2-a
java快速入门
本文深入探讨Java中的继承概念,包括子类与超类的关系、构造函数的使用、访问修饰符的作用,以及代码重用和多态性的实现。同时,详细解析Java字符串的特性,如不可变性、字符串字面量的识别及字符串方法的使用。

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



