目录
包(package)
1.包的出现
- 使用包的主要目的是保证类的唯一性。
- 包是组织类的一种方式。
1、如图,在工程text的src中,已经有Test类,此时你在src中创建命名为Test的类时,是不允许的。
如果你在工作中代码中写了一个 Test 类,然后你的同事也可能写一个 Test 类,你要去查看他的内容时,出现两个同名的类, 就会冲突, 导致代码不能编译通过。(此时我们可以在src中创建一个包,在包中定义一个Text类是可以的。)
2、如何创建包,在包中创建类
1) 在 IDEA 中先新建一个包: 右键 src -> 新建 -> 包;
2) 输入包名(如:net.csdn.blog);
3) 在包中创建类, 右键包名 -> 新建 -> 类, 然后输入类名(如:Test)即可;
4) 此时可以看到我们的磁盘上的目录结构已经被 IDEA 自动创建出来了;
5) 同时我们也看到了, 在新创建的 Test.java 文件的最上方, 就出现了一个 package 语句。
文件夹中:
2.导入包中的类
用package声明包,用 import 语句导入包。
Java 中已经提供了很多现成的类供我们使用,如:
1. java.lang:系统常用基础类(String、Object),此包从JDK1.1后自动导入。
2. java.lang.reflect:java 反射编程包;
3. java.net:进行网络编程开发包。
4. java.sql:进行数据库开发的支持包。
5. java.util:是java提供的工具程序包。(集合类等) 非常重要
6. java.io:I/O编程开发包
1、用 toString 输出数组的内容
以下两种写法相同:
写法一:用 import 语句导入包。
import java.util.Arrays;
public class Test {
public static void main(String[] args) {
int[] arr={1,2,3};
System.out.println(Arrays.toString(arr));
}
}
写法二:使用 java.util.Date 这种方式引入 java.util 这个包中的 Date 类.
public class Test {
public static void main(String[] args) {
int[] arr={1,2,3};
System.out.println(java.util.Arrays.toString(arr));
}
}
2、如果需要使用 java.util 中的其他类, 可以使用 import java.util.* 导入until中的全部包。但是我们更建议显式的指定要导入的类名. 否则还是容易出现冲突的情况,如下编译出错:
import java.util.*;
import java.sql.*;
public class Test {
public static void main(String[] args) {
// util 和 sql 中都存在一个 Date 这样的类, 此时就会出现歧义, 编译出错
Date date = new Date();
System.out.println(date.getTime());
}
}
// 编译出错
Error:(5, 9) java: 对Date的引用不明确
java.sql 中的类 java.sql.Date 和 java.util 中的类 java.util.Date 都匹配
在这种情况下需要使用完整的类名。
import java.util.*;//不在这改成import java.util.Date,其他地方可能用到的不止Date。
import java.sql.*;
public class Test {
public static void main(String[] args) {
java.util.Date date = new java.util.Date();//写完整类名
System.out.println(date.getTime());
}
}
3.将类放到包中
基本规则:
- 在文件的最上方加上一个 package 语句指定该代码在哪个包中;
- 包名需要尽量指定成唯一的名字, 通常会用公司的域名的颠倒形式;
- 包名要和代码路径相匹配. 例如创建 net.csdn.blog的包, 那么会存在一个对应的路径 net/csdn/blog 来存 储代码。
- 如果一个类没有 package 语句, 则该类被放到一个默认包中。
包的访问权限控制:
private 中的成员只能被类的内部使用,如果某个成员不包含 public 和 private 关键字, 此时这个成员可以在包内部的其他类使用, 但是不能在包外使用,也就是默认权限(default)。
- 对于同一个包:在net.csdn 下和 net.csdn.blog 下也不算在同一个包中;
如下: Test 和 Test1 在同一个包( net.csdn.blog)中,TestDemo不在; 在Test1中定义一个变量value(图一),在Test中可以使用(图二), 在TestDemo 中不可使用(图三),因为 value 在 net.csdn.blog.Test1 中不是公共的, 无法从外部程序包中对其进行访问)。
封装:将字段或者方法使用private进行修饰。其意义在于安全性,让类的调用者对类的使用成本降低。
继承(extends)
1、基本语法
class 子类 extends 父类 {
}
2、规则
1、A extends B A:父类、超类、基类 B:子类、派生类
2、使用 extends 指定父类:
- Java 中一个子类只能继承一个父类 (而C++/Python等语言支持多继承)。
- 子类会继承父类的所有 public 的字段和方法,除了构造方法。
- 对于父类的 private 的字段和方法, 子类可以继承但是无法访问的。
- 子类的实例中, 也包含着父类的实例,可以使用 super 关键字得到父类实例的引用。
- 对于父类的 private 的字段和方法, 子类中是无法访问的。
3、意义:代码的重复使用
4、什么时候把关系设置为继承?关系:A is a B.(Dog is a Animal.)
例:
class Animal{
public String name;
public String age;
public void eat(){
System.out.println("吃");
}
}
class Dog {
public String name;
public String age;
public void eat() {
System.out.println("吃");
}
}
class Bird {
public String name;
public String age;
public void eat() {
System.out.println("吃");
}
public void fly() {
System.out.println("飞");
}
}
public class Test {
public static void main(String[] args) {
Dog dog=new Dog();
dog.name="灰灰";
dog.eat();
Bird bird=new Bird();
bird.name="八哥";
bird.eat();
bird.fly();
}
}
//灰灰吃
八哥吃
八哥飞
运用继承后:
class Animal{
public String name;
public String age;
public void eat(){
System.out.println("吃");
}
}
class Dog extends Animal {
}
class Bird extends Animal {
public void fly() {
System.out.println("飞");
}
}
public class Test {
public static void main(String[] args) {
Dog dog=new Dog();
dog.name="灰灰";
dog.eat();
Bird bird=new Bird();
bird.name="八哥";
bird.eat();
bird.fly();
}
}
//灰灰吃
八哥吃
八哥飞
3、四种访问权限
Java 中对于字段和方法共有四种访问权限:
- private: 类内部能访问, 类外部不能访问
- 默认(也叫包访问权限): 类内部能访问, 同一个包中的类可以访问, 其他类不能访问.
- protected: 类内部能访问, 子类和同一个包中的类可以访问, 其他类不能访问.
- public : 类内部和类的调用者都能访问。
4、protected 关键字
如果把字段设为 private, 子类不能访问,但是设成 public, 又违背了我们 "封装" 的初衷。两全其美的办法就是 protected 关键字:
对于类的调用者来说, protected 修饰的字段和方法是不能访问的;
对于类的 子类 和 同一个包 的其他类 来说, protected 修饰的字段和方法是可以访问的。
用protected修饰的变量:
- 同一类可访问
- 同包不同类可访问
- 不同包需继承才可访问(如下示例)
Test1与TestDemo在不同的包中(看目录),Test1在 net.csdn.blog包下,TestDemo在src下,在Test1中 定义一个用protected修饰的变量val,当 TestDemo 继承 Test1时,通过super.val 是可以访问的。
5、final 关键字
final 关键字, 修饰一个变量或者字段的时候, 表示 常量 (不能修改)。
final 关键字也能修饰类, 此时表示被修饰的类就不能被继承。
final public class Animal {
...
}
public class Bird extends Animal {
...
}
// 编译出错
Error:(3, 27) java: 无法从最终com.bit.Animal进行继承
组合
1、组合
和继承类似, 组合也是一种表达类之间关系的方式, 也是能够达到代码重用的效果.例如表示一个学校:
public class Student {
...
}
public class Teacher {
...
}
public class School {
public Student[] students;
public Teacher[] teachers;
}
组合表示 has - a 语义 在刚才的例子中, 我们可以理解成一个学校中 "包含" 若干学生和教师.
继承表示 is - a 语义 在上面的 "动物和猫" 的例子中, 我们可以理解成一只猫也 "是" 一种动物
2、super 关键字
this代表当前对象的引用:
- this():调用自己的构造方法
- this.func():访问方法
- this.data:访问属性
1、super:父类对象的引用。
2、用法:
1. 使用了 super 来调用父类的构造器
- 子类继承父类,子类构造的时候,需要首先帮助父类进行构造。
- 怎么帮助父类构造?在子类的构造方法内部,调用父类的构造方法:super()//显式调用父类的构造方法。所以构造方法不是被继承的,二是在子类显式被调用的。
2.使用 super 来调用父类的普通方法
class Animal{
public String name;
public Animal(String name) {
this.name = name;
}
public void eat(String food){
}
}
class Bird extends Animal {
public Bird(String name) {
super(name);
}
@Override
public void eat(String food) {
// 修改代码, 让子调用父类的接口
super.eat(food);
System.out.println("我是一只小鸟");
System.out.println(this.name + "正在吃" + food);
}
}
public class TestDemo {
public static void main(String[] args) {
Bird bird=new Bird("Lucky");
bird.eat("baba");
}
}
//
我是一只小鸟
Lucky正在吃baba
1.子类构造首先帮助父类构造对象(从运行结果看出,是先帮助父类构造,然后子类构造)
class Animal{
public String name;
private int age;
//构造函数
public Animal(){//不含参数
super();//默认会有可以不写
System.out.println("父类构造(不带参数)");
}
public Animal(String name, int age) {//两个参数
this.name = name;
this.age = age;
System.out.println("Animal(String,int)");
}
}
class Dog extends Animal{
//构造方法
public Dog() {
super();//默认会有,可以不写
System.out.println("子类构造(不带参数)");
}
public Dog(String name, int age) {
super(name, age);
System.out.println("Dog(String,int)");
}
}
public class TestDemo {
public static void main(String[] args) {
Dog dog=new Dog();// 不带参数
}
}
//结果:
父类构造(不带参数)
子类构造(不带参数)
2.如何帮助?(通过super()调用父类的造方法)。
3.父类无构造方法,默认会有一个不带参数的构造方法,此时以下写法是正确的;
4.但是当父类的构造方法带有参数时,就不会默认生成不带有参数的构造方法,此时子类也不需要帮助父类构造不含参数的构造方法。
5.注:
- super()放在第一行!
- super不能在静态方法当中使用(super代表父类对象的引用,而静态的不依赖对象)
6、注意 super 和 this 功能相似, 但有区别。
7.执行顺序:静态的先执行且只执行一次;
class Animal{
public String name;
private int age;
static {
System.out.println("父类静态代码块");
}
{
System.out.println("父类实例代码块");
}
public Animal(){//构造方法
System.out.println("父类构造");
}
}
class Dog extends Animal{
static {
System.out.println("Dog静态代码块");
}
{
System.out.println("Dog实例代码块");
}
public Dog() {//构造方法
super();//默认会有,可以不写
System.out.println("Dog构造");
}
}
class Bird extends Animal{
static {
System.out.println("Bird静态代码块");
}
{
System.out.println("Bird实例代码块");
}
public Bird() {//构造方法
System.out.println("Bird构造");
}
}
public class TestDemo {
public static void main(String[] args) {
Dog dog=new Dog();
System.out.println("------------");
Bird brid=new Bird();
}
}
运行结果分析: