달력

4

« 2024/4 »

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
태그 클래스를 클래스 계층으로 변환하려면 태그 값에 따라 달라지는 각 메소드를 추상 메소드로 만들고

추상클래스를 정의한다.

태그 값에 관계없이 동작하는 메소드 는 추상 클래스에 포함한다.

만일 모든 종류의 인스턴스들이 사용하는 필드들이 있다면 그것들도 추상클래스에 넣자.

:
Posted by 유쾌한순례자
2010. 12. 12. 00:23

타입을 정의할 때만 인터페이스를 사용 Study/Java2010. 12. 12. 00:23

인터페이스는 참조하는데 사용될 수 있는 타입의 역할을 하는데 이외의 목적으로는 좋지않다.

소위 말하는 상수 인터페이스 등이 있는데 메소드를 갖지 않으며 외부에 제공하는 상수 값을 갖는 static final 필드 만으로.

ex)

interface Sangsu{
static final int A = 2;
static final int B = 3;
static final int C = 10;
}

문제점이 뭐가 있을까.

이 상수를 더 이상 사용할 필요가 없어서 클래스를 변경하더라도 바이너리 호환성 유지를 위해

여전히 인터페이스를 구현해야한다.

이럴 때는 상수 유틸리티 클래스(유형4) 로 구현하는게 좋다.

public class Sangsu{
private Sangsu(){
public static final A = 2;
public static final B = 3;
public satic final C = 10;
}
}

즉 인터페이스는 타입을 정의할 뿐이고 상수를 외부에 제공되기 위한 목적이 아니다.
:
Posted by 유쾌한순례자
2010. 12. 11. 23:28

인터페이스 Study/Java2010. 12. 11. 23:28

인터페이스란?

구현 된 것은 아무것도 없는 밑바탕만 있는 "기본 설계도" 라고 생각하면 된다.

인터페이스 작성방법
ex)
interface 인터페이스 이름{
//모든 멤버변수는 public static final 이어야 하고
//모든 메서드는 public abstract 이어야한다.
}
내가 기존에 알고 있던 인터페이스는 C++ 에는 있지만 자바에는 없는 다중 상속을 사용할 때

기존의 다중상속의 장점만을 취해서 하는 것이라고 생각했다.

(※자바의 정석 298page 에 보면 인터페이스가 단순히 다중 상속을 위한 것으로 오해를 사고는 하는데 공부를 하다보면 참된 의미를 알 것이라고 하였다.)

ex)
interface A{
..생략..
}
interface B{
..생략..
}
interface C extends A,B{
..생략..
}

인터페이스의 장점만을 적어보자면 (자바의 정석 page 303)

1. 개발 시간을 단축 : 메서드를 호출 하는 쪽에서는 메서드의 내용에 관계없이 선언부만 알면됨!
2. 표준화가 가능 : 기본틀을 인터페이스로 작성하여 일관화되고 정형화된 개발이 가능
3. 서로 관계없는 클래스들끼리 관계를 맺어 줌 : 하나의 인터페이스를 공통적으로 구현하도록 관계를 맺어줌.
4. 독립적인 프로그래밍 가능 : 선언과 구현을 분리시킬 수 있다.

문제 : (interface를 사용할것!)
온풍기 냉풍기 가 가능한 에어콘이 있다.
on 이라는 명령을 내리고 설정온도를 입력하면 25도 초과일때 Hot mode
25도 미만일때 Cold mode
25도 일때 Air Care mode
로 출력하게 하며
off 일때는 종료가 엉뚱한 명령어가 입력되거나 최대값 30도, 최저값 18도 범위 밖일 경우도 종료시켜라.

음. 내가 만든 문제는 아니고 어디선가 봤던 문제인듯.

(정답을 몰라서 일단 내 코딩을 등록해두고 과감히 평가받기)


import javax.swing.JOptionPane;
interface Airconable{
abstract void mode(int temp);
}

class Aircon{
private int max_temp = 30;
private int min_temp = 18;
void operate(String operate, int temp){
if(operate.equals("on")){
if(control(temp)){
System.out.println("작동중");
}
else{
System.exit(0);
}
}
else if(operate.equals("off")){
System.out.println("정지");
System.exit(0);
}
else{
System.out.println("잘못입력했습니다");
System.exit(0);
}
}
boolean control(int temp){
System.out.println(temp+"도로 설정되었습니다.");
if(temp > max_temp){
System.out.println("온도가 너무 높게 설정되었습니다."+"종료합니다.");
return false;
}
else if(temp<min_temp){
System.out.println("온도가 너무 낮게 설정되었습니다."+"종료합니다.");
return false;
}
else{
return true;
}
}
}

class SelectMode extends Aircon implements Airconable{
SelectMode(String operate, int temp){
super.operate(operate,temp);
mode(temp);
}
@Override
public void mode(int temp) {
if(temp>25){
System.out.println("HOT MODE");
}
else if(temp<25){
System.out.println("COLD MODE");
}
else{
System.out.println("AIR CORE MODE");
}
}
}
public class aircon2 {
public static void main(String args[]){
String oper = "";
String question = "";
int temp = 25;
oper = JOptionPane.showInputDialog("시작:on  ,    종료:off.");
if(oper.equals("on")){
question = JOptionPane.showInputDialog("온도를 입력하세요.");
temp = Integer.parseInt(question);
}
SelectMode sm = new SelectMode(oper, temp);
}
}
:
Posted by 유쾌한순례자

추상클래스로 정의된 타입을 구현하는 클래스는 반드시 추상 클래스의 서브 클래스가 되어야 한다.

인터페이스를 구현하는 클래스의 경우는 인터페이스에 정의된 모든 메소드를 구현하고 인터페이스 구현 계약을 지키면

되므로 클래스 상속계층과는 무관하다.

각각의 장점(?) 즉 외부에 공개된 중요한 인터페이스와 연관시킨 골격 구현 추상클래스를 제공하여 인터페이스와

추상 클래스의 장점을 결합한다.

골격 구현 클래스의 작성법은 다음과 같다.

우선 대상이 되는 인터페이스를 파악하고, 구현할 메소드와 그대로 둘 메소드를 결정한다

그대로 둘 메소드가 골격 구현 클래스의 추상 메소드가 될 것이다.

그다음 그대로 둘 메소드를 제외한 인터페이스의 나머지 모든 메소드를 구현한다.

다음의 예제를 한번 보면 좀 더 이해가 갈 것 같다.

public abstract class AbstractMapEntry<K,V> implements Map.Entry<K,V> {
public abstract K getKey();
public abstract V getValue();

public V setValue(V value){
throw new UnsupportedOperationException();
}

//기타 Map.Entry.equals 메소드에 약속된 보면적 계약은 생략...
}

음 여기 항목도 결론은 상황에 따라 추상 클래스와 인터페이스 중 잘 선택해서 쓰자 라는 것.

추상 클래스는  진화의 용이성 이 중요할 때

인터페이스는 유연성이 중요할 때  인 것 같다.

:
Posted by 유쾌한순례자
2010. 12. 9. 16:53

추상 클래스 Study/Java2010. 12. 9. 16:53

한마디로 " 설계서, 공통적인 양식 " 라고 생각하면 될 것 같다.

추상메서드는 선언부만 작성하고 구현부는 남겨둔다.(이러하기 때문에 미완성 메서드)

메서드의 내용이 상속받는 클래스에 따라 달라지기 때문에 실제내용은 상속받는 클래스에서 구현하도록 하는 것이다,

사용방법은 키워드 abstract 해서 쓰면 된다.

ex)

abstract class 클래스 명{
abstract void Test();
}

실제로 예제 정리

import javax.swing.*;
abstract class Work{
abstract void temp(int j);
}
class Mode extends Work{
@Override
void temp(int i) {
if(i<23){
System.out.println("Cold Mode");
}else{
System.out.println("Hot Mode");
}
}
}
public class aircon{
public static void main(String args[]){
String ques = "";
int temp = 26;
Work wk = new Mode();
ques = JOptionPane.showInputDialog("온도를 입력하세요");
temp = Integer.parseInt(ques);
wk.temp(temp);
}
}
}

다음은 JLS 의 abstract class 부분을 보자 (  JLS 8.1.1.1 abstract class 발췌 )


8.1.1.1 abstract Classes
An abstract class is a class that is incomplete, or to be considered incomplete.
Normal classes may have abstract methods (§8.4.3.1, §9.4), that is methods
that are declared but not yet implemented, only if they are abstract classes.
If a normal class that is not abstract contains an abstract method, then a compile-
time error occurs.
Enum types (§8.9) must not be declared abstract; doing so will result in a
compile-time error. It is a compile-time error for an enum type E to have an
abstract method m as a member unless E has one or more enum constants, and all
of E’s enum constants have class bodies that provide concrete implementations of
m. It is a compile-time error for the class body of an enum constant to declare an
abstract method.
A class C has abstract methods if any of the following is true:
• C explicitly contains a declaration of an abstract method (§8.4.3).
• Any of C’s superclasses has an abstract method and C neither declares nor
inherits a method that implements (§8.4.8.1) it.
• A direct superinterface (§8.1.5) of C declares or inherits a method (which is
therefore necessarily abstract) and C neither declares nor inherits a method
that implements it.
In the example:
abstract class Point {
int x = 1, y = 1;
void move(int dx, int dy) {
x += dx;
y += dy;
alert();
}
abstract void alert();
}
abstract class ColoredPoint extends Point {
int color;
}

class SimplePoint extends Point {
void alert() { }
}
a class Point is declared that must be declared abstract, because it contains a
declaration of an abstract method named alert. The subclass of Point named
ColoredPoint inherits the abstract method alert, so it must also be declared
abstract. On the other hand, the subclass of Point named SimplePoint provides
an implementation of alert, so it need not be abstract.
A compile-time error occurs if an attempt is made to create an instance of an
abstract class using a class instance creation expression (§15.9).
Thus, continuing the example just shown, the statement:
Point p = new Point();
would result in a compile-time error; the class Point cannot be instantiated
because it is abstract. However, a Point variable could correctly be initialized
with a reference to any subclass of Point, and the class SimplePoint is not
abstract, so the statement:
Point p = new SimplePoint();
would be correct.
A subclass of an abstract class that is not itself abstract may be instantiated,
resulting in the execution of a constructor for the abstract class and, therefore,
the execution of the field initializers for instance variables of that class. Thus,
in the example just given, instantiation of a SimplePoint causes the default constructor
and field initializers for x and y of Point to be executed.
It is a compile-time error to declare an abstract class type such that it is not
possible to create a subclass that implements all of its abstract methods. This
situation can occur if the class would have as members two abstract methods
that have the same method signature (§8.4.2) but incompatible return types.
As an example, the declarations:
interface Colorable { void setColor(int color); }
abstract class Colored implements Colorable {
abstract int setColor(int color);
}
result in a compile-time error: it would be impossible for any subclass of class
Colored to provide an implementation of a method named setColor, taking one
argument of type int, that can satisfy both abstract method specifications,
because the one in interface Colorable requires the same method to return no
value, while the one in class Colored requires the same method to return a value
of type int (§8.4).
A class type should be declared abstract only if the intent is that subclasses
can be created to complete the implementation. If the intent is simply to prevent
instantiation of a class, the proper way to express this is to declare a constructor
(§8.8.10) of no arguments, make it private, never invoke it, and declare no other
constructors. A class of this form usually contains class methods and variables.
The class Math is an example of a class that cannot be instantiated; its declaration
looks like this:
public final class Math {
private Math() { } // never instantiate this class
. . . declarations of class variables and methods . . .
}
:
Posted by 유쾌한순례자

일단 상속을 피해야하는 이유에 대해서 구글링과 책자를 찾아보았다.

일단 구글링 중에 무지 좋은 사이트 발견 http://www.javaworld.com/

그중에 Allen Holub 분의 Why extends is evil (왜 상속이 나쁠까) 라는 글을 발견

원문 : http://www.javaworld.com/javaworld/jw-08-2003/jw-0801-toolbox.html

일단 자세한건 주소로 들어가서 보고

핵심은

Losing Flexibility
Coupling
The fragile base-class problem
Framework
Summing up fragile base classes

이정도랄까.

(보면서 흥미로웠던건 아직 안봤던 GOF -Gang Of Four Design Pattern-  에서 인터페이스 상속을 지지한다고 한다.)

각각 내용은 나중에 따로 따로 블로깅 하기로 하고 슬슬 책 내용을 공부하자.

여기서 핵심은 요약 부분정리 ㅋ

상속은 강력하지만 캡슐화를 위배하므로 문제가 된다. 그리고 서브 클래스와 수퍼 클래스간에 진정한 서브 타입 관계가 있을 때만 적합하다. 만일 서브 클래스가 수퍼 클래스와 다른 패키지에 있고, 수퍼 클래스가 상속을 위해 설계된 것이 아니라면 상속은 서브 클래스를 허약하게 만들 수 있다.

그냥 이 항목 , 다음 항목은 상속에 대한 문제점을 분석하는게 낫겠다.

'Study > Java' 카테고리의 다른 글

태그 클래스보다는 클래스 계층을 사용하자  (0) 2010.12.12
타입을 정의할 때만 인터페이스를 사용  (0) 2010.12.12
인터페이스  (0) 2010.12.11
추상 클래스보다는 인터페이스를 사용하자  (0) 2010.12.09
추상 클래스  (0) 2010.12.09
상속  (0) 2010.12.08
이해안가던 자바퍼즐러6 Multicast  (0) 2010.12.08
[자바퍼즐러 3] 긴 나눗셈  (0) 2010.12.08
이진소수점 계산할 때..  (0) 2010.12.08
compareTo  (0) 2010.11.16
:
Posted by 유쾌한순례자
2010. 12. 8. 19:50

상속 Study/Java2010. 12. 8. 19:50

EJ2E 항목 16 가급적 상속 보다는 컴포지션을 사용하자 공부전에 상속 복습.

자바의 꽃이자 생명이라고 생각했던 상속.

자바의 정석 : 상속이란, 기존의 클래스를 재사용하여 새로운 클래스를 작성하는 것이다. 상속을 통해서 클래스를 작성하면, 보다 적은 양의 코드로 새로운 클래스를 작성할 수 있고 코드를 공통적으로 관리할 수 있기 때문에 코드의 추가 및 변경이 매우 용이하다.


즉 자식이 부모 꺼 쓸때 라고 생각하면 쉽다 -.-

쉽게 예제를 들어보고 밑에 JLS 부분을 적어둬야겠다.


class Car {
protected int carNum = 2011;
void name(){
System.out.println("택시입니다");
}
public class Taxi extends Car{
public static void main(String args[]){
Car car = new Car();
System.out.println(car.carNum);
car.name();
}
}

결과값
2011
택시입니다.

자식인 Taxi 에서 부모인 Car의 모든 것을 사용해보았다. 다음은 JLS 에서는 뭐라고 설명해놨나 발췌


8.1.4 Superclasses and Subclasses

The optional extends clause in a normal class declaration specifies the direct
superclass of the current class.
Super:
extends ClassType
The following is repeated from §4.3 to make the presentation here clearer:
ClassType:
TypeDeclSpecifier TypeArgumentsopt
A class is said to be a direct subclass of its direct superclass. The direct superclass
is the class from whose implementation the implementation of the current
class is derived. The direct superclass of an enum type E is Enum<E>. The
extends clause must not appear in the definition of the class Object, because it is
the primordial class and has no direct superclass.
Given a (possibly generic) class declaration for C<F1,...,Fn>, ,
, the direct superclass of the class type (§4.5) C<F1,...,Fn> is the type
given in the extends clause of the declaration of C if an extends clause is present,
or Object otherwise.
Let C<F1,...,Fn>, , be a generic class declaration. The direct superclass
of the parameterized class type C<T1,...,Tn> , where Ti, , is a type, is
D<U1 theta , ..., Uk theta>, where D<U1,...,Uk> is the direct superclass of
C<F1,...,Fn>, and theta is the substitution [F1 := T1, ..., Fn := Tn].
The ClassType must name an accessible (§6.6) class type, or a compile-time
error occurs. If the specified ClassType names a class that is final (§8.1.1.2),
then a compile-time error occurs; final classes are not allowed to have subclasses.
It is a compile-time error if the ClassType names the class Enum or any
invocation of it. If the TypeName is followed by any type arguments, it must be a
correct invocation of the type declaration denoted by TypeName, and none of the
type arguments may be wildcard type arguments, or a compile-time error occurs.
In the example:
class Point { int x, y; }
final class ColoredPoint extends Point { int color; }
class Colored3DPoint extends ColoredPoint { int z; } // error
the relationships are as follows:
• The class Point is a direct subclass of Object.
• The class Object is the direct superclass of the class Point.
• The class ColoredPoint is a direct subclass of class Point.
n ≥ 0
C ≠ Object
n > 0
1 ≤ i ≤ n

• The class Point is the direct superclass of class ColoredPoint.
The declaration of class Colored3dPoint causes a compile-time error because it
attempts to extend the final class ColoredPoint.
The subclass relationship is the transitive closure of the direct subclass relationship.
A class A is a subclass of class C if either of the following is true:
• A is the direct subclass of C.
• There exists a class B such that A is a subclass of B, and B is a subclass of C,
applying this definition recursively.
Class C is said to be a superclass of class A whenever A is a subclass of C.
In the example:
class Point { int x, y; }
class ColoredPoint extends Point { int color; }
final class Colored3dPoint extends ColoredPoint { int z; }
the relationships are as follows:
• The class Point is a superclass of class ColoredPoint.
• The class Point is a superclass of class Colored3dPoint.
• The class ColoredPoint is a subclass of class Point.
• The class ColoredPoint is a superclass of class Colored3dPoint.
• The class Colored3dPoint is a subclass of class ColoredPoint.
• The class Colored3dPoint is a subclass of class Point.
A class C directly depends on a type T if T is mentioned in the extends or implements
clause of C either as a superclass or superinterface, or as a qualifier of a
superclass or superinterface name. A class C depends on a reference type T if any
of the following conditions hold:
• C directly depends on T.
• C directly depends on an interface I that depends (§9.1.3) on T.
• C directly depends on a class D that depends on T (using this definition recursively).
It is a compile-time error if a class depends on itself.
For example:
class Point extends ColoredPoint { int x, y; }
class ColoredPoint extends Point { int color; }

causes a compile-time error.
If circularly declared classes are detected at run time, as classes are loaded
(§12.2), then a ClassCircularityError is thrown.

그 다음은 JLS (8.2.1 Example of Inheritance 총 발췌) 핵심사항 8.2.1.2 Inheritance with public and protected


8.2.1 Examples of Inheritance
This section illustrates inheritance of class members through several examples.
8.2.1.1 Example: Inheritance with Default Access
Consider the example where the points package declares two compilation units:
package points;
public class Point {
int x, y;
public void move(int dx, int dy) { x += dx; y += dy; }
}
and:
package points;
public class Point3d extends Point {
int z;
public void move(int dx, int dy, int dz) {
x += dx; y += dy; z += dz;
}
}
and a third compilation unit, in another package, is:
import points.Point3d;
class Point4d extends Point3d {
int w;
public void move(int dx, int dy, int dz, int dw) {
x += dx; y += dy; z += dz; w += dw; // compile-time errors
}
}
Here both classes in the points package compile. The class Point3d inherits the
fields x and y of class Point, because it is in the same package as Point. The
class Point4d, which is in a different package, does not inherit the fields x and y
of class Point or the field z of class Point3d, and so fails to compile.
A better way to write the third compilation unit would be:
import points.Point3d;
class Point4d extends Point3d {
int w;
public void move(int dx, int dy, int dz, int dw) {
super.move(dx, dy, dz); w += dw;
}
}
using the move method of the superclass Point3d to process dx, dy, and dz. If
Point4d is written in this way it will compile without errors.
8.2.1.2 Inheritance with public and protected
Given the class Point:
package points;
public class Point {
public int x, y;
protected int useCount = 0;
static protected int totalUseCount = 0;
public void move(int dx, int dy) {
x += dx; y += dy; useCount++; totalUseCount++;
}
}
the public and protected fields x, y, useCount and totalUseCount are inherited
in all subclasses of Point.
Therefore, this test program, in another package, can be compiled successfully:
class Test extends points.Point {
public void moveBack(int dx, int dy) {
x -= dx; y -= dy; useCount++; totalUseCount++;
}
}
8.2.1.3 Inheritance with private
In the example:
class Point {
int x, y;
void move(int dx, int dy) {
x += dx; y += dy; totalMoves++;
}
private static int totalMoves;
void printMoves() { System.out.println(totalMoves); }
}
class Point3d extends Point {
int z;
void move(int dx, int dy, int dz) {
super.move(dx, dy); z += dz; totalMoves++;
}
}
the class variable totalMoves can be used only within the class Point; it is not
inherited by the subclass Point3d. A compile-time error occurs because method
move of class Point3d tries to increment totalMoves.
8.2.1.4 Accessing Members of Inaccessible Classes
Even though a class might not be declared public, instances of the class might be
available at run time to code outside the package in which it is declared by means
a public superclass or superinterface. An instance of the class can be assigned to
a variable of such a public type. An invocation of a public method of the object
referred to by such a variable may invoke a method of the class if it implements or
overrides a method of the public superclass or superinterface. (In this situation,
the method is necessarily declared public, even though it is declared in a class
that is not public.)
Consider the compilation unit:
package points;
public class Point {
public int x, y;
public void move(int dx, int dy) {
x += dx; y += dy;
}
}
and another compilation unit of another package:
package morePoints;
class Point3d extends points.Point {
public int z;
public void move(int dx, int dy, int dz) {
super.move(dx, dy); z += dz;
}
public void move(int dx, int dy) {
move(dx, dy, 0);
}
}
public class OnePoint {
public static points.Point getOne() {
return new Point3d();
}
}
An invocation morePoints.OnePoint.getOne() in yet a third package would
return a Point3d that can be used as a Point, even though the type Point3d is
not available outside the package morePoints. The two argument version of
method move could then be invoked for that object, which is permissible because
method move of Point3d is public (as it must be, for any method that overrides a
public method must itself be public, precisely so that situations such as this will
work out correctly). The fields x and y of that object could also be accessed from
such a third package.
While the field z of class Point3d is public, it is not possible to access this
field from code outside the package morePoints, given only a reference to an
instance of class Point3d in a variable p of type Point. This is because the
expression p.z is not correct, as p has type Point and class Point has no field
named z; also, the expression ((Point3d)p).z is not correct, because the class
type Point3d cannot be referred to outside package morePoints.
The declaration of the field z as public is not useless, however. If there were
to be, in package morePoints, a public subclass Point4d of the class Point3d:
package morePoints;
public class Point4d extends Point3d {
public int w;
public void move(int dx, int dy, int dz, int dw) {
super.move(dx, dy, dz); w += dw;
}
}
then class Point4d would inherit the field z, which, being public, could then be
accessed by code in packages other than morePoints, through variables and
expressions of the public type Point4d.

중요한건 자식 부모간의 private 안되니까 protected 써! 이거인듯.

참고완료!

이제 항목16 가급적 컴포지션을 쓰라고 하는지 보러가야겠다.
:
Posted by 유쾌한순례자
2010. 12. 8. 11:39

이해안가던 자바퍼즐러6 Multicast Study/Java2010. 12. 8. 11:39

이해 안가서 차례대로 변환해봤다.

..생략..
System.out.println((byte)-1);
System.out.println((char)(byte)-1);
System.out.println((int)(char)(byte)-1);

결과

-1
?
65535

일단 int - > byte 타입은 축소기본타입변환인데.. 하위 8비트를 제외하고 모두 잘라낸다. <JLS 5.1.3>

<JLS 발췌>
5.1.3 Narrowing Primitive Conversions
The following 22 specific conversions on primitive types are called the narrowing
primitive conversions:
• short to byte or char
• char to byte or short
• int to byte, short, or char
• long to byte, short, char, or int
• float to byte, short, char, int, or long
• double to byte, short, char, int, long, or float
Narrowing conversions may lose information about the overall magnitude of a
numeric value and may also lose precision.
A narrowing conversion of a signed integer to an integral type T simply discards
all but the n lowest order bits, where n is the number of bits used to represent
type T. In addition to a possible loss of information about the magnitude of
the numeric value, this may cause the sign of the resulting value to differ from the
sign of the input value.
A narrowing conversion of a char to an integral type T likewise simply discards
all but the n lowest order bits, where n is the number of bits used to represent
type T. In addition to a possible loss of information about the magnitude of
the numeric value, this may cause the resulting value to be a negative number,
even though chars represent 16-bit unsigned integer values.
A narrowing conversion of a floating-point number to an integral type T takes
two steps:
1. In the first step, the floating-point number is converted either to a long, if T is
long, or to an int, if T is byte, short, char, or int, as follows:
◆ If the floating-point number is NaN (§4.2.3), the result of the first step of
the conversion is an int or long 0.
◆ Otherwise, if the floating-point number is not an infinity, the floating-point
value is rounded to an integer value V, rounding toward zero using IEEE
754 round-toward-zero mode (§4.2.3). Then there are two cases:
❖ If T is long, and this integer value can be represented as a long, then the
result of the first step is the long value V.
❖ Otherwise, if this integer value can be represented as an int, then the
result of the first step is the int value V.
◆ Otherwise, one of the following two cases must be true:
CONVERSIONS AND PROMOTIONS Narrowing Primitive Conversions 5.1.3
83
❖ The value must be too small (a negative value of large magnitude or negative
infinity), and the result of the first step is the smallest representable
value of type int or long.
❖ The value must be too large (a positive value of large magnitude or positive
infinity), and the result of the first step is the largest representable
value of type int or long.
2. In the second step:
◆ If T is int or long,the result of the conversion is the result of the first step.
◆ If T is byte, char, or short, the result of the conversion is the result of a
narrowing conversion to type T (§5.1.3) of the result of the first step.
The example:
class Test {
public static void main(String[] args) {
float fmin = Float.NEGATIVE_INFINITY;
float fmax = Float.POSITIVE_INFINITY;
System.out.println("long: " + (long)fmin +
".." + (long)fmax);
System.out.println("int: " + (int)fmin +
".." + (int)fmax);
System.out.println("short: " + (short)fmin +
".." + (short)fmax);
System.out.println("char: " + (int)(char)fmin +
".." + (int)(char)fmax);
System.out.println("byte: " + (byte)fmin +
".." + (byte)fmax);
}
}
produces the output:
long: -9223372036854775808..9223372036854775807
int: -2147483648..2147483647
short: 0..-1
char: 0..65535
byte: 0..-1

The results for char, int, and long are unsurprising, producing the minimum
and maximum representable values of the type.
The results for byte and short lose information about the sign and magnitude
of the numeric values and also lose precision. The results can be understood
by examining the low order bits of the minimum and maximum int. The minimum
int is, in hexadecimal, 0x80000000, and the maximum int is 0x7fffffff.
This explains the short results, which are the low 16 bits of these values, namely,

0x0000 and 0xffff; it explains the char results, which also are the low 16 bits of
these values, namely, '\u0000' and '\uffff'; and it explains the byte results,
which are the low 8 bits of these values, namely, 0x00 and 0xff.
Despite the fact that overflow, underflow, or other loss of information may
occur, narrowing conversions among primitive types never result in a run-time
exception (§11).
Here is a small test program that demonstrates a number of narrowing conversions
that lose information:
class Test {
public static void main(String[] args) {
// A narrowing of int to short loses high bits:
System.out.println("(short)0x12345678==0x" +
Integer.toHexString((short)0x12345678));
// A int value not fitting in byte changes sign and magnitude:
System.out.println("(byte)255==" + (byte)255);
// A float value too big to fit gives largest int value:
System.out.println("(int)1e20f==" + (int)1e20f);
// A NaN converted to int yields zero:
System.out.println("(int)NaN==" + (int)Float.NaN);
// A double value too large for float yields infinity:
System.out.println("(float)-1e100==" + (float)-1e100);
// A double value too small for float underflows to zero:
System.out.println("(float)1e-50==" + (float)1e-50);
}
}
This test program produces the following output:
(short)0x12345678==0x5678
(byte)255==-1
(int)1e20f==2147483647
(int)NaN==0
(float)-1e100==-Infinity
(float)1e-50==0.0

char 타입으로 음의 byte 타입 변환은 불가능..

음 이 예제는 아무리 봐도 핵심이 중요한것 같다 -..-

핵심 : 프로그램을 보는 것만으로는 프로그램이 무엇을 하는지 알 수 없다면 프로그램은 아마도 여러분이 원하는

작업을 하지 않을 것이다.

:
Posted by 유쾌한순례자
2010. 12. 8. 11:17

[자바퍼즐러 3] 긴 나눗셈 Study/Java2010. 12. 8. 11:17

핵심 : 큰 수를 다룰 때는 오버플로우에 주의.

..생략..
final long Micro = 24 * 60 * 60 * 1000 * 1000;
final long Millis = 24 * 60 * 60 * 1000;
System.out.println(Micro/Millis);

연산은 오로지 int로만 이루어지고 끝난후에 long 타입으로 확장된다.

int - > long 타입으로의 확장은 기본 타입 확장 변환 이다. (JLS 5.1.2)

<JLS 발췌>
5.1.2 Widening Primitive Conversion
The following 19 specific conversions on primitive types are called the widening
primitive conversions:
CONVERSIONS AND PROMOTIONS Widening Primitive Conversion 5.1.2

• byte to short, int, long, float, or double
• short to int, long, float, or double
• char to int, long, float, or double
• int to long, float, or double
• long to float or double
• float to double
Widening primitive conversions do not lose information about the overall
magnitude of a numeric value. Indeed, conversions widening from an integral type
to another integral type do not lose any information at all; the numeric value is
preserved exactly. Conversions widening from float to double in strictfp
expressions also preserve the numeric value exactly; however, such conversions
that are not strictfp may lose information about the overall magnitude of the
converted value.
Conversion of an int or a long value to float, or of a long value to double,
may result in loss of precision—that is, the result may lose some of the least significant
bits of the value. In this case, the resulting floating-point value will be a
correctly rounded version of the integer value, using IEEE 754 round-to-nearest
mode (§4.2.4).
A widening conversion of a signed integer value to an integral type T simply
sign-extends the two’s-complement representation of the integer value to fill the
wider format. A widening conversion of a char to an integral type T zero-extends
the representation of the char value to fill the wider format.
Despite the fact that loss of precision may occur, widening conversions
among primitive types never result in a run-time exception (§11).
Here is an example of a widening conversion that loses precision:
class Test {
public static void main(String[] args) {
int big = 1234567890;
float approx = big;
System.out.println(big - (int)approx);
}
}
which prints:
-46
thus indicating that information was lost during the conversion from type int to
type float because values of type float are not precise to nine significant digits.


수정은 간단하다. long 타입 상수를 이용하면 된다.

final long Micro = 24L * 60 * 60 * 1000 * 1000;
final long Mills = 24L * 60 * 60 * 1000;

뒷장에서 나오지만 Long 타입 리터럴 을 사용할 경우는 소문자가 아닌 대문자 L을 이용한다.

(1과 l 은 햇갈릴 수 있기 때문..)
:
Posted by 유쾌한순례자
2010. 12. 8. 11:08

이진소수점 계산할 때.. Study/Java2010. 12. 8. 11:08

자바퍼즐러 퍼즐2

결론 : 정확한 답을 요구하는 곳에서는 float 타입과 double 타입을 피하고 금전 계산에서는 int,long 또는 BigDecimal

을 사용할 것.

public class Change{
public static void main(String args[]){

System.out.println(new BigDecimal("2.00").subtract(new BigDecimal("1.10"));
}

위의 식에서 System.out.println(2.00 - 1.10) 을 그대로 할 경우 이진부동소수점 계산이 되기 때문에..

근사값으로 계산되기 때문에 BigDecimal을 이용함.

※ BigDecimal(double)이 아닌 BigDecimal(String) 생성자를 사용하자.
:
Posted by 유쾌한순례자