- •Объявление переменных в java
- •Ссылочные типы данных
- •Преобразования числовых типов
- •Приведение числовых типов
- •№21 Работа со строками
- •Коллекции объектов Java.
- •Integer — так называемый wrapper-класс (класс-обертка) для целых (int). Он использован потому, что в коллекцию нельзя занести данные элементарных типов, а только объекты классов.
- •Коллекции — это наборы произвольных объектов
Преобразования числовых типов
Часто возникает необходимость преобразовать один числовой тип в другой.
На рис. 3.1 показаны разрешенные преобразования.
Шесть черных стрелок на рис. 3.1 обозначают преобразования, которые выполняются без потери информации. Три серые стрелки означают преобразования, при которых может произойти потеря точности. Например, количество цифр в большом целом числе 123456789 превышает количество цифр, которое может быть представлено типом float. Число, преобразованное в тип float, имеет правильную величину, но несколько меньшую точность.
int n = 123456789; float f = n; // Число n равно 1.23456789268.
Рис. 3.1 Разрешенные преобразования числовых типов
Если два значения объединяются бинарным оператором (например n+f, где n — целое число, a f — число с плавающей точкой), то перед выполнением операции оба операнда преобразовываются в числа, имеющие одинаковый тип.
Если хотя бы один из операндов имеет тип double, то второй тоже преобразовывается в число типа double.
В противном случае, если хотя бы один из операндов имеет тип float, то второй тоже преобразовывается в число типа float. В противном случае, если хотя бы один из операндов имеет тип long, то второй тоже преобразовывается в число типа long. В противном случае оба операнда преобразовываются в числа типа int.
Приведение числовых типов
В предыдущем разделе мы видели, что при необходимости значения типа int автоматически преобразовываются в значения типа double. С другой стороны, есть несколько очевидных ситуаций, когда число типа double рассматривается как целое. Преобразования чисел в языке Java возможны, однако, разумеется, при этом может происходить потеря информации. Такие преобразования называютсяприведением типа (cast).
Синтаксически приведение типа задается парой скобок, внутри которых указывается желательный тип, а затем — имя переменной. Например, double х = 9.997; int nx = (int)x;
Теперь в результате приведения значения с плавающей точкой к целому типу переменная nх равна 9, поскольку при этом дробная часть числа отбрасывается.
Если нужно округлить число с плавающей точкой до ближайшего целого числа (что во многих случаях является намного более полезным), используется метод Math.round. double x = 9.997; int nx = (int) Math. round (x);
Теперь переменная nx равна 10. При вызове метода round по-прежнему нужно выполнять приведение поскольку возвращаемое им значение имеет тип long, и присвоить его переменной типа int можно лишь с помощью явного приведения.
При попытке привести число одного типа к другому результат может выйти за пределы допустимого диапазона. В этом случае результат будет усечен.
Например, выражение (byte) 300 равно 44. Поэтому рекомендуется явно проверять заранее, будет ли результат лежать в допустимом диапазоне после приведения типов.
Приведение между булевским и целыми типами невозможно. Это предотвращает появление ошибок. В редких случаях для того, чтобы привести булевское значение к числовому типу, можно использовать условное выражение b ? 1 : 0.
№11Классы Java
class Point { int х, у;
Point(int х, int у) {
this.x = х;
this. y = y;
}
double distance(int х, int у) {
int dx = this.x - х;
int dy = this.у - у;
return Math.sqrt(dx*dx + dy*dy);
}
double distance(Point p) {
return distance(p.x, p.y);
} }
class PointDist {
public static void main(String args[]) {
Point p1 = new Point(0, 0);
Point p2 = new Point(30, 40);
System.out.println("p1 = " + pi.x + ", " + p1.y);
System.out.println("p2 = " + p2.x + ", " + p2.y);
System.out.println("p1.distance(p2) = " + p1.distance(p2));
System.out.println("p1.distance(60, 80) = " + p1.distance(60, 80));
} }
№12 Конструкторы Java
class Point { int х, у; Point(int х, int у) { this.x = x; this.y = y; } } class PointCreate { public static void main(String args[]) { Point p = new Point(10,20); System.out.println("x = " + p.x + " у = " + p.y); }}
№13 Методы в Java
Метод — это именованный обособленный блок кода. С методом можно выполнить три операции. Объявить — описать, что такой метод есть, однако не расписывать его содержимое, т.е. тело; определить — описать метод с его структурой, т.е. с его телом; вызвать, т.е. запустить этот метод на выполнение. Объявление метода состоит из двух частей: заголовка метода и его тела. В заголовке метода указываются его модификаторы, имя метода и в скобках его параметры (аргументы). Тело метода располагается между двумя фигурными скобками и является блоком кода.
Рассмотрим следующие модификаторы.
• Модификаторы доступа — они уже подробно разбирались. • Модификаторы strictpf, static — они также уже рассматривались. • Abstract. Он предусматривает только объявление метода. Метод должен быть определен в классах-наследниках (подробнее об этом — в разделе "Наследование"). • Final. Методы не могут переопределяться в классах-наследниках (об этом подробнее см. в том же разделе). • Native. Если у метода есть такой модификатор, то данный метод написан на другом языке программирования (например, на языке С++). • Sinchronized— этот модификатор означает, что данный метод защищен от разрушения данных при попытке использования этих данных несколькими методами сразу.
Создадим теперь простой метод и вызовем его (листинг 4.5).
Листинг 4.5. Создание и вызов простого метода
У каждого метода в скобках можно помещать аргументы, или параметры. С помощью аргументов можно передать какие-либо значения методу, над которыми он будет работать. Если передавать методу ссылку (на объект, переменную и т.д.), то значение каких- либо свойств объекта могут измениться. Приведем пример использования методов с аргументами (листинг 4.6).
Листинг 4.6. Пример использования методов с аргументами
Заметим, что при задании ссылки в качестве аргумента значение свойств объекта меняется. Почему так? Дело в том, что передается ссылке, которая находится в аргументе метода, не ссылка как таковая, а сам объект и, следовательно, ссылка, являющаяся аргументом, выступает полноправной ссылкой на объект. И поэтому в методе можно изменять свойства того или иного объекта.
Ранее мы использовали параметр, являющийся массивом объектов String с именем args, который указывается в методе main. Если запускать программу из командной строки, то можно передать в программу несколько значений, которые последовательно будут записываться в элементы этого массива. Если это необходимо, можно получить к ним доступ, указывая соответствующие элементы массива.
Возможно также наличие следующего модификатора типа возвращаемого значения (мы уже указывали модификатор void, означающий то, что метод ничего не возвращает). Метод может возвращать какое-то одно значение. Чтобы метод возвращал значение, нужно указать модификатор типа значения, которое вы собираетесь возвращать, а в конце выполнения метода добавить return с переменной (или значением).
В листинге 4.7 представлен пример использования метода, имеющего модификатор типа возвращаемого значения.
Листинг 4.7. Пример использования метода, имеющего модификатор типа j возвращаемого значения
Перегруженные методы
Если два и более методов класса имеют одно имя, но их параметры не совпадают, то такие методы называют перегруженными. Примером перегруженных методов являются конструкторы. Пример в листинге 4.8.
Листинг 4.8. Пример перегруженных методов
№14Классы-шаблоны
шаблон класса
Параметры шаблона класса указываются в угловых скобках. Класс не может быть потомком класса Throwable. Если в С++ по шаблону класса создается именно новый класс, то в Java типы, созданные по одному шаблону, являются классом этого шаблона. Поэтому тип параметра нельзя использовать для определения статических членов или использовать в статических методах.
public class TstTpl<T> {
private T t;
public TstTpl(T tt) {
t = tt;
}
public void out() {
System.out.println("tplclass="+getClass()+
", param class=" + t.getClass() + ", val="
+ t.toString());
}
public static void main(String[] args) {
new TstTpl<Boolean>(true).out();
// сгенерированные типы принадлежат одному классу
TstTpl<Integer> a = new TstTpl<Integer>(1);
TstTpl<Double> b = new TstTpl<Double>(3.14);
System.out.println(a.getClass() == b.getClass());
}
}
№ 15 шаблон метода
Аналогичным образом в классе можно определить шаблонный метод.
public class TstTplm {
static <T1, T2> void outmerge(T1 t1, T2 t2) {
System.out.println(t1.toString() + t2);
}
public static void main(String[] args) {
outmerge(new Double(3.14),new Boolean(true));
}
}
№16 Методы с переменным числом параметров
Можно создавать методы с переменным числом параметров. В этом случае используется многоточие.
public static double getMaxValue(Object... args) {
// код
}
По сути, создаётся массив типа Object[].
Создадим метод, вычисляющий и возвращающий максимальное из произвольного количества значений.
public static double getMaxValue(double... values) {
double largest = Double.MIN_VALUE;
for(double v : values) {
if (v > largest) {
largest = v;
}
}
return largest;
}
№17 Наследование.
Наследование является неотъемлемой частью Java. При использовании наследования вы говорите: Этот новый класс похож на тот старый класс. В коде это пишется как extends, после которого указываете имя базового класса. Тем самым вы получаете доступ ко всем полям и методам базового класса. Используя наследование, можно создать общий класс, которые определяет характеристики, общие для набора связанных элементов. Затем вы можете наследоваться от него и создать новый класс, который будет иметь свои уникальные характеристики. Главный наследуемый класс в Java называют суперклассом. Наследующий класс называют подклассом. Получается, что подкласс - это специализированная версия суперкласса, которая наследует все члены суперкласса и добавляет свои собственные уникальные элементы. К примеру, в Android есть класс View и подкласс TextView.
Чтобы наследовать класс, достаточно вставить имя наследуемого класса с использованием ключевого слова extends:
public class MainActivity extends Activity {
}
В этом коде мы наследуемся от класса Activity и добавляем свой код, который будет отвечать за наше приложение.
Подкласс в свою очередь может быть суперклассом другого подкласса. Так например, упоминавший ранее класс TextViewявляется суперклассом для EditText.
В производный класс можно добавлять новые методы.
Для каждого создаваемого подкласса можно указывать только один суперкласс. При этом никакой класс не может быть собственным суперклассом.
Хотя подкласс включает в себя все члены своего суперкласса, он не может получить доступ к тем членам суперкласса, которые объявлены как private.
Помните, мы создавали класс Box для коробки кота. Давайте наследуемся от этого класса и создадим новый класс, который будет иметь не только размеры коробки, но и вес.
В том же файле Box.java после последней закрывающей скобки добавьте новый код:
class HeavyBox extends Box {
int weight; // вес коробки
// конструктор
HeavyBox(int w, int h, int d, int m) {
width = w;
height = h;
depth = d;
weight = m; // масса
}
}
Возвращаемся в главную активность и пишем код:
HeavyBox box = new HeavyBox(15, 10, 20, 5);
int vol = box.getVolume();
textInfo.setText("Объём коробки: " + vol + " Вес коробки: " + box.weight);
Обратите внимание, что мы вызываем метод getVolume(), который не прописывали в классе HeavyBox. Однако мы можем его использовать, так как мы наследовались от класса Box и нам доступны все открытые поля и методы. Заодно мы вычисляем вес коробки с помощью новой переменной, которую добавили в подкласс.
При желании вы можете создать множество разных классов на основе одного суперкласса. Например, мы можем создать цветную коробку.
class ColorBox extends Box {
int color; // цвет коробки
// конструктор
ColorBox(int w, int h, int d, int c) {
width = w;
height = h;
depth = d;
color = c; // цвет
}
}
№18 Полиморфизм
В данной статье мы рассмотрим полиморфизм. Он представляет собой один из краеугольных камней ООП. Суть полиморфизма заключается в том, что вы можете использовать наследников, как родителей. При этом, если в классе-наследнике был переопределен какой — то метод, то вызовется он. Рассмотрим простой пример. Пусть у нас есть некоторый класс Shape(фигура), в котором есть только один метод рисовать. Очевидно, что в классе Shape он ничего делать не будет, потому что не понятно, что собственно говоря надо отрисовать, какую фигуру:
1 2 3 4 5 |
public class Shape { public void draw() { //ничего не делаем } } |
После этого мы создаем различные классы-наследники: Square (квадрат), Сircle (круг) и Triangle:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
public class Square extends Shape { public void draw() { System.out.println("Квадрат"); } } public class Сircle extends Shape { public void draw() { System.out.println("Круг"); } } public class Triangle extends Shape { public void draw() { System.out.println("Треугольник"); } } |
Как вы могли заметить в наследниках у нас переопределен метод draw. Теперь увидим, в чем заключается удивительная возможность полиморфизма:
1 2 3 4 5 |
Shape[] a = new Shape[]{new Shape(), new Triangle(), new Square(), new Сircle()}; for(int i = 0; i < a.length; i++) { a[i].draw(); } |
Выведет: Треугольник Квадрат Круг Таким образом каждый класс наследник вызвал именно свой метод draw, вместо того, чтобы вызвать пустой метод draw из класса Shape. В следующих уроках мы поймем зачем может понадобится такой подход.
№19 Абстрактные классы
Абстрактным называется класс, на основе которого не могут создаваться объекты. При этом наследники класса могут быть не абстрактными, на их основе объекты создавать, соответсвенно, можно.
Для того, чтобы превратить класс в абстрактный перед его именем надо указать модификатор abstract.
Рассмотрим пример абстрактного класса A:
abstract class A { int p1; A() { p1 = 1; } void print() { System.out.println(p1); } } class B extends A { } public class Main { public static void main(String[] args) { A ob1; // ошибка: ob1 = new A(); B ob2 = new B(); // будет вызван конструктов по умолчанию из A ob2.print(); } }
Java разрешит описать конструкторы в классе A, но не разрешит ими воспользоваться (потому что запрещено создавать объекты абстрактного класса).
№20 Интерфейсы
Интерфейс это консутрукция языка программирования Java, в рамках которой могут описываться только абстрактные публичные (abstract public) методы и статические константyst свойства (final static). То есть также, как и на основе абстрактных классов, на основе интерфейсов нельзя порождать объекты.
Один интерфейс может быть наследником другого интерфейса.
Классы могут реализовывать интерфейсы (т. е. получать от интерфейса список методов и описывать реализацю каждого из них), притом, что особенно важно, один класс может реализовывать сразу несколько интерфейсов.
Перед описанием интерфейса указывается ключевое слово interface. Когда класс реализуемт интерфейс, то после его имени указывается ключевое слово implements и далее через запятую перечисляются имена тех интерфейсов, методы которых будут полностью описаны в классе.
Пример:
interface Instruments { final static String key = "До мажор"; public void play(); } class Drum implements Instruments { public void play() { System.out.println("бум бац бац бум бац бац"); } } class Guitar implements Instruments { public void play() { System.out.println("до ми соль до ре до"); } }
Поскольку все свойства интерфейса должны быть константными и статическими, а все методы общедоступными, то соответсвующие модификаторы перед свойствами и методами разрешается не указывать. То есть интерфейс можно было описать так:
interface Instruments { static public String key = "До мажор"; void play(); }
Но когда метод play() будет описываться в реализующем интерфейс классе, перед ним всё равно необходимо будет явно указать модификатор public.
