java是一款面向对象语言,接下来进入java的入门
首先java是有类的概念,类由属性跟方法,而每个类跟属性都可以设置public跟private,区别就是能否被外部访问,就跟python中设置类属性,类方法一样,如果我们外部访问类的私有属性或方法,就会报错。
this指针始终指向调用者,与python一样
class Person{ public String name; private int age; public int getAge(){ return this.age; } public void setAge(int age){ this.age = age; } } public class HelloWorld { public static void main(String[] args) { Person p = new Person(); // p.age = 25; // Error:(18, 10) java: age 在 Person 中是 private 访问控制 p.name = "小明"; System.out.println(p.getAge()); // 0 p.setAge(25); System.out.println(p.getAge()); // 25 System.out.println(p.name); // 小明 } }
下面来看一下私有方法,从报错来看,私有方法如果外部访问也会报错,因此如果对于一些敏感信息,限制信息,可以定义为私有的,然后定义一个方法接口进行限制,然后在返回就可以了
class Person{ public String name; private int age; public int getAge(){ return this.age; } public void setAge(int age){ this.age = age; } private int xuSui(){ return this.age + 1; } public int getXuSui(){ return this.xuSui(); } } public class HelloWorld { public static void main(String[] args) { Person p = new Person(); // p.age = 25; // Error:(18, 10) java: age 在 Person 中是 private 访问控制 p.name = "小明"; p.setAge(25); // System.out.println(p.xuSui()); // Error:(27, 29) java: xuSui() 在 Person 中是 private 访问控制 System.out.println(p.getXuSui()); // 26 } }
看到初始化就想到,这个初始化难道没有构造方法吗?有的,接下来就来看一下构造方法
class Person{ private String name; private int age; // 构造方法 public Person(String name, int age){ this.name = name; this.age =age; } // 构造方法,一般如果我们没有创建构造方法,系统会给我们默认创建一个这样的构造方法 public Person(){} public String getName(){ return this.name; } public int getAge(){ return this.age; } } public class HelloWorld { public static void main(String[] args) { Person p1 = new Person(); Person p2 = new Person("小明", 25); System.out.println(p1.getAge()); // 0 System.out.println(p1.getName()); // null System.out.println(p2.getAge()); // 25 System.out.println(p2.getName()); // 小明 } }
从上述代码可以看出,一个类可以有多个构造方法,并且初始化如果没有赋值,默认为空值,那接下来我们看一下,这个赋值过程是什么样子的,如果在类内部声明属性的时候就给他个值是什么情况
class Person { private String name = "小红"; private int age = 18; // 构造方法 public Person(String name, int age) { this.name = name; this.age = age; } // 构造方法,一般如果我们没有创建构造方法,系统会给我们默认创建一个这样的构造方法 public Person() { } public String getName() { return this.name; } public int getAge() { return this.age; } } public class HelloWorld { public static void main(String[] args) { Person p1 = new Person(); Person p2 = new Person("小明", 25); System.out.println(p1.getAge()); // 18 System.out.println(p1.getName()); // 小红 System.out.println(p2.getAge()); // 25 System.out.println(p2.getName()); // 小明 } }
从结果可以看出,这个会执行属性的初始化,然后在执行构造方法
接下来,学了类了,我们在使用String.indexof时,不是有很多可以调用吗?那个就是方法重载,顾名思义,就是方法名,返回值都是一样的,可能就是参数以及代码块有所不同,如下所示
class Print { public void print() { System.out.println("null"); } public void print(char s) { System.out.printf("char:%s", s); } public void print(int s) { System.out.printf("int:%d", s); } public void print(float s) { System.out.printf("float:%f", s); } } public class HelloWorld { public static void main(String[] args) { Print p = new Print(); p.print(); // null p.print(‘a‘); // char:a p.print(1); // int:1 p.print(1.08f); //float:1.080000 } }
接下来看一下继承,继承的关键字就是extends,前端也是这个写的,所有的类除了基类,都有且仅有一个父类,如果没有extends类,默认是继承object类,跟python也是一样的
如果new一个子类,可以使用父类来声明,因此子类是包含父类的。
另外,类的实例也是可以进行转化的,但只能???子类向父类转化,不能反过来,转化为父类之后,就访问不到子类中的方法了;
class Person { private String name; // private定义的私有化,子类是访问不到的 protected int age; // 自身,子类及同一个包中类可以访问,外部包无法访问,外部包后续在说 public Person(String name, int age) { this.name = name; this.age = age; } public String getName() { return this.name; } } class Student extends Person { private float score; public Student(String name, int age, float score) { super(name, age); // 如果父类没有构造方法,或者构造方法参数不一致,会报错,super就是继承父类构造方法 this.score = score; } public float getScore() { return this.score; } public void print() { System.out.println(this.age); // 18 // System.out.println(this.name); // Error:(26, 32) java: name 在 Person 中是 private 访问控制 } } public class HelloWorld { public static void main(String[] args) { Person p = new Person("ming", 25); System.out.println(p.age); // 25 Student s = new Student("hong", 18, 60.0f); System.out.println(s.age); // 18 System.out.println(s.getName()); // hong System.out.println(s.getScore()); // 60.0 s.print(); Person m = new Student("mei", 30, 99.0f); // Student mm = new Person("mei", 30); // Error:(43, 22) java: 不兼容的类型: Person无法转换为Student System.out.println(m instanceof Person); // true instance中文意思实例,判断名是否是Person的实例 System.out.println(m instanceof Student); // true // System.out.println(m.getScore()); // Error:(46, 29) java: 找不到符号符号: 方法 getScore() 位置: 类型为Person的变量 m Student n = (Student) m; // 类型的强制转化 System.out.println(n instanceof Person); // true System.out.println(n instanceof Student); // true System.out.println(n.getScore()); // 99.0 } }
另外,关于这个声明是否可被访问的关键字的范围如下:
类内部 | 本包 | 子类 | 外部包 | |
public | √ | √ | √ | √ |
protected | √ | √ | √ | × |
default | √ | √ | × | × |
private | √ | × | × | × |
从上面的表中可以看出,private除了类内部,其他都访问不到。
接下来看一下多态:
@Override建议如果是重写方法的话要带上,这样编译器会帮助我们检查,要不然玩意手抖把参数写错了,那就是重载了。。
根据下面的例子,理解多态的含义:java实例调用的方法是基于运行时实际类型的动态调用,这就是多态
class Person { public String eat(String food) { System.out.println("Person eat something"); return food; } public void run() { System.out.println("Person running"); } public int cal(int s) { return s; } // final 可以指定该方法不可以被重写 final void tell() { System.out.println("Person is talking"); } } class Student extends Person { // 重写 override @Override // 非必需的,这个就是编译器会帮助我们在编译时检查错误 public String eat(String food) { System.out.println("Student eat something"); return food; } // 方法签名一样,但是返回值不一样,会报错 // @Override // java: 方法不会覆盖或实现超类型的方法 // public int run() { // java: Student中的run()无法覆盖Person中的run() 返回类型int与void不兼容 // System.out.println("Person running"); // return 1; // } // 重载 overload public int run(int s) { // Error:(18, 16) java: Student中的run()无法覆盖Person中的run() 返回类型int与void不兼容 System.out.println("Student running"); return s; } @Override public int cal(int s) { return super.cal(s) * 2; // super可以调用已经被覆盖的父类方法 } // @Override // public void tell(){ // ava: Student中的tell()无法覆盖Person中的tell()被覆盖的方法为final // System.out.println("Student is talking"); // } } public class HelloWorld { public static void main(String[] args) { Person p = new Person(); Person s = new Student(); s.eat("egg"); // Student eat something, 因此可以确定,java实例调用的方法是基于运行时实际类型的动态调用,这就是多态 // s.run(1); // 会报错,因为声明的是person类型,但是调用student方法 Student s1 = new Student(); s1.run(); // Person running 因为方法签名跟返回值不同,因此 run是重载 s1.run(1); // Student running System.out.println(p.cal(1)); // 1 System.out.println(s.cal(1)); // 2 这个也说明java是基于运行时候实例指向的类型进行动态调用 System.out.println(s1.cal(1)); // 2 s.tell(); // Person is talking s1.tell(); // Person is talking } }
看到一个例子,将如何扣税,对于多态讲的挺好,自己写了一下
class Income { protected double income; public Income(double income) { this.income = income; } public double getTax() { return income * 0.15; } } class NormalIncome extends Income { public NormalIncome(double income) { super(income); } // 重写getTax,个人超过五千要交0.1的税 @Override public double getTax() { if (this.income < 5000) { return 0; } return (this.income - 5000) * 0.10; } } class GWYIncome extends Income { public GWYIncome(double income) { super(income); } // 重写getTax,含义就是不交税 @Override public double getTax() { return 0; } } public class HelloWorld { public static void main(String[] args) { Income[] m = new Income[]{new Income(3000), new NormalIncome(5500), new GWYIncome(6000)}; double total = 0; for (Income i : m) { total += i.getTax(); } System.out.println(total); } }
工厂模式:
这个词应该很熟悉吧,比如说我定义了一个工厂,那我定义工厂必须实现定义车间,但我在这个类中不会进行具体实现,具体实现由子类实现,并且子类必须实现,
java的抽象类就是工厂模式,并且在声明类时,使用的时车类,而不是宝马类等。。
抽象类是无法实例化的,关键词是abstract,如果子类有必须实现的方法,那么需要在方法字段上声明
abstract class Car { protected int wheelNum; public Car(int num) { this.wheelNum = num; } public abstract void run(); public abstract void printWheelNum(); public void start() { System.out.println("car started"); } } class BMW extends Car { public BMW(int num) { super(num); } @Override public void run() { System.out.println("BMW is running"); } @Override public void printWheelNum() { System.out.printf("BMW wheel num %d", this.wheelNum); } } public class HelloWorld { public static void main(String[] args) { // Car c = new Car(); // java: Car是抽象的; 无法实例化 Car b = new BMW(4); b.run(); // BMW is running b.start(); // car started b.printWheelNum(); // BMW wheel num 4 } }
接口:这个go里面也有接口,感觉都差不太多,go里面的接口比java里面功能更多
java里面的接口使用:如果抽象类中没有属性,建议使用接口,另外一个类实现多个接口,类实现接口的关键词是implements,接口就是比抽象类更进一步抽象,另外接口中可以使用default关键字,这个这个方法可以不被重写,其余的要实现这个接口,必须实现其内部所有方法,如果实现了多了接口,想要调用全部方法,需要声明子类类型,否则使用对应接口方法,就用相应的接口类型,不要使用该接口为定义的方法
interface Car { void run(); int getWheelNum(); default void addWheelNum() { System.out.println(getWheelNum() + 1); } } interface Window { void printWindow(); } class BMW implements Car, Window { private int wheelNum; private String window; public BMW(int num, String window) { this.wheelNum = num; this.window = window; } @Override public void run() { System.out.println("BMW is running"); } @Override public void printWindow() { System.out.printf("BMW window is %s", this.window); } @Override public int getWheelNum() { return this.wheelNum; } } public class HelloWorld { public static void main(String[] args) { Car b = new BMW(4, "glass"); b.run(); // BMW is running b.addWheelNum(); // 5 System.out.println(b.getWheelNum()); // 4 // b.printWindow(); // java: 找不到符号 符号: 方法 printWindow() 位置: 类型为Car的变量 b Window a = new BMW(4, "glass"); // a.addWheelNum(); // java: 找不到符号 符号: 方法 addWheelNum() 位置: 类型为Window的变量 a a.printWindow(); // BMW window is glass } }
静态方法和静态属性
声明的关键字段是 static,这个属性跟方法是字段的,实例访问的时候,会先编程原类,为什么呢?
类有一个命名空间。实例对象有一个命名空间,如果实例对象中没有你要访问的东西,就回去类的命名空间中找。
class Person { private String name; public static int n; // 声明静态字段,只有类可以调用 public Person(String name) { this.name = name; } // 声明静态方法,只有类可以调用 public static void print() { // System.out.println(this.name); // java: 无法从静态上下文中引用非静态 变量 this,静态方法中无法使用this指针 System.out.println("i ma static print"); } public String getName() { return this.name; } } public class HelloWorld { public static void main(String[] args) { Person p1 = new Person("ming"); Person p2 = new Person("hong"); System.out.println(p1.n); // 0 这里为什么可以通过实例访问呢,是因为编译器已经将这个实例转化为类进行调用的n,下面调用静态方法相同 p1.n = 10; System.out.println(p2.n); // 10 Person.n = 100; System.out.println(p1.n); // 100 System.out.println(Person.n); // 100 p2.print(); // i ma static print Person.print(); // i ma static print } }
接口的静态属性
接口静态属性完整字段应该是:public static final int MALE= 1; 但是接口中属性只能定义静态的,因此就省略了
interface Person { int MALE = 1; void getMale(); } class Student implements Person { public void getMale() { System.out.println(this.MALE); } } public class HelloWorld { public static void main(String[] args) { Person p = new Student(); p.getMale(); // 1 Student s = new Student(); s.getMale(); //1 } }
包:
Java内建的package
机制是为了避免class
命名冲突;
JDK的核心类使用java.lang
包,编译器会自动导入;
JDK的其它常用类定义在java.util.*
,java.math.*
,java.text.*
,……;
包名推荐使用倒置的域名,例如org.apache
作用域:
如果不确定是否需要public
,就不声明为public
,即尽可能少地暴露对外的字段和方法。
把方法定义为package
权限有助于测试,因为测试类和被测试类只要位于同一个package
,测试代码就可以访问被测试类的package
权限方法。
一个.java
文件只能包含一个public
类,但可以包含多个非public
类。如果有public
类,文件名必须和public
类的名字相同。
Java内建的访问权限包括public
、protected
、private
和package
权限;
Java在方法内部定义的变量是局部变量,局部变量的作用域从变量声明开始,到一个块结束;
final
修饰符不是访问权限,它可以修饰class
、field
和method
;
一个.java
文件只能包含一个public
类,但可以包含多个非public
类。
原文:https://www.cnblogs.com/yangshixiong/p/12163034.html